diff options
Diffstat (limited to 'indra/newview/llsidetray.cpp')
-rw-r--r-- | indra/newview/llsidetray.cpp | 623 |
1 files changed, 493 insertions, 130 deletions
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 85b6e0dec4..631b244785 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -32,6 +32,8 @@ #include "llappviewer.h" #include "llbottomtray.h" #include "llfloaterreg.h" +#include "llfirstuse.h" +#include "llhints.h" #include "llsidetray.h" #include "llviewerwindow.h" #include "llaccordionctrl.h" @@ -49,6 +51,10 @@ #include "llwindow.h"//for SetCursor #include "lltransientfloatermgr.h" +#include "llsidepanelappearance.h" + +#include "llsidetraylistener.h" + //#include "llscrollcontainer.h" using namespace std; @@ -57,6 +63,8 @@ using namespace LLNotificationsUI; static LLRootViewRegistry::Register<LLSideTray> t1("side_tray"); static LLDefaultChildRegistry::Register<LLSideTrayTab> t2("sidetray_tab"); +static const S32 BOTTOM_BAR_PAD = 5; + static const std::string COLLAPSED_NAME = "<<"; static const std::string EXPANDED_NAME = ">>"; @@ -65,6 +73,8 @@ static const std::string TAB_PANEL_CAPTION_TITLE_BOX = "sidetray_tab_title"; LLSideTray* LLSideTray::sInstance = 0; +static LLSideTrayListener sSideTrayListener(LLSideTray::getInstance); + // static LLSideTray* LLSideTray::getInstance() { @@ -90,6 +100,7 @@ bool LLSideTray::instanceCreated () class LLSideTrayTab: public LLPanel { + LOG_CLASS(LLSideTrayTab); friend class LLUICtrlFactory; friend class LLSideTray; public: @@ -112,6 +123,10 @@ public: protected: LLSideTrayTab(const Params& params); + void dock(LLFloater* floater_tab); + void undock(LLFloater* floater_tab); + + LLSideTray* getSideTray(); public: virtual ~LLSideTrayTab(); @@ -128,8 +143,12 @@ public: const std::string& getTabTitle() const { return mTabTitle;} void onOpen (const LLSD& key); + + void toggleTabDocked(bool toggle_floater = true); + void setDocked(bool dock); + bool isDocked() const; - void toggleTabDocked(); + BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); LLPanel *getPanel(); private: @@ -149,8 +168,6 @@ LLSideTrayTab::LLSideTrayTab(const Params& p) mDescription(p.description), mMainPanel(NULL) { - // Necessary for focus movement among child controls - setFocusRoot(TRUE); } LLSideTrayTab::~LLSideTrayTab() @@ -176,7 +193,8 @@ BOOL LLSideTrayTab::postBuild() title_panel->getChild<LLTextBox>(TAB_PANEL_CAPTION_TITLE_BOX)->setValue(mTabTitle); - getChild<LLButton>("dock")->setCommitCallback(boost::bind(&LLSideTrayTab::toggleTabDocked, this)); + getChild<LLButton>("undock")->setCommitCallback(boost::bind(&LLSideTrayTab::setDocked, this, false)); + getChild<LLButton>("dock")->setCommitCallback(boost::bind(&LLSideTrayTab::setDocked, this, true)); return true; } @@ -210,64 +228,207 @@ void LLSideTrayTab::onOpen (const LLSD& key) panel->onOpen(key); } -void LLSideTrayTab::toggleTabDocked() +// Attempts to get the existing side tray instance. +// Needed to avoid recursive calls of LLSideTray::getInstance(). +LLSideTray* LLSideTrayTab::getSideTray() +{ + // First, check if the side tray is our parent (i.e. we're attached). + LLSideTray* side_tray = dynamic_cast<LLSideTray*>(getParent()); + if (!side_tray) + { + // Detached? Ok, check if the instance exists at all/ + if (LLSideTray::instanceCreated()) + { + side_tray = LLSideTray::getInstance(); + } + else + { + llerrs << "No safe way to get the side tray instance" << llendl; + } + } + + return side_tray; +} + +void LLSideTrayTab::toggleTabDocked(bool toggle_floater /* = true */) { - LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", LLSD().with("name", mTabTitle)); + // *FIX: Calling this method twice per frame would crash the viewer. + + std::string tab_name = getName(); + + LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab_name); if (!floater_tab) return; - LLFloaterReg::toggleInstance("side_bar_tab", LLSD().with("name", mTabTitle)); + bool docking = !isDocked(); - LLSideTray* side_tray = LLSideTray::getInstance(); + // Hide the "Tear Off" button when a tab gets undocked + // and show "Dock" button instead. + getChild<LLButton>("undock")->setVisible(docking); + getChild<LLButton>("dock")->setVisible(!docking); - if (LLFloater::isShown(floater_tab)) + if (docking) { - // Remove the tab from Side Tray's tabs list. - // We have to do it despite removing the tab from Side Tray's child view tree - // by addChild(). Otherwise the tab could be accessed by the pointer in LLSideTray::mTabs. - if (!side_tray->removeTab(this)) - { - llwarns << "Failed to remove tab " << getName() << " from side tray" << llendl; - return; - } + dock(floater_tab); + } + else + { + undock(floater_tab); + } + + // Open/close the floater *after* we reparent the tab panel, + // so that it doesn't receive redundant visibility change notifications. + if (toggle_floater) + { + LLFloaterReg::toggleInstance("side_bar_tab", tab_name); + } +} + +// Same as toggleTabDocked() apart from making sure that we do exactly what we want. +void LLSideTrayTab::setDocked(bool dock) +{ + if (isDocked() == dock) + { + llwarns << "Tab " << getName() << " is already " << (dock ? "docked" : "undocked") << llendl; + return; + } - setVisible(true); // *HACK: restore visibility after being hidden by LLSideTray::selectTabByName(). - floater_tab->addChild(this); - floater_tab->setTitle(mTabTitle); + toggleTabDocked(); +} - LLRect rect = side_tray->getLocalRect(); - floater_tab->reshape(rect.getWidth(), rect.getHeight()); +bool LLSideTrayTab::isDocked() const +{ + return dynamic_cast<LLSideTray*>(getParent()) != NULL; +} - rect.mTop -= floater_tab->getHeaderHeight(); - setRect(rect); - reshape(rect.getWidth(), rect.getHeight()); +BOOL LLSideTrayTab::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + // Let children handle the event + LLUICtrl::handleScrollWheel(x, y, clicks); - // Set FOLLOWS_ALL flag for the tab to follow floater dimensions upon resizing. - setFollowsAll(); + // and then eat it to prevent in-world scrolling (STORM-351). + return TRUE; +} - if (!side_tray->getCollapsed()) - { - side_tray->collapseSideBar(); - } +void LLSideTrayTab::dock(LLFloater* floater_tab) +{ + LLSideTray* side_tray = getSideTray(); + if (!side_tray) return; + + // Before docking the tab, reset its (and its children's) transparency to default (STORM-688). + floater_tab->updateTransparency(TT_DEFAULT); + + if (!side_tray->addTab(this)) + { + llwarns << "Failed to add tab " << getName() << " to side tray" << llendl; + return; + } + + setRect(side_tray->getLocalRect()); + reshape(getRect().getWidth(), getRect().getHeight()); + + // Select the re-docked tab. + side_tray->selectTabByName(getName()); + + if (side_tray->getCollapsed()) + { + side_tray->expandSideBar(false); + } +} + +static void on_minimize(LLSidepanelAppearance* panel, LLSD minimized) +{ + if (!panel) return; + bool visible = !minimized.asBoolean(); + LLSD visibility; + visibility["visible"] = visible; + // Do not reset accordion state on minimize (STORM-375) + visibility["reset_accordion"] = false; + panel->updateToVisibility(visibility); +} + +void LLSideTrayTab::undock(LLFloater* floater_tab) +{ + LLSideTray* side_tray = getSideTray(); + if (!side_tray) return; + + // Remember whether the tab have been active before detaching + // because removeTab() will change active tab. + bool was_active = side_tray->getActiveTab() == this; + + // Remove the tab from Side Tray's tabs list. + // We have to do it despite removing the tab from Side Tray's child view tree + // by addChild(). Otherwise the tab could be accessed by the pointer in LLSideTray::mTabs. + if (!side_tray->removeTab(this)) + { + llwarns << "Failed to remove tab " << getName() << " from side tray" << llendl; + return; + } + + // If we're undocking while side tray is collapsed we need to explicitly show the panel. + if (!getVisible()) + { + setVisible(true); + } + + floater_tab->addChild(this); + floater_tab->setTitle(mTabTitle); + floater_tab->setName(getName()); + + // Resize handles get obscured by added panel so move them to front. + floater_tab->moveResizeHandlesToFront(); + + // Reshape the floater if needed. + LLRect floater_rect; + if (floater_tab->hasSavedRect()) + { + // We've got saved rect for the floater, hence no need to reshape it. + floater_rect = floater_tab->getLocalRect(); } else { - if (!side_tray->addTab(this)) - { - llwarns << "Failed to add tab " << getName() << " to side tray" << llendl; - return; - } + // Detaching for the first time. Reshape the floater. + floater_rect = side_tray->getLocalRect(); - setRect(side_tray->getLocalRect()); - reshape(getRect().getWidth(), getRect().getHeight()); + // Reduce detached floater height by small BOTTOM_BAR_PAD not to make it flush with the bottom bar. + floater_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight() + BOTTOM_BAR_PAD; + floater_rect.makeValid(); + floater_tab->reshape(floater_rect.getWidth(), floater_rect.getHeight()); + } - // Select the re-docked tab. - side_tray->selectTabByName(getName()); + // Reshape the panel. + { + LLRect panel_rect = floater_tab->getLocalRect(); + panel_rect.mTop -= floater_tab->getHeaderHeight(); + panel_rect.makeValid(); + setRect(panel_rect); + reshape(panel_rect.getWidth(), panel_rect.getHeight()); + } - if (side_tray->getCollapsed()) + // Set FOLLOWS_ALL flag for the tab to follow floater dimensions upon resizing. + setFollowsAll(); + + // Camera view may need to be changed for appearance panel(STORM-301) on minimize of floater, + // so setting callback here. + if (getName() == "sidebar_appearance") + { + LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel()); + if(panel_appearance) { - side_tray->expandSideBar(); + floater_tab->setMinimizeCallback(boost::bind(&on_minimize, panel_appearance, _2)); } } + + if (!side_tray->getCollapsed()) + { + side_tray->collapseSideBar(); + } + + if (!was_active) + { + // When a tab other then current active tab is detached from Side Tray + // onOpen() should be called as tab visibility is changed. + onOpen(LLSD()); + } } LLPanel* LLSideTrayTab::getPanel() @@ -285,6 +446,11 @@ LLSideTrayTab* LLSideTrayTab::createInstance () return tab; } +// Now that we know the definition of LLSideTrayTab, we can implement +// tab_cast. +template <> +LLPanel* tab_cast<LLPanel*>(LLSideTrayTab* tab) { return tab; } + ////////////////////////////////////////////////////////////////////////////// // LLSideTrayButton // Side Tray tab button with "tear off" handling. @@ -332,12 +498,11 @@ public: LLSideTrayTab* tab = side_tray->getTab(getName()); if (!tab) return FALSE; - tab->toggleTabDocked(); + tab->setDocked(false); - LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", LLSD().with("name", tab->getTabTitle())); + LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab->getName()); if (!floater_tab) return FALSE; - LLRect original_rect = floater_tab->getRect(); S32 header_snap_y = floater_tab->getHeaderHeight() / 2; S32 snap_x = screen_x - original_rect.mLeft - original_rect.getWidth() / 2; @@ -378,8 +543,8 @@ private: LLSideTray::Params::Params() : collapsed("collapsed",false), - tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("sidebar_tab_left.tga")), - tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("button_enabled_selected_32x128.tga")), + tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Off.png")), + tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Selected.png")), default_button_width("tab_btn_width",32), default_button_height("tab_btn_height",32), default_button_margin("tab_btn_margin",0) @@ -399,6 +564,8 @@ LLSideTray::LLSideTray(const Params& params) // register handler function to process data from the xml. // panel_name should be specified via "parameter" attribute. commit.add("SideTray.ShowPanel", boost::bind(&LLSideTray::showPanel, this, _2, LLUUID::null)); + commit.add("SideTray.Toggle", boost::bind(&LLSideTray::onToggleCollapse, this)); + commit.add("SideTray.Collapse", boost::bind(&LLSideTray::collapseSideBar, this)); LLTransientFloaterMgr::getInstance()->addControlView(this); LLView* side_bar_tabs = gViewerWindow->getRootView()->getChildView("side_bar_tabs"); if (side_bar_tabs != NULL) @@ -441,9 +608,10 @@ BOOL LLSideTray::postBuild() { if ((*it).channel) { - getCollapseSignal().connect(boost::bind(&LLScreenChannelBase::resetPositionAndSize, (*it).channel, _2)); + setVisibleWidthChangeCallback(boost::bind(&LLScreenChannelBase::resetPositionAndSize, (*it).channel)); } } + return true; } @@ -451,16 +619,20 @@ void LLSideTray::handleLoginComplete() { //reset tab to "home" tab if it was changesd during login process selectTabByName("sidebar_home"); + + detachTabs(); } LLSideTrayTab* LLSideTray::getTab(const std::string& name) { - return getChild<LLSideTrayTab>(name,false); + return findChild<LLSideTrayTab>(name,false); } bool LLSideTray::isTabAttached(const std::string& name) { LLSideTrayTab* tab = getTab(name); + if (!tab) return false; + return std::find(mTabs.begin(), mTabs.end(), tab) != mTabs.end(); } @@ -481,10 +653,60 @@ void LLSideTray::toggleTabButton(LLSideTrayTab* tab) LLButton* btn = it->second; bool new_state = !btn->getToggleState(); btn->setToggleState(new_state); - btn->setImageOverlay( new_state ? tab->mImageSelected : tab->mImage ); + // Only highlight the tab if side tray is expanded (STORM-157). + btn->setImageOverlay( new_state && !getCollapsed() ? tab->mImageSelected : tab->mImage ); } } +LLPanel* LLSideTray::openChildPanel(LLSideTrayTab* tab, const std::string& panel_name, const LLSD& params) +{ + LLView* view = tab->findChildView(panel_name, true); + if (!view) return NULL; + + std::string tab_name = tab->getName(); + + bool tab_attached = isTabAttached(tab_name); + + if (tab_attached && LLUI::sSettingGroups["config"]->getBOOL("OpenSidePanelsInFloaters")) + { + tab->setDocked(false); + tab_attached = false; + } + + // Select tab and expand Side Tray only when a tab is attached. + if (tab_attached) + { + selectTabByName(tab_name); + if (mCollapsed) + expandSideBar(); + } + else + { + LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab_name); + if (!floater_tab) return NULL; + + floater_tab->openFloater(tab_name); + } + + LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent()); + if (container) + { + LLSD new_params = params; + new_params[LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME] = panel_name; + container->onOpen(new_params); + + return container->getCurrentPanel(); + } + + LLPanel* panel = dynamic_cast<LLPanel*>(view); + if (panel) + { + panel->onOpen(params); + } + + return panel; +} + bool LLSideTray::selectTabByIndex(size_t index) { if(index>=mTabs.size()) @@ -494,9 +716,11 @@ bool LLSideTray::selectTabByIndex(size_t index) return selectTabByName(sidebar_tab->getName()); } -bool LLSideTray::selectTabByName (const std::string& name) +bool LLSideTray::selectTabByName(const std::string& name, bool keep_prev_visible) { + LLSideTrayTab* tab_to_keep_visible = NULL; LLSideTrayTab* new_tab = getTab(name); + if (!new_tab) return false; // Bail out if already selected. if (new_tab == mActiveTab) @@ -505,7 +729,9 @@ bool LLSideTray::selectTabByName (const std::string& name) //deselect old tab if (mActiveTab) { - toggleTabButton(mActiveTab); + // Keep previously active tab visible if requested. + if (keep_prev_visible) tab_to_keep_visible = mActiveTab; + toggleTabButton(mActiveTab); } //select new tab @@ -513,9 +739,9 @@ bool LLSideTray::selectTabByName (const std::string& name) if (mActiveTab) { - toggleTabButton(mActiveTab); - LLSD key;//empty - mActiveTab->onOpen(key); + toggleTabButton(mActiveTab); + LLSD key;//empty + mActiveTab->onOpen(key); } //arrange(); @@ -525,9 +751,17 @@ bool LLSideTray::selectTabByName (const std::string& name) for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { LLSideTrayTab* sidebar_tab = *child_it; + + bool vis = sidebar_tab == mActiveTab; + + // Force keeping the tab visible if requested. + vis |= sidebar_tab == tab_to_keep_visible; + // When the last tab gets detached, for a short moment the "Toggle Sidebar" pseudo-tab // is shown. So, to avoid the flicker we make sure it never gets visible. - sidebar_tab->setVisible(sidebar_tab == mActiveTab && (*child_it)->getName() != "sidebar_openclose"); + vis &= (*child_it)->getName() != "sidebar_openclose"; + + sidebar_tab->setVisible(vis); } return true; } @@ -614,15 +848,25 @@ bool LLSideTray::removeTab(LLSideTrayTab* tab) // Deselect the tab. if (mActiveTab == tab) { - child_vector_iter_t next_tab_it = - (tab_it < (mTabs.end() - 1)) ? tab_it + 1 : mTabs.begin(); - selectTabByName((*next_tab_it)->getName()); + // Select the next tab (or first one, if we're removing the last tab), + // skipping the fake open/close tab (STORM-155). + child_vector_iter_t next_tab_it = tab_it; + do + { + next_tab_it = (next_tab_it < (mTabs.end() - 1)) ? next_tab_it + 1 : mTabs.begin(); + } + while ((*next_tab_it)->getName() == "sidebar_openclose"); + + selectTabByName((*next_tab_it)->getName(), true); // Don't hide the tab being removed. } // Remove the tab. removeChild(tab); mTabs.erase(tab_it); + // Add the tab to detached tabs list. + mDetachedTabs.push_back(tab); + // Remove the button from the buttons panel so that it isn't drawn anymore. mButtonsPanel->removeChild(btn); @@ -684,6 +928,13 @@ bool LLSideTray::addTab(LLSideTrayTab* tab) // Arrange tabs after inserting a new one. arrange(); + // Remove the tab from the list of detached tabs. + child_vector_iter_t tab_it = std::find(mDetachedTabs.begin(), mDetachedTabs.end(), tab); + if (tab_it != mDetachedTabs.end()) + { + mDetachedTabs.erase(tab_it); + } + return true; } @@ -702,6 +953,7 @@ void LLSideTray::createButtons () { mCollapseButton = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(), boost::bind(&LLSideTray::onToggleCollapse, this)); + LLHints::registerHintTarget("side_panel_btn", mCollapseButton->getHandle()); } else { @@ -710,6 +962,7 @@ void LLSideTray::createButtons () mTabButtons[name] = button; } } + LLHints::registerHintTarget("inventory_btn", mTabButtons["sidebar_inventory"]->getHandle()); } void LLSideTray::processTriState () @@ -733,8 +986,10 @@ void LLSideTray::processTriState () void LLSideTray::onTabButtonClick(string name) { - LLSideTrayTab* side_bar = getTab(name); - if(side_bar == mActiveTab) + LLSideTrayTab* tab = getTab(name); + if (!tab) return; + + if(tab == mActiveTab) { processTriState (); return; @@ -746,6 +1001,7 @@ void LLSideTray::onTabButtonClick(string name) void LLSideTray::onToggleCollapse() { + LLFirstUse::notUsingSidePanel(false); if(mCollapsed) { expandSideBar(); @@ -760,21 +1016,9 @@ void LLSideTray::reflectCollapseChange() { updateSidetrayVisibility(); - if(mCollapsed) - { - gFloaterView->setSnapOffsetRight(0); - setFocus(FALSE); - } - else - { - gFloaterView->setSnapOffsetRight(getRect().getWidth()); - setFocus(TRUE); - } + setFocus(!mCollapsed); gFloaterView->refresh(); - - LLSD new_value = mCollapsed; - mCollapseSignal(this,new_value); } void LLSideTray::arrange() @@ -824,7 +1068,30 @@ void LLSideTray::arrange() } // The tab buttons should be shown only if there is at least one non-detached tab. - mButtonsPanel->setVisible(hasTabs()); + // Also hide them in mouse-look mode. + mButtonsPanel->setVisible(hasTabs() && !gAgentCamera.cameraMouselook()); +} + +// Detach those tabs that were detached when the viewer exited last time. +void LLSideTray::detachTabs() +{ + // copy mTabs because LLSideTray::toggleTabDocked() modifies it. + child_vector_t tabs = mTabs; + + for (child_vector_const_iter_t it = tabs.begin(); it != tabs.end(); ++it) + { + LLSideTrayTab* tab = *it; + + std::string floater_ctrl_name = LLFloater::getControlName("side_bar_tab", LLSD(tab->getName())); + std::string vis_ctrl_name = LLFloaterReg::getVisibilityControlName(floater_ctrl_name); + if (!LLFloater::getControlGroup()->controlExists(vis_ctrl_name)) continue; + + bool is_visible = LLFloater::getControlGroup()->getBOOL(vis_ctrl_name); + if (!is_visible) continue; + + llassert(isTabAttached(tab->getName())); + tab->setDocked(false); + } } void LLSideTray::collapseSideBar() @@ -857,7 +1124,7 @@ void LLSideTray::collapseSideBar() setFocus( FALSE ); } -void LLSideTray::expandSideBar() +void LLSideTray::expandSideBar(bool open_active) { mCollapsed = false; LLSideTrayTab* openclose_tab = getTab("sidebar_openclose"); @@ -865,8 +1132,11 @@ void LLSideTray::expandSideBar() { mCollapseButton->setImageOverlay( openclose_tab->mImageSelected ); } - LLSD key;//empty - mActiveTab->onOpen(key); + + if (open_active) + { + mActiveTab->onOpen(LLSD()); + } reflectCollapseChange(); @@ -910,6 +1180,38 @@ void LLSideTray::reshape(S32 width, S32 height, BOOL called_from_parent) arrange(); } +// This is just LLView::findChildView specialized to restrict the search to LLPanels. +// Optimization for EXT-4068 to avoid searching down to the individual item level +// when inventories are large. +LLPanel *findChildPanel(LLPanel *panel, const std::string& name, bool recurse) +{ + for (LLView::child_list_const_iter_t child_it = panel->beginChild(); + child_it != panel->endChild(); ++child_it) + { + LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it); + if (!child_panel) + continue; + if (child_panel->getName() == name) + return child_panel; + } + if (recurse) + { + for (LLView::child_list_const_iter_t child_it = panel->beginChild(); + child_it != panel->endChild(); ++child_it) + { + LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it); + if (!child_panel) + continue; + LLPanel *found_panel = findChildPanel(child_panel,name,recurse); + if (found_panel) + { + return found_panel; + } + } + } + return NULL; +} + /** * Activate tab with "panel_name" panel * if no such tab - return false, otherwise true. @@ -919,37 +1221,68 @@ void LLSideTray::reshape(S32 width, S32 height, BOOL called_from_parent) */ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& params) { - //arrange tabs + LLPanel* new_panel = NULL; + + // Look up the tab in the list of detached tabs. child_vector_const_iter_t child_it; + for ( child_it = mDetachedTabs.begin(); child_it != mDetachedTabs.end(); ++child_it) + { + new_panel = openChildPanel(*child_it, panel_name, params); + if (new_panel) break; + } + + // Look up the tab in the list of attached tabs. for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { - LLView* view = (*child_it)->findChildView(panel_name,true); - if(view) - { - selectTabByName ((*child_it)->getName()); - if(mCollapsed) - expandSideBar(); + new_panel = openChildPanel(*child_it, panel_name, params); + if (new_panel) break; + } - LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent()); - if(container) - { - LLSD new_params = params; - new_params[LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME] = panel_name; - container->onOpen(new_params); + return new_panel; +} - return container->getCurrentPanel(); - } +bool LLSideTray::hidePanel(const std::string& panel_name) +{ + bool panelHidden = false; + + LLPanel* panelp = getPanel(panel_name); - LLPanel* panel = dynamic_cast<LLPanel*>(view); - if(panel) + if (panelp) + { + LLView* parentp = panelp->getParent(); + + // Collapse the side bar if the panel or the panel's parent is an attached tab + if (isTabAttached(panel_name) || (parentp && isTabAttached(parentp->getName()))) + { + collapseSideBar(); + panelHidden = true; + } + else + { + panelHidden = LLFloaterReg::hideInstance("side_bar_tab", panel_name); + + if (!panelHidden) { - panel->onOpen(params); + // Look up the panel in the list of detached tabs. + for (child_vector_const_iter_t child_it = mDetachedTabs.begin(); child_it != mDetachedTabs.end(); ++child_it) + { + LLPanel *detached_panel = dynamic_cast<LLPanel*>(*child_it); + + if (detached_panel) + { + // Hide this detached panel if it is a parent of our panel + if (findChildPanel(detached_panel, panel_name, true) != NULL) + { + panelHidden = LLFloaterReg::hideInstance("side_bar_tab", detached_panel->getName()); + break; + } + } + } } - - return panel; } } - return NULL; + + return panelHidden; } void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params) @@ -957,7 +1290,9 @@ void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, if(!sub_panel) return; - if (sub_panel->isInVisibleChain()) + // If a panel is visible and attached to Side Tray (has LLSideTray among its ancestors) + // it should be toggled off by collapsing Side Tray. + if (sub_panel->isInVisibleChain() && sub_panel->hasAncestor(this)) { LLSideTray::getInstance()->collapseSideBar(); } @@ -967,40 +1302,19 @@ void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, } } -// This is just LLView::findChildView specialized to restrict the search to LLPanels. -// Optimization for EXT-4068 to avoid searching down to the individual item level -// when inventories are large. -LLPanel *findChildPanel(LLPanel *panel, const std::string& name, bool recurse) +LLPanel* LLSideTray::getPanel(const std::string& panel_name) { - for (LLView::child_list_const_iter_t child_it = panel->beginChild(); - child_it != panel->endChild(); ++child_it) + // Look up the panel in the list of detached tabs. + for ( child_vector_const_iter_t child_it = mDetachedTabs.begin(); child_it != mDetachedTabs.end(); ++child_it) { - LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it); - if (!child_panel) - continue; - if (child_panel->getName() == name) - return child_panel; - } - if (recurse) - { - for (LLView::child_list_const_iter_t child_it = panel->beginChild(); - child_it != panel->endChild(); ++child_it) + LLPanel *panel = findChildPanel(*child_it,panel_name,true); + if(panel) { - LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it); - if (!child_panel) - continue; - LLPanel *found_panel = findChildPanel(child_panel,name,recurse); - if (found_panel) - { - return found_panel; - } + return panel; } } - return NULL; -} -LLPanel* LLSideTray::getPanel(const std::string& panel_name) -{ + // Look up the panel in the list of attached tabs. for ( child_vector_const_iter_t child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) { LLPanel *panel = findChildPanel(*child_it,panel_name,true); @@ -1028,12 +1342,61 @@ bool LLSideTray::isPanelActive(const std::string& panel_name) return (panel->getName() == panel_name); } +void LLSideTray::setTabDocked(const std::string& tab_name, bool dock, bool toggle_floater /* = true*/) +{ + // Lookup tab by name. + LLSideTrayTab* tab = getTab(tab_name); + if (!tab) + { // not a docked tab, look through detached tabs + for(child_vector_iter_t tab_it = mDetachedTabs.begin(), tab_end_it = mDetachedTabs.end(); + tab_it != tab_end_it; + ++tab_it) + { + if ((*tab_it)->getName() == tab_name) + { + tab = *tab_it; + break; + } + } + + } + + llassert(tab != NULL); + + // Toggle its dock state. + if (tab && tab->isDocked() != dock) + { + tab->toggleTabDocked(toggle_floater); + } +} + + void LLSideTray::updateSidetrayVisibility() { // set visibility of parent container based on collapsed state - if (getParent()) + LLView* parent = getParent(); + if (parent) { - getParent()->setVisible(!mCollapsed && !gAgentCamera.cameraMouselook()); + bool old_visibility = parent->getVisible(); + bool new_visibility = !mCollapsed && !gAgentCamera.cameraMouselook(); + + if (old_visibility != new_visibility) + { + parent->setVisible(new_visibility); + + // Signal change of visible width. + llinfos << "Visible: " << new_visibility << llendl; + mVisibleWidthChangeSignal(this, new_visibility); + } } } +S32 LLSideTray::getVisibleWidth() +{ + return (isInVisibleChain() && !mCollapsed) ? getRect().getWidth() : 0; +} + +void LLSideTray::setVisibleWidthChangeCallback(const commit_signal_t::slot_type& cb) +{ + mVisibleWidthChangeSignal.connect(cb); +} |