diff --git a/bazaar/XMLMenu/WithXMLMenu.h b/bazaar/XMLMenu/WithXMLMenu.h index 30a385b1b..8a28f31ed 100644 --- a/bazaar/XMLMenu/WithXMLMenu.h +++ b/bazaar/XMLMenu/WithXMLMenu.h @@ -29,10 +29,10 @@ template class WithXMLMenu : public T, public XMLMenuInterface XMLToolBarFrame rightFrame; // the menu bars - Array menuBarCtrls; + ArrayMap menuBarCtrls; // toolbar controls storage area - Array toolBarCtrls; + ArrayMap toolBarCtrls; // flags stating allowed dock point and main menu bar bool dockTop, dockBottom, dockLeft, dockRight; @@ -93,6 +93,7 @@ template class WithXMLMenu : public T, public XMLMenuInterface void DragLoop(Point startP); // refresh menus and bars + void RefreshBarsDeep(void); void RefreshBars(void); // sync bars from ctrls @@ -151,7 +152,6 @@ template WithXMLMenu::WithXMLMenu() : leftFrame (TOOLBAR_LEFT), rightFrame (TOOLBAR_RIGHT) { -DLOG("XMLMenu : " << FormatHex(this)); // allows, by default, docking on 4 corners and embeds // main menu too dockTop = dockBottom = dockLeft = dockRight = true; @@ -175,34 +175,33 @@ template WithXMLMenu::~WithXMLMenu() template void WithXMLMenu::RefreshFrames(void) { // removes all frames -// T::ClearFrames(); T::RemoveFrame(topFrame); T::RemoveFrame(bottomFrame); T::RemoveFrame(leftFrame); T::RemoveFrame(rightFrame); - // add docking frames - if(dockTop) - T::InsertFrame(0, topFrame); - if(dockBottom) - T::InsertFrame(0, bottomFrame); - if(dockLeft) - T::InsertFrame(0, leftFrame); - if(dockRight) - T::InsertFrame(0, rightFrame); - // adds main menu + int iFrame = 0; if(mainMenu) { - int mainIdx = menuBars.Find("Main"); + int mainIdx = menuBarCtrls.Find("Main"); if(mainIdx >= 0) { MenuBar &bar = menuBarCtrls[mainIdx]; T::RemoveFrame(bar); - T::InsertFrame(0, bar); + T::InsertFrame(iFrame++, bar); } } + // add docking frames + if(dockTop) + T::InsertFrame(iFrame++, topFrame); + if(dockBottom) + T::InsertFrame(iFrame++, bottomFrame); + if(dockLeft) + T::InsertFrame(iFrame++, leftFrame); + if(dockRight) + T::InsertFrame(iFrame, rightFrame); } @@ -509,9 +508,9 @@ template void WithXMLMenu::SetToolBar0(Bar &bar, int tbIdx, Array void WithXMLMenu::RefreshBars(void) +template void WithXMLMenu::RefreshBarsDeep(void) { -// T::ClearFrames(); + // do a deep refresh, wiping all controls and recreating then T::RemoveFrame(topFrame); T::RemoveFrame(bottomFrame); T::RemoveFrame(leftFrame); @@ -523,7 +522,7 @@ template void WithXMLMenu::RefreshBars(void) menuBarCtrls.Clear(); for(int iBar = 0; iBar < menuBars.GetCount(); iBar++) { - menuBarCtrls.Add(new MenuBar); + menuBarCtrls.Add(menuBars.GetKey(iBar), new MenuBar); // workaround for main menu... without this one // it appears as a popup menu @@ -539,7 +538,7 @@ template void WithXMLMenu::RefreshBars(void) for(int iBar = 0; iBar < toolBars.GetCount(); iBar++) { XMLToolBar &toolBar = toolBars[iBar]; - toolBarCtrls.Add(new XMLToolBarCtrl(this)); + toolBarCtrls.Add(toolBars.GetKey(iBar), new XMLToolBarCtrl(this)); XMLToolBarCtrl &toolBarCtrl = toolBarCtrls.Top(); toolBarCtrls[iBar].Set(THISBACK1(SetToolBar, iBar)); Reposition(&toolBarCtrl, toolBar.GetState(), toolBar.GetPosition()); @@ -550,6 +549,72 @@ template void WithXMLMenu::RefreshBars(void) RefreshFrames(); } +template void WithXMLMenu::RefreshBars(void) +{ + // refactored logic for toolbar updates -- avoids unneeded + // screen redrawing and frame adding/removing + + // we shall first find if controls were added or removed + // in that case we proceed the old way, recalculating all frames + Vector const &ctrlNames = toolBarCtrls.GetKeys(); + bool deepUpdate = false; + for(int iName = 0; iName < ctrlNames.GetCount(); iName++) + { + if(toolBars.Find(ctrlNames[iName]) < 0) + { + deepUpdate = true; + break; + } + } + if(!deepUpdate) + { + Vector const &barNames = toolBars.GetKeys(); + for(int iName = 0; iName < barNames.GetCount(); iName++) + { + if(toolBarCtrls.Find(barNames[iName]) < 0) + { + deepUpdate = true; + break; + } + } + } + if(!deepUpdate) + { + Vector const &menuCtrlNames = menuBars.GetKeys(); + for(int iName = 0; iName < menuCtrlNames.GetCount(); iName++) + { + if(menuBars.Find(menuCtrlNames[iName]) < 0) + { + deepUpdate = true; + break; + } + } + } + if(!deepUpdate) + { + Vector const &menuNames = menuBars.GetKeys(); + for(int iName = 0; iName < menuNames.GetCount(); iName++) + { + if(menuBarCtrls.Find(menuNames[iName]) < 0) + { + deepUpdate = true; + break; + } + } + } + + if(deepUpdate) + RefreshBarsDeep(); + else + { + // do a smart refresh, just update controls inside menus and toolbars + for(int iBar = 0; iBar < menuBars.GetCount(); iBar++) + menuBarCtrls[iBar].Set(THISBACK1(SetMenuBar, iBar)); + for(int iBar = 0; iBar < toolBars.GetCount(); iBar++) + toolBarCtrls[iBar].Set(THISBACK1(SetToolBar, iBar)); + } +} + // sync bars from ctrls template void WithXMLMenu::SyncBars(void) { @@ -594,10 +659,7 @@ template void WithXMLMenu::SetToolBars(Callback1 tb) // gets a context menu by name -- NULL if none template MenuBar *WithXMLMenu::GetContextMenu(String const &name) { - int idx = menuBars.Find(name); - if(idx < 0) - return NULL; - return &menuBarCtrls[idx]; + return menuBarCtrls.FindPtr(name); } // xml support @@ -614,7 +676,7 @@ template void WithXMLMenu::Xmlize(XmlIO xml) // wait that top window is opened before refreshing toolbars // don't know if it's the right way, but..... if(xml.IsLoading()) - T::PostCallback(THISBACK(RefreshBars)); + T::PostCallback(THISBACK(RefreshBarsDeep)); } // toggles bar visibility