wjakob / nanogui

Minimalistic GUI library for OpenGL
Other
4.66k stars 608 forks source link

VScrollPanel still misbehaving? #140

Closed VirgiliuC closed 8 years ago

VirgiliuC commented 8 years ago

SOLVED!

I am trying to integrate VScrollPanel into a layout of widgets, but I still cannot get the expected behaviour. I know there were issues with it, but I understand a patch should have resolved the problems with children's layout inside of vscrollpanel.

The code I used:

/* The window*/
    auto window = new Window(screen, "VScrollPanel");
    window->setPosition(Vector2i(350, 405));
    window->setLayout(new BoxLayout(Orientation::Vertical,Alignment::Middle,5, 10));

/*Host for the desired layout*/
    auto dataViewList = new Widget(window);
    dataViewList->setLayout(new BoxLayout(Orientation::Vertical,Alignment::Fill));

/*First control in the layout*/
    auto dummy_button = new Button(dataViewList, "Dummy Button");

/*VScrollPanel - the second widget in the layout*/
    auto table = new GridLayout(/*dir*/Orientation::Horizontal, /*dir size*/4,
                              Alignment::Fill, /*margin*/3,/*spacing*/6);
    ref<VScrollPanel> scrollpanel = new VScrollPanel(dataViewList);
    scrollpanel->setLayout(table);
    scrollpanel->setFixedHeight(200);

/* Children of VScrollPanel, to be arranged and scrolled*/
    for (int i=0;  i< 16; i++) {
        auto label = new Label(scrollpanel,"Label ctrl");
        label->setFixedWidth(100);
        auto tb = new TextBox(scrollpanel, std::string("Textbox ctrl"));//'A'+(char)i));
        tb->setEditable(true);
        tb->setFixedWidth(100);
        auto combo = new ComboBox(scrollpanel, { "Combo box item 1", "Combo box item 2", "Combo box item 3"});
        combo->setEnabled(true);
        combo->setFixedWidth(100);
        auto ck = new CheckBox(scrollpanel,"Checkbox ctrl");
        ck->setChecked(i%2);
        ck->setFixedWidth(100);
    }

The result of above is: vscroll_orig

If I use a custom vscroll control which I created (just sandwiching vscrollpanel between two other widgets inside the c'tor of my ScrolledControl, I get what I expect (no other change of the code above): vscroll_custom

Can I kindly ask what am I doing wrong with vscollpanel, if its issues have been fixed, as I was told? I cannot see one in the examples provided. I am up-to-date with the lib, using Win32 with GCC 5.1.0 Thanks.

VirgiliuC commented 8 years ago

Forget it!

wjakob commented 8 years ago

Sorry, I didn't get to this yet -- any reasons for closing the ticket? Did it turn out not to be an issue after all?

VirgiliuC commented 8 years ago

Hi Wenzel.

No, the issue is still unclear, clearly it doesn't work for me (according to the code used). I closed it because I thought there is little/no interest in this regard, so I didn't want to clutter the space.

My fix is another minimal control, with just only a constructor added and nothing more, which sandwiches VScrollPanel between two ordinary widgets. The scrolling works fine, not the side popup for combobox though. The latter is not on my radar, as I plan to adapt a (new?) combo with the dropdown bit underneath the heading, as per usual behaviour.

Virgiliu

wjakob commented 8 years ago

Well, let's keep it open for a bit longer unless you have a different patch for this issue.

(I'm a starting professor at EPFL and generally super-busy, so it can sometimes take me quite a bit of time until I'm able to sit down and look through all the tickets/PRs for any of my projects.)

VirgiliuC commented 8 years ago

Great, let's keep it open for a while to see how it goes from the user base. I also closed a PR for the same reason; with no feedback I wasn't sure about right or wrong. For me, that simple fix does the job for v-scrolling, but it's not an elegant fix, I know. I would look deeper into the VScroll code and the more general framework, but my time, like yours, is very limited currently.

Btw, good luck with your professorship! :-)

VirgiliuC commented 8 years ago

Finally I had some time to look inside VScrollPanel, and I managed to sort out the problem described above. First, VSP is designed to take only ONE child (the Panel!), and nothing more - thing that I missed by not looking inside and being mislead by a previous post. So this explains the encountered behaviour. Also, I changed a bit the internal code for simplicity and a correct functionality, and - as a byproduct - the side popup windows (like from combos) appear now in the correct position alongside the scrolled control. If the triggering control is scrolled vertically, the popup follows it up and down, on the correct position! Ain't that cute?

Because I won't put forward a PR for this, here are the steps I took to correct this, in case anybody needs it.

VSP code change:

  1. DON'T scroll by translating the NVG graphics. Delete the line nvgTranslate in ::draw(ctx) that dose this pseudo-scrolling.
  2. Replace the line above with a call to 'performLayout(ctx)' (why do I need this?).
  3. Remove completely the functions 'mouseButtonEvent' and 'mouseMotionEvent'. Not needed anymore, as we'll perform a physical scroll in the next step.
  4. The new performLayout function for VSP is:
void VScrollPanel::performLayout(NVGcontext *ctx) {
    //don't use layout on  this widget
    mLayout = nullptr;
    Widget::performLayout(ctx);
    if (mChildren.empty())
        return;
    //confine this height to the available space from parent, if necessary
    if(mFixedSize.y() == 0.0 and mParent){
        //clip own height to parent, to let scrolling to kick in and do its job
        int pheight = mParent->height();
        mSize.y() =  std::min(mSize.y(), pheight - mPos.y());
    }
    Widget *child = mChildren[0];
    mChildPreferredHeight = child->preferredSize(ctx).y();
    //translate the child based on the current scroll shift
    child->setPosition(Vector2i(0, -mScroll*(mChildPreferredHeight - mSize.y())));
    child->setSize(Vector2i(mSize.x()-12, mChildPreferredHeight));
}

VSP usage:

  1. Don't add a Layout to VSP, keep it empty (null) in this regard ( see in the code above the mLayout=NULL).
  2. Put all the to-be-scrolled controls in one container (ordinary widget).
  3. Make the above container the only kid for VSP and...voila! (my out-of-the-box VScrollContainer encapsulates these 3 steps).

Note: one may notice a code block above if(mFixedSize.... That corrects a subtle general layout error induced by VSP. When the scroll panel goes into a parent with restricted vertical space (e.g. fixedHeight), it will not know about that and spill out of parent control. I added the missing scissors in Widget::draw(ctx) which clips this, but the VSP becomes "frozen-clipped" in that limited space, defying its role of scrolling its kids into the visible area. That's because physically it's fully extended and doesn't need scrolling. So it's of no use. That bit of code will adjust the height of VSP to the restricted space, forcing the scrolling mechanism to kick in and do the job that's paid for.

Virgiliu

wjakob commented 8 years ago

Thank you for looking into this. I've ported the main idea (translating the widget position instead of running nvgTranslate) and changed a few other things as well (no scroll bar displayed when there is nothing to scroll). This should hopefully resolve all problems.

VirgiliuC commented 8 years ago

Thanks Wenzel. Actually, I did the 'no scroll bar' when not needed as well in my version, looks neater. Sorry, I didn't put a PR for this as my version (branch) has other developments needed for my projects (should have created more branches though).

VirgiliuC commented 5 months ago

Hi

This is a very old issue, never used this GUI in an actual product, and never further developed or sync'ed this 8-year old code. If you wish the VScrollPanel code as I did it at that time, give me an email address where to send it.

Regards

On 30/04/2024 15:57 BST augustinlss @.***> wrote:

Hey @VirgiliuC https://github.com/VirgiliuC, do you mind sharing the implementation you mention here:

"If I use a custom vscroll control which I created (just sandwiching vscrollpanel between two other widgets inside the c'tor of my ScrolledControl, I get what I expect (no other change of the code above):"

I modified vscrollpanel as you advised but im still getting the same result

Screenshot.2024-04-30.at.4.56.08.PM.png (view on web) https://github.com/wjakob/nanogui/assets/132910284/50a8b905-8884-467b-be5f-e0d3dff66a4b

Any help would be appreciated!

— Reply to this email directly, view it on GitHub https://github.com/wjakob/nanogui/issues/140#issuecomment-2085568501, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEAYZ4WFRSVQIMOHDRT5VG3Y76WNNAVCNFSM4CQ2KS52U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TEMBYGU2TMOBVGAYQ. You are receiving this because you were mentioned.Message ID: @.***>