void TTeamMenuItem::ToggleExpandState(bool resizeWindow) { fExpanded = !fExpanded; if (fExpanded) { // Populate Menu() with the stuff from SubMenu(). TWindowMenu* sub = (static_cast<TWindowMenu*>(Submenu())); if (sub) { // force the menu to update it's contents. bool locked = sub->LockLooper(); // if locking the looper failed, the menu is just not visible sub->AttachedToWindow(); if (locked) sub->UnlockLooper(); if (sub->CountItems() > 1) { TExpandoMenuBar* parent = static_cast<TExpandoMenuBar*>(Menu()); int myindex = parent->IndexOf(this) + 1; TWindowMenuItem* windowItem = NULL; int childIndex = 0; int totalChildren = sub->CountItems() - 4; // hide, show, close, separator. for (; childIndex < totalChildren; childIndex++) { windowItem = static_cast<TWindowMenuItem*> (sub->RemoveItem((int32)0)); parent->AddItem(windowItem, myindex + childIndex); windowItem->ExpandedItem(true); } sub->SetExpanded(true, myindex + childIndex); if (resizeWindow) parent->SizeWindow(); } } } else { // Remove the goodies from the Menu() that should be in the SubMenu(); TWindowMenu* sub = static_cast<TWindowMenu*>(Submenu()); if (sub) { TExpandoMenuBar* parent = static_cast<TExpandoMenuBar*>(Menu()); TWindowMenuItem* windowItem = NULL; int childIndex = parent->IndexOf(this) + 1; while (!parent->SubmenuAt(childIndex) && childIndex < parent->CountItems()) { windowItem = static_cast<TWindowMenuItem*> (parent->RemoveItem(childIndex)); sub->AddItem(windowItem, 0); windowItem->ExpandedItem(false); } sub->SetExpanded(false, 0); if (resizeWindow) parent->SizeWindow(); } } }
void TExpandoMenuBar::BuildItems() { BMessenger self(this); TBarApp::Subscribe(self, &fTeamList); int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize(); desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings(); float itemWidth = -1.0f; if (fVertical) itemWidth = Frame().Width(); else { itemWidth = iconSize; if (!settings->hideLabels) itemWidth += gMinimumWindowWidth - kMinimumIconSize; else itemWidth += kIconPadding * 2; } float itemHeight = -1.0f; TeamMenuItemMap items; int32 itemCount = CountItems(); BList itemList(itemCount); for (int32 i = 0; i < itemCount; i++) { BMenuItem* menuItem = RemoveItem((int32)0); itemList.AddItem(menuItem); TTeamMenuItem* item = dynamic_cast<TTeamMenuItem*>(menuItem); if (item != NULL) items[BString(item->Signature()).ToLower()] = item; } if (settings->sortRunningApps) fTeamList.SortItems(TTeamMenu::CompareByName); int32 teamCount = fTeamList.CountItems(); for (int32 i = 0; i < teamCount; i++) { BarTeamInfo* barInfo = (BarTeamInfo*)fTeamList.ItemAt(i); TeamMenuItemMap::const_iterator iter = items.find(BString(barInfo->sig).ToLower()); if (iter == items.end()) { // new team TTeamMenuItem* item = new TTeamMenuItem(barInfo->teams, barInfo->icon, barInfo->name, barInfo->sig, itemWidth, itemHeight); if (settings->trackerAlwaysFirst && strcasecmp(barInfo->sig, kTrackerSignature) == 0) { AddItem(item, 0); } else AddItem(item); if (fFirstBuild && fVertical && settings->expandNewTeams) item->ToggleExpandState(true); } else { // existing team, update info and add it TTeamMenuItem* item = iter->second; item->SetIcon(barInfo->icon); item->SetOverrideWidth(itemWidth); item->SetOverrideHeight(itemHeight); if (settings->trackerAlwaysFirst && strcasecmp(barInfo->sig, kTrackerSignature) == 0) { AddItem(item, 0); } else AddItem(item); // add window items back int32 index = itemList.IndexOf(item); TWindowMenuItem* windowItem; TWindowMenu* submenu = dynamic_cast<TWindowMenu*>(item->Submenu()); bool hasWindowItems = false; while ((windowItem = dynamic_cast<TWindowMenuItem*>( (BMenuItem*)(itemList.ItemAt(++index)))) != NULL) { if (fVertical) AddItem(windowItem); else { delete windowItem; hasWindowItems = submenu != NULL; } } // unexpand if turn off show team expander if (fVertical && !settings->superExpando && item->IsExpanded()) item->ToggleExpandState(false); if (hasWindowItems) { // add (new) window items in submenu submenu->SetExpanded(false, 0); submenu->AttachedToWindow(); } } } if (CountItems() == 0) { // If we're empty, BMenuBar::AttachedToWindow() resizes us to some // weird value - we just override it again ResizeTo(itemWidth, 0); } fFirstBuild = false; }