Reduce number of allocations for menu creation

Every time either the Slit menu or the Toolbar menu were added to the
root menu, the whole root menu was (re)created from scratch. Now we
create and remove only the menus needed.

Side effect: the position of these menus is now at the end of the root
menu and not somewhere in between. If users complaint, I' ll think about
it.
This commit is contained in:
Mathias Gumz 2015-01-16 08:36:49 +01:00
parent bd9afcafb9
commit b495878065
4 changed files with 44 additions and 23 deletions

View file

@ -91,6 +91,12 @@ Menu* s_focused = 0; // holds currently focused menu
Menu* Menu::shownMenu() { return s_shown; }
Menu* Menu::focused() { return s_focused; }
void Menu::hideShownMenu() {
if (s_shown)
s_shown->hide();
}
Menu::Menu(FbTk::ThemeProxy<MenuTheme> &tm, ImageControl &imgctrl):
m_theme(tm),
m_parent(0),
@ -240,6 +246,18 @@ int Menu::insertItem(MenuItem *item, int pos) {
return m_items.size();
}
int Menu::findSubmenuIndex(const FbTk::Menu* submenu) const {
size_t i;
for (i = 0; i < m_items.size(); i++) {
if (m_items[i]->submenu() == submenu) {
return i;
}
}
return -1;
}
void Menu::fixMenuItemIndices() {
for (size_t i = 0; i < m_items.size(); i++)
m_items[i]->setIndex(i);
@ -1391,9 +1409,5 @@ void Menu::drawLine(int index, int size){
item->drawLine(m_frame, theme(), size, item_x, item_y, m_item_w);
}
void Menu::hideShownMenu() {
if (s_shown)
s_shown->hide();
}
} // end namespace FbTk

View file

@ -45,6 +45,12 @@ template <typename T> class RefCount;
/// Base class for menus
class Menu: public FbTk::EventHandler, FbTk::FbWindowRenderer {
public:
static Menu* shownMenu();
static Menu* focused();
static void hideShownMenu();
enum Alignment{ ALIGNDONTCARE = 1, ALIGNTOP, ALIGNBOTTOM };
enum { RIGHT = 1, LEFT };
@ -134,11 +140,13 @@ public:
FbTk::ThemeProxy<MenuTheme> &theme() { return m_theme; }
const FbTk::ThemeProxy<MenuTheme> &theme() const { return m_theme; }
unsigned char alpha() const { return theme()->alpha(); }
static Menu* shownMenu();
static Menu* focused();
static void hideShownMenu();
const MenuItem *find(size_t i) const { return m_items[i]; }
MenuItem *find(size_t i) { return m_items[i]; }
// returns index of 'submenu', it it is in the top most list of
// menu items. -1 if no match is found
int findSubmenuIndex(const Menu* submenu) const;
//@}
/// @return true if index is valid
bool validIndex(int index) const { return (index < static_cast<int>(numberOfItems()) && index >= 0); }

View file

@ -1362,22 +1362,25 @@ void BScreen::rereadWindowMenu() {
}
void BScreen::addConfigMenu(const FbTk::FbString &label, FbTk::Menu &menu) {
m_configmenu_list.push_back(make_pair(label, &menu));
if (m_configmenu.get())
setupConfigmenu(*m_configmenu.get());
FbTk::Menu* cm = m_configmenu.get();
if (cm) {
int pos = cm->findSubmenuIndex(&menu);
if (pos == -1) { // not found? add
cm->insertSubmenu(label, &menu, pos);
}
}
}
void BScreen::removeConfigMenu(FbTk::Menu &menu) {
Configmenus::iterator erase_it = find_if(m_configmenu_list.begin(),
m_configmenu_list.end(),
FbTk::Compose(bind2nd(equal_to<FbTk::Menu *>(), &menu),
FbTk::Select2nd<Configmenus::value_type>()));
if (erase_it != m_configmenu_list.end())
m_configmenu_list.erase(erase_it);
if (!isShuttingdown() && m_configmenu.get())
setupConfigmenu(*m_configmenu.get());
FbTk::Menu* cm = m_configmenu.get();
if (cm) {
int pos = cm->findSubmenuIndex(&menu);
if (pos > -1) {
cm->remove(pos);
}
}
}

View file

@ -501,10 +501,6 @@ private:
ExtraMenus m_extramenus;
typedef std::list<std::pair<FbTk::FbString, FbTk::Menu *> > Configmenus;
Configmenus m_configmenu_list;
Icons m_icon_list;
std::auto_ptr<Slit> m_slit;