wxAuiToolBar‘s overflow function cannot work as expected, when as pane in wxAuiManager, on GTK.
当增加一个AuiToolBar到一个auimanager之后,如果想用它的overflow feature,在gtk平台,无法工作。 WHY?
1) 首先查看wxAuiToolBar的OnSize函数做了些什么事情:
void wxAuiToolBar:: OnSize(wxSizeEvent & WXUNUSED (evt)) { int x , y; GetClientSize(&x , &y); if (x > y) SetOrientation(wxHORIZONTAL ); else SetOrientation(wxVERTICAL ); if (((x >= y) && m_absolute_min_size .x > x) || (( y > x ) && m_absolute_min_size.y > y)) { // hide all flexible items size_t i , count; for (i = 0, count = m_items.GetCount (); i < count; ++i ) { wxAuiToolBarItem& item = m_items. Item(i ); if (item .sizer_item && item.proportion > 0 && item .sizer_item-> IsShown()) { item.sizer_item ->Show( false); item.sizer_item ->SetProportion(0); } } } else { // show all flexible items size_t i , count; for (i = 0, count = m_items.GetCount (); i < count; ++i ) { wxAuiToolBarItem& item = m_items. Item(i ); if (item .sizer_item && item.proportion > 0 && !item .sizer_item-> IsShown()) { item.sizer_item ->Show( true); item.sizer_item ->SetProportion( item.proportion ); } } } m_sizer->SetDimension (0, 0, x, y); Refresh(false ); Update(); }
可以看到函数对一些tool button做了show/hide设置。
然后设置断点,跟踪每次size时, x/y计算出来的值是多少。发现它始终就没变过,不管如何resize那个toolbar
2) 不从ClientSize里面获取x/y值,从evt参数中拿值。看下上层代码是如何给它值。发现下面函数触发OnSize函数调用:
void wxAuiToolBar:: DoSetSize(int x, int y , int width , int height , int sizeFlags ) { wxSize parent_size = GetParent()-> GetClientSize(); if (x + width > parent_size.x ) width = wxMax (0, parent_size. x - x ); if (y + height > parent_size.y ) height = wxMax (0, parent_size. y - y ); wxWindow::DoSetSize (x, y, width , height, sizeFlags); }
跟踪发现width/height确实是更改过的值,但是在wxWindow::DoSetSize函数中,但是gtk版本的DoSetSize函数(src/gtk/window.cpp: 2712行),对width/height进行了进一步的处理。在函数最后处理size事件
2829 if (!m_nativeSizeEvent) 2830 { 2831 wxSizeEvent event( wxSize(m_width,m_height), GetId() ); 2832 event.SetEventObject( this ); 2833 GetEventHandler()->ProcessEvent( event ); 2834 }
跟踪发现m_width/m_height,确实在函数内部以下代码段中更改了。
2744 int minWidth = GetMinWidth(), 2745 minHeight = GetMinHeight(), 2746 maxWidth = GetMaxWidth(), 2747 maxHeight = GetMaxHeight(); 2748 2749 if ((minWidth != -1) && (m_width < minWidth )) m_width = minWidth; 2750 if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight; 2751 if ((maxWidth != -1) && (m_width > maxWidth )) m_width = maxWidth; 2752 if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
GetMinWidth函数调用GetMinSize函数获取widht。跟踪发现这个minsize失踪是toolbar最初显示出来的size。我们并没有设置它的minsize啊?是谁在其间调用了SetMinSize函数设置其值了?
3) GDB断点跟踪发现,在auimanager的Update函数中调用了Sizer的SetItemMinSize函数,进而调用了toolbar的SetMinSize函数:
1658 void wxAuiManager::LayoutAddPane(wxSizer* cont, 1659 wxAuiDockInfo& dock, 1660 wxAuiPaneInfo& pane, 1661 wxAuiDockUIPartArray& uiparts, 1662 bool spacer_only) ... 1779 // determine if the pane should have a minimum size; if the pane is 1780 // non-resizable (fixed) then we must set a minimum size. Alternatively, 1781 // if the pane.min_size is set, we must use that value as well 1782 1783 wxSize min_size = pane.min_size; 1784 if (pane.IsFixed()) 1785 { 1786 if (min_size == wxDefaultSize) 1787 { 1788 min_size = pane.best_size; 1789 pane_proportion = 0; 1790 } 1791 } 1792 1793 if (min_size != wxDefaultSize) 1794 { 1795 vert_pane_sizer->SetItemMinSize( 1796 vert_pane_sizer->GetChildren().GetCount()-1, 1797 min_size.x, min_size.y); 1798 }
我们的toolbar是一个fixed的pane,开始时并没有设置它的min size,所以1788行将会设置为best size,而best size将会是初始化时的size。这样1795行将会被调用到,而且是以best size的值来调用。
4) 找到根源之后,如何修改?
最简单的方式是在auimanager.AddPane调用增加toolbar时,设置它的minsize为一个tool button的size。这个size可以从toolbar提供的接口获取到。
wxAuiToolBar的overflow cannot work on GTK 解决方法,布布扣,bubuko.com
wxAuiToolBar的overflow cannot work on GTK 解决方法
原文:http://my.oschina.net/zeroli/blog/290641