wxScrolled<> and minSize

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
fantomas
In need of some credit
In need of some credit
Posts: 4
Joined: Fri Jun 15, 2018 10:44 pm

wxScrolled<> and minSize

Post by fantomas »

I use wxWidget 3.0.2 from Debian stable distro. I have not tried the latest updates yet but I have looked through changelists of 3.0.3, 3.0.4 and I did not noticed anything about wxScroll or min-size fixes there.

Anyway I don't know if this strange behaviour is by design for some reason or it is a kind of bug. May be I just do know where the right way lies.

I am trying to implement simple layout inside mainwindow frame. Picture (1) on attached image.
I want to get sidebar on the left with controls. It may contain lots of controls, and I want it to be vertically scrollable if needed (vscrollbar should appear when window is resized or when more controls added from program). Sidebar is of some fixed width or it can gain a little more space when mainwindow frame is too wide, "fixed width" should be calculated automatically by sizer or based on the auto-calculated value.
The main part of frame should contain canvas (of some size) with painting on the panel, panel has to be scrollable if canvas does not fit the viewport.


There are some macro-vars defined for the following source that allows to compile different versions of program.

1. If source is compiled as is, wxPanel is used as a sidebar holder, everything with sidebar and general layout is ok (but no scrollbars and no scrolling), sizer does its work as expected. Picture (2).

2. If source is compiled with -D USE_SCROLLED, wxScrolled<wxPanel> is used in place of simple wxPanel, but... nothing changes. No scrollbar appear even if I resize frame to minimum with a mouse.

3. If source is compiled with both -D USE_SCROLLED and -D USE_SCROLLRATE, calls to ->SetScrollRate(1, 1) are added to both sidebar wxScrolled-panel and mainview wxScrolled-panel. Voila, now scrollbars appear on resize - as needed, excellent. But... layout is broken. Picture (3).
Look, I asked for vertical scrollbar only in case of sidebar. So far I expect that in connection to horizontal sizing it would behave like an usual panel, like it was with simple not-scrollable wxPanel. I expect wxScrolled-panel should use certain minimal size of its child panel if that was set, or it should use "optimal" size of its child panel calculated by sizer and use that width to set one's own width to fit around child (horizontally). But instead wxScrolled assumes its child width is 0 or so... or maybe the width of vertical scrollbar is taken by wxScrolled as its minimal horizontal size.

4. Macro var USE_MINSIZE added. SetMinSize() calls added for:
- sidebar panel (not wxScrolled-panel but to its child, I expect scroller (not scrollable in this direction) must respect it, but it does not)
- to maincanvas wxScrolled-panel, I expect this would prevent viewport panel from minimizing to ugly mess (as on picture (5)).
Nothing changed, layout is still broken.
wxScrolled with sizer set completely ignores child widget's "best size" and min-size for its not-scrollable direction and does not fit around child unlike wxPanel does.
wxScrolled completely drops(?) min-size set to its viewport scrollable direction - it allows parent sizer to scale itself to zero. Min-client-size set to wxScrolled's not-scrollable direction works partially (see below).

5. Macro var USE_MINSIZE removed and USE_MINSIZE_2 added (-D USE_SCROLLED -D USE_SCROLLRATE -D USE_MINSIZE_2).
Now I try to transfer by hand the calculated by wx "best size.width" of scrollbar panel to its parent scroller client-min-size.
Almost good. Layout is ok. All scrollbars appear and disappear as expected. The only bad thing is that when sidebar's scrollbar appears, it eats some horizonal space and sidebar panel with controls does not fit its scroller area anymore, right edge of controls is hidden under scrollbar when scrollbar appears. Picture (4).
What do I expect? I expect that the wxScrolled, when vscrollbar has to appear and needs space, will "push" edge between sidebar and mainarea to right (well, actually it is sizer/layout manager who adjusts layout) to get space for vscrollbar.
I will try to imitate this behaviour programmatically, but it is not too easy and I'm afraid solution may be not too reliable. Unfortunately I do not see special events on scrollbar appear/disappear to use them as a signal to start recalculation of layout.

6. Macro USE_EVTHANDLER added (-D USE_SCROLLED -D USE_SCROLLRATE -D USE_MINSIZE_2 -D USE_EVTHANDLER).
So what the handleSizeEvent() code does? It does crazy thing. When it sees that wxScrolled failed to respect client area min-size the scroller was told to guarantee, event handler insist on this and tells wxScrolled to respect (quite the same) min-size once more. That fixes layout. Imperfectly, as size event is arised when layout had already become broken, so changes come in two steps: at first broken at second fixed.

What is possible else?

7. Macro var USE_MINSIZE_2 replaced with USE_MINSIZE_3 (-D USE_SCROLLED -D USE_SCROLLRATE -D USE_MINSIZE_3).
Now I reserve 20 pixel more space for scroller than child panel needs. Now there is empty space on right edge of panel and scrollbar takes it when it appears.

Or:
8. Macro var USE_MINSIZE_3A added (-D USE_SCROLLED -D USE_SCROLLRATE -D USE_MINSIZE_3 -D USE_MINSIZE_3A).
Additionally wxEXPAND is passed to scroller sizer, now sidebar panel takes 20 extra pixels initially and squeezes back when scrollbar appears but still fits inside scroller viewport.

So far I do not know a way how to implement (without handcrafted hooks like that insistent eventhandler) behaviour I mentioned above: when scrollbar's appearance makes wxScrolled to increment its outer size (in not-scrollable direction, instead of eating inner viewport space that promised to respect child's min-size requirement). But with some handcraft I at least can get satisfying results.
But I expected it to work out of the box: replace wxPanel with wxScrolled<wxPanel>, add it to the parent window's sizer, set own sizer for wxScrolled object and that's it. Unfortunately not true.


By the way I want to say there is one more topic I would be glad to find more information upon. It is handling of tab, shift+tab, up/down arrow keys by wxPanel. AFAIK in Java Swing and in Javascript browser DOM systems key/mouse input events do complex path there: from topwindow root they go up to target widget and then go down back to topwindow if not "consumed" on some stage, so far every parent window can intercept and handle incoming events before they reach target child widget. Wx docs say events start their trip from target widget (well, after optional filtering on app-level), so parent widget have no possibility to intercept... so far how is tab/shift+tab/up/down handling implemented? I suspect wxControl-family widgets "by contract" prefilter and propagate special key events to parent widget... or do not do it in case control was constructed with wxWANTS_CHARS? and call to .Navigate() may be used by programmer in subclasses to propagate special key events to parent panel if he wants to?
It would be great if someone is so kind to shed some light of knowledge into this fog of mistery. Unfortunately events overview from doc keeps this in secret, API doc keeps underlying class undocumented by intention.

Code: Select all

  
  #include <iostream>

  #include <wx/app.h>
  #include <wx/window.h>
  #include <wx/frame.h>
  #include <wx/event.h>
  #include <wx/panel.h>
  #include <wx/string.h>  
  #include <wx/textctrl.h>
  #include <wx/sizer.h>  
  #include <wx/scrolwin.h>  
  #include <wx/stattext.h>  
  //  #include <wx/.h>  
  //  #include <wx/.h>  


  
  class MyApp : public wxApp
  {
      
    public:

      MyApp(void) ;
      virtual  bool OnInit(void) ;
  } ;


  
  class MainWindow : public wxFrame  {
    
    public:
      explicit MainWindow(void) ;
      
#ifdef USE_EVTHANDLER  
      void handleSizeEvent(wxEvent&) ;
#endif      
    protected:

      wxWindow* buildSideBar(wxWindow* p_parentwnd) ;
    private:
#ifdef USE_EVTHANDLER  
      wxWindow* _p_scroller ;
      wxWindow* _p_sidebar ;
      int _minsize ;
#endif      
  } ;
  

  
  wxIMPLEMENT_APP(MyApp) ;



  MyApp::MyApp(void)
    : wxApp()
  {
    return ;
  }
  
  

  bool MyApp::OnInit(void)  {
    bool retv = false ;
    if (wxApp::OnInit())  {
      wxWindow* p_mainwnd = new MainWindow() ;
      this->SetTopWindow(p_mainwnd) ;
      p_mainwnd->Show(true) ;
      retv = true ;
    }
    return  retv ;
  }
  
  

  MainWindow::MainWindow(void)
    : wxFrame(NULL, wxID_ANY, "Test Scrolled+MinSize")
  {
    wxBoxSizer* const p_lm_root = new wxBoxSizer(wxHORIZONTAL) ;
    this->SetSizer(p_lm_root) ;

    
    //  sidebar
#ifndef USE_SCROLLED
    wxPanel* p_scroller = new wxPanel(this, wxID_ANY) ;
#else
    wxScrolled<wxPanel>* const p_scroller
        = new wxScrolled<wxPanel>(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, (wxVSCROLL)) ;
#endif

#ifdef USE_SCROLLRATE
    p_scroller->SetScrollRate(1, 1) ; 
#endif
    
    p_lm_root->Add(p_scroller, 1, (wxEXPAND)) ;
    
    wxBoxSizer* const p_lm_scroller = new wxBoxSizer(wxVERTICAL) ;
    p_scroller->SetSizer(p_lm_scroller) ;
    
    wxWindow* const p_sidebar = this->buildSideBar(p_scroller) ;
    
#ifndef USE_MINSIZE_3A
    p_lm_scroller->Add(p_sidebar, 1) ;
#else
    p_lm_scroller->Add(p_sidebar, 1, (wxEXPAND)) ;
#endif

    
#ifdef USE_MINSIZE_2
    {
      const int sidebar_w = p_sidebar->GetBestSize().GetWidth() ;
      const wxSize size(sidebar_w, wxDefaultCoord) ;
      std::cerr << "D: Sidebar scroller minsize.width set to: " << sidebar_w << std::endl ;
      p_scroller->SetMinClientSize(size) ;
      _minsize = sidebar_w ;
    }
#endif
    
#ifdef USE_MINSIZE_3
    {
      const int sidebar_w = (p_sidebar->GetBestSize().GetWidth() + 20);  // reserve 20 pixels more for vscrollbar
      const wxSize size(sidebar_w, wxDefaultCoord) ;
      std::cerr << "D: Sidebar scroller minsize.width set to: " << sidebar_w << std::endl ;
      p_scroller->SetMinClientSize(size) ;
    }
#endif

#ifdef USE_EVTHANDLER  
    _p_scroller = p_scroller ;
    _p_sidebar = p_sidebar ;
    this->Bind(wxEVT_SIZE, & MainWindow::handleSizeEvent, this) ;
#endif    


    
    //  mainarea
    wxScrolled<wxWindow>* const p_mainpanel = new wxScrolled<wxWindow>(this, wxID_ANY) ;
    
#ifdef USE_SCROLLRATE
    p_mainpanel->SetScrollRate(1, 1) ;  // Scrolled is like Panel or Window if this is comment out!!!
#endif

#ifdef USE_MINSIZE
    p_mainpanel->SetMinSize(wxSize(100, 100)) ;
#endif
    
    p_lm_root->Add(p_mainpanel, 8, (wxEXPAND)) ;
    wxBoxSizer* const p_lm_mainpanel = new wxBoxSizer(wxVERTICAL) ;
    p_mainpanel->SetSizer(p_lm_mainpanel) ;
    
    wxWindow* const p_mainview = new wxWindow(p_mainpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, (wxBORDER_RAISED)) ;
    p_mainview->SetMinClientSize(wxSize(300, 200)) ;
    p_lm_mainpanel->Add(p_mainview, 0) ;

    return ;
  }



  wxWindow* MainWindow::buildSideBar(wxWindow* const p_parentwnd)  {
    wxPanel* p_root = new wxPanel(p_parentwnd, wxID_ANY) ;
    wxBoxSizer* p_lm_root = new wxBoxSizer(wxVERTICAL) ;
    p_root->SetSizer(p_lm_root) ;

    {
      wxStaticText* p_text1 = new wxStaticText(p_root, wxID_ANY, wxT("Sample static text")) ;
      wxTextCtrl* p_tc1 = new wxTextCtrl(p_root, wxID_ANY, wxT("Input text here")) ;
      
      p_lm_root->Add(p_text1, 0, (wxEXPAND | wxALL), 4) ;
      p_lm_root->Add(p_tc1, 0, (wxEXPAND | wxALL), 4) ;
    }

    {
      wxStaticText* p_text1 = new wxStaticText(p_root, wxID_ANY, wxT("Sample static text")) ;
      wxTextCtrl* p_tc1 = new wxTextCtrl(p_root, wxID_ANY, wxT("Input text here")) ;
      
      p_lm_root->Add(p_text1, 0, (wxEXPAND | wxALL), 4) ;
      p_lm_root->Add(p_tc1, 0, (wxEXPAND | wxALL), 4) ;
    }

    {
      wxStaticText* p_text1 = new wxStaticText(p_root, wxID_ANY, wxT("Sample static text")) ;
      wxTextCtrl* p_tc1 = new wxTextCtrl(p_root, wxID_ANY, wxT("Input text here")) ;
      
      p_lm_root->Add(p_text1, 0, (wxEXPAND | wxALL), 4) ;
      p_lm_root->Add(p_tc1, 0, (wxEXPAND | wxALL), 4) ;
    }

    {
      wxStaticText* p_text1 = new wxStaticText(p_root, wxID_ANY, wxT("Sample static text")) ;
      wxTextCtrl* p_tc1 = new wxTextCtrl(p_root, wxID_ANY, wxT("Input text here")) ;
      
      p_lm_root->Add(p_text1, 0, (wxEXPAND | wxALL), 4) ;
      p_lm_root->Add(p_tc1, 0, (wxEXPAND | wxALL), 4) ;
    }

    
#ifdef USE_MINSIZE
    p_root->SetMinSize(wxSize(200, wxDefaultCoord)) ;
#endif
    return  p_root ;
  }

  

#ifdef USE_EVTHANDLER  
  void MainWindow::handleSizeEvent(wxEvent& evt)  {
    const int current_size = _p_scroller->GetClientSize().GetWidth() ;
    std::cerr << "D: required clientarea minsize: " << _minsize << ", current clientarea size: " << current_size << std::endl ;
    if (current_size != _minsize)  {
      std::cerr << "D: Adjusting layout" << std::endl ;
      const wxSize size(_minsize, wxDefaultCoord) ;
      std::cerr << "D: Setting sidebar scroller's client area min-width to: " << _minsize << std::endl ;
      _p_scroller->SetMinClientSize(size) ;
    }
    evt.Skip() ;
    return ;
  }
#endif

Attachments
test_scrolled.png
test_scrolled.png (61.87 KiB) Viewed 1224 times
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxScrolled<> and minSize

Post by doublemax »

That's a lot of text :)

I won't go into any detail, just some general hints.

1) Settings a min-size for a child window is only obeyed by the sizer layout. It will not automatically restrict resizing of the outer frame by the user. If the user makes the frame too small, the sizer will not be able to fulfill the minimum sizes of all controls and the layout will be broken in one way or another. Therefore you can use wxWindow::SetSizerAndFit() (or some related metod) for the outmost sizer which will set a minimum size for the frame as well.

2) Using a scrolled window for static controls is usually not a good idea. It's better to restrict the size of the outer frame in a way that all controls are always visible.

3) There is no easy solution regarding the appearing/disappearing of a scrollbar and what to do with the available space. Therefore, if you can't fulfill 2) and have to put controls in a scrolled window, i would put the scrolled window into a wxSplitterWindow so that the user can resize the window himself. So, if the user has to work on a small screen and a scrollbar appears and covers some of the controls, he can just make it a little wider himself. In this case it's important that your app saves these settings, so that the user doesn't have to do it every time the app starts.

Regarding the keyboard navigation: There is a default keyboard handler in wxWindow which will call wxWindow::Navigate(). But i don't see any check for arrow keys in there, so it's possible that this is handled by the underlying OS automatically (not sure about this, just a guess)
Use the source, Luke!
fantomas
In need of some credit
In need of some credit
Posts: 4
Joined: Fri Jun 15, 2018 10:44 pm

Re: wxScrolled<> and minSize

Post by fantomas »

doublemax wrote:That's a lot of text
Yeah... I dont like it too. But I hoped a colour picture makes it look more appealing. :D
doublemax wrote:If the user makes the frame too small, the sizer will not be able to fulfill the minimum sizes of all controls and the layout will be broken in one way or another.
I understand. I just expected view to be scaled down to minimum and stop, then frame may cut it like it cuts (not squeezes) images... Ok, it is mostly "decorative" matter, I now noticed there is also squeezed last textctrl on picture (2), after all it may be just GTK decision to squeeze not cut widgets.
doublemax wrote:Using a scrolled window for static controls is usually not a good idea. It's better to restrict the size of the outer frame in a way that all controls are always visible.
I expect them not fit the screen. Actually it is a kind of enlarged "property sheet" widely used in various RADs/IDEs, but more flexible and comfortable (property sheets surely are not).
doublemax wrote:There is no easy solution regarding
Ok, I will try to emphasize something. It is mostly library design and logic related question.
When I decide to replace properly set up and working panel with scrolled panel I (stupid programmer) may expect that:
a) everything works out of the box, only difference is scrolling appears where content earlier was squeezed or cut.
- Not true, I have to call SetScrollRate() additionally instead of relying on some reasonable default value I can change if I want.
b) in direction where I do not request scrolling scrollable panel should behave like normal panel, this means sizers that I setup with wxPanel have to do their work with wxScrolled<wxPanel> similarly. Not true again, sizer behaves buggy and I see no way to make it work without hook code - compare pictures (2) and (3), wxPanel vs wxScrolled<wxPanel>.

I think if sizer in b) worked as I expected, issue with scrollbar eating inner space could be resolved automatically by working sizer.

Thank you.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxScrolled<> and minSize

Post by doublemax »

I expect them not fit the screen. Actually it is a kind of enlarged "property sheet" widely used in various RADs/IDEs, but more flexible and comfortable (property sheets surely are not).
In that case i would just always show the scrollbar.
I think if sizer in b) worked as I expected, issue with scrollbar eating inner space could be resolved automatically by working sizer.
You may think that's a bug, but that's how it is. You either have to live with it or work around it.
Use the source, Luke!
fantomas
In need of some credit
In need of some credit
Posts: 4
Joined: Fri Jun 15, 2018 10:44 pm

Re: wxScrolled<> and minSize

Post by fantomas »

doublemax wrote:that's how it is
I see, thanks.

But do anybody know a reason why when panel is scrollable in one direction boxsizer stops to do its job in another direction (picture 2 vs 3), while that may be easily fixed by handcrafted transfer of size value from child to scroller after both are created - isn't it what the sizer exist for?
(I know, I am boring... :roll: )
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxScrolled<> and minSize

Post by doublemax »

I played a little with your code. I removed a few things i didn't understand.

The size handler is a little messy and is not perfect as the size of the side panel changes once the scrollbar has been visible for the first time.

I also colored some panels for the test, so i could see better what's going on.

Code: Select all

  #include <wx/wx.h>

  #include <wx/app.h>
  #include <wx/window.h>
  #include <wx/frame.h>
  #include <wx/event.h>
  #include <wx/panel.h>
  #include <wx/string.h> 
  #include <wx/textctrl.h>
  #include <wx/sizer.h> 
  #include <wx/scrolwin.h> 
  #include <wx/stattext.h> 
  
#include <iostream>

#define USE_SCROLLED
#define USE_SCROLLRATE
#define USE_EVTHANDLER
 
  class MyApp : public wxApp
  {
     
    public:

      MyApp(void) ;
      virtual  bool OnInit(void) ;
  } ;
 
  class MainWindow : public wxFrame  {
   
    public:
      explicit MainWindow(void) ;
     
#ifdef USE_EVTHANDLER 
      void handleSizeEvent(wxEvent&) ;
#endif     
    protected:

      void buildSideBar(wxWindow* p_parentwnd) ;
    private:
#ifdef USE_EVTHANDLER 
      wxWindow* _p_scroller ;
      //wxWindow* _p_sidebar ;
      int _minsize ;
#endif     
  } ;
 
  wxIMPLEMENT_APP(MyApp) ;

  MyApp::MyApp(void)
    : wxApp()
  {
    return ;
  }
 
 

  bool MyApp::OnInit(void)  {
    bool retv = false ;
    if (wxApp::OnInit())  {
      wxWindow* p_mainwnd = new MainWindow() ;
      this->SetTopWindow(p_mainwnd) ;
      p_mainwnd->Show(true) ;
      retv = true ;
    }
    return  retv ;
  }
 
 

  MainWindow::MainWindow(void)
    : wxFrame(NULL, wxID_ANY, "Test Scrolled+MinSize")
  {
    wxBoxSizer* const p_lm_root = new wxBoxSizer(wxHORIZONTAL) ;
    this->SetSizer(p_lm_root) ;
   
    //  sidebar
#ifndef USE_SCROLLED
    wxPanel* p_scroller = new wxPanel(this, wxID_ANY) ;
#else
    wxScrolled<wxPanel>* const p_scroller = new wxScrolled<wxPanel>(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, (wxVSCROLL /* |wxALWAYS_SHOW_SB */ )) ;
    p_scroller->SetBackgroundColour(*wxRED);
#endif

#ifdef USE_SCROLLRATE
    p_scroller->SetScrollRate(15, 15) ;
#endif
   
    p_lm_root->Add(p_scroller, 0, (wxEXPAND)) ;
   
    buildSideBar(p_scroller) ;
   
    //  mainarea
    wxScrolled<wxWindow>* const p_mainpanel = new wxScrolled<wxWindow>(this, wxID_ANY) ;
    p_mainpanel->SetBackgroundColour(*wxGREEN);
   
#ifdef USE_SCROLLRATE
    p_mainpanel->SetScrollRate(1, 1) ;  // Scrolled is like Panel or Window if this is comment out!!!
    p_mainpanel->SetMinSize(wxSize(100, 100)) ;
#endif

    p_lm_root->Add(p_mainpanel, 1, (wxEXPAND)) ;
    wxBoxSizer* const p_lm_mainpanel = new wxBoxSizer(wxVERTICAL) ;
    p_mainpanel->SetSizer(p_lm_mainpanel) ;
   
    wxWindow* const p_mainview = new wxWindow(p_mainpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, (wxBORDER_RAISED)) ;
    p_mainview->SetMinClientSize(wxSize(300, 200)) ;
    p_lm_mainpanel->Add(p_mainview, 0) ;

#ifdef USE_EVTHANDLER 
    _p_scroller = p_scroller ;
    this->Bind(wxEVT_SIZE, & MainWindow::handleSizeEvent, this) ;
#endif    

    return ;
  }



  void MainWindow::buildSideBar(wxWindow* const p_parentwnd)  {
    wxBoxSizer* p_lm_root = new wxBoxSizer(wxVERTICAL) ;
    p_parentwnd->SetSizer(p_lm_root) ;

    {
      wxStaticText* p_text1 = new wxStaticText(p_parentwnd, wxID_ANY, wxT("Sample static text")) ;
      wxTextCtrl* p_tc1 = new wxTextCtrl(p_parentwnd, wxID_ANY, wxT("Input text here")) ;
     
      p_lm_root->Add(p_text1, 0, (wxEXPAND | wxALL), 4) ;
      p_lm_root->Add(p_tc1, 0, (wxEXPAND | wxALL), 4) ;
    }

    {
      wxStaticText* p_text1 = new wxStaticText(p_parentwnd, wxID_ANY, wxT("Sample static text")) ;
      wxTextCtrl* p_tc1 = new wxTextCtrl(p_parentwnd, wxID_ANY, wxT("Input text here")) ;
     
      p_lm_root->Add(p_text1, 0, (wxEXPAND | wxALL), 4) ;
      p_lm_root->Add(p_tc1, 0, (wxEXPAND | wxALL), 4) ;
    }

    {
      wxStaticText* p_text1 = new wxStaticText(p_parentwnd, wxID_ANY, wxT("Sample static text")) ;
      wxTextCtrl* p_tc1 = new wxTextCtrl(p_parentwnd, wxID_ANY, wxT("Input text here")) ;
     
      p_lm_root->Add(p_text1, 0, (wxEXPAND | wxALL), 4) ;
      p_lm_root->Add(p_tc1, 0, (wxEXPAND | wxALL), 4) ;
    }

    {
      wxStaticText* p_text1 = new wxStaticText(p_parentwnd, wxID_ANY, wxT("Sample static text")) ;
      wxTextCtrl* p_tc1 = new wxTextCtrl(p_parentwnd, wxID_ANY, wxT("Input text here")) ;
     
      p_lm_root->Add(p_text1, 0, (wxEXPAND | wxALL), 4) ;
      p_lm_root->Add(p_tc1, 0, (wxEXPAND | wxALL), 4) ;
    }

    p_lm_root->SetSizeHints( p_parentwnd );
   
#ifdef USE_MINSIZE
    p_root->SetMinSize(wxSize(200, wxDefaultCoord)) ;
#endif
  }

 

#ifdef USE_EVTHANDLER 
  void MainWindow::handleSizeEvent(wxEvent& evt)  {
    const int current_size = _p_scroller->GetClientSize().GetWidth();
    wxSize best_size = _p_scroller->GetSizer()->CalcMin();
    if( _p_scroller->HasScrollbar(wxVERTICAL) )
      best_size.x += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X );

    wxLogDebug("onsize: act=%d best=%d", current_size, best_size.x );
    if( best_size.x > current_size )
    {
     _p_scroller->SetMinClientSize( best_size );
     wxGetTopLevelParent(_p_scroller)->Layout();
    }
    evt.Skip() ;
  }
#endif
Use the source, Luke!
Post Reply