diff options
Diffstat (limited to 'indra/newview/llsidetray.cpp')
-rw-r--r-- | indra/newview/llsidetray.cpp | 411 |
1 files changed, 286 insertions, 125 deletions
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index eb537c7d7b..651897a217 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -30,6 +30,7 @@ #include "llagentcamera.h" #include "llappviewer.h" +#include "llbadge.h" #include "llbottomtray.h" #include "llfloaterreg.h" #include "llfirstuse.h" @@ -40,6 +41,7 @@ #include "llfocusmgr.h" #include "llrootview.h" #include "llnavigationbar.h" +#include "llpanelmarketplaceinbox.h" #include "llaccordionctrltab.h" @@ -53,6 +55,8 @@ #include "llsidepanelappearance.h" +#include "llsidetraylistener.h" + //#include "llscrollcontainer.h" using namespace std; @@ -71,6 +75,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() { @@ -96,6 +102,7 @@ bool LLSideTray::instanceCreated () class LLSideTrayTab: public LLPanel { + LOG_CLASS(LLSideTrayTab); friend class LLUICtrlFactory; friend class LLSideTray; public: @@ -108,11 +115,14 @@ public: Optional<std::string> image_selected; Optional<std::string> tab_title; Optional<std::string> description; + Optional<LLBadge::Params> badge; + Params() : image("image"), image_selected("image_selected"), tab_title("tab_title","no title"), - description("description","no description") + description("description","no description"), + badge("badge") {}; }; protected: @@ -135,15 +145,19 @@ public: static LLSideTrayTab* createInstance (); const std::string& getDescription () const { return mDescription;} - const std::string& getTabTitle() const { return mTabTitle;} void onOpen (const LLSD& key); - void toggleTabDocked(); + void toggleTabDocked(bool toggle_floater = true); + void setDocked(bool dock); + bool isDocked() const; BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - LLPanel *getPanel(); + LLPanel* getPanel(); + + LLButton* createButton(bool allowTearOff, LLUICtrl::commit_callback_t callback); + private: std::string mTabTitle; std::string mImage; @@ -151,6 +165,9 @@ private: std::string mDescription; LLView* mMainPanel; + + bool mHasBadge; + LLBadge::Params mBadgeParams; }; LLSideTrayTab::LLSideTrayTab(const Params& p) @@ -159,8 +176,10 @@ LLSideTrayTab::LLSideTrayTab(const Params& p) mImage(p.image), mImageSelected(p.image_selected), mDescription(p.description), - mMainPanel(NULL) + mMainPanel(NULL), + mBadgeParams(p.badge) { + mHasBadge = p.badge.isProvided(); } LLSideTrayTab::~LLSideTrayTab() @@ -175,8 +194,6 @@ bool LLSideTrayTab::addChild(LLView* view, S32 tab_group) //return res; } - - //virtual BOOL LLSideTrayTab::postBuild() { @@ -186,10 +203,10 @@ BOOL LLSideTrayTab::postBuild() title_panel->getChild<LLTextBox>(TAB_PANEL_CAPTION_TITLE_BOX)->setValue(mTabTitle); - getChild<LLButton>("undock")->setCommitCallback(boost::bind(&LLSideTrayTab::toggleTabDocked, this)); - 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; + return LLPanel::postBuild(); } static const S32 splitter_margin = 1; @@ -243,14 +260,16 @@ LLSideTray* LLSideTrayTab::getSideTray() return side_tray; } -void LLSideTrayTab::toggleTabDocked() +void LLSideTrayTab::toggleTabDocked(bool toggle_floater /* = true */) { + // *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; - bool docking = LLFloater::isShown(floater_tab); + bool docking = !isDocked(); // Hide the "Tear Off" button when a tab gets undocked // and show "Dock" button instead. @@ -268,7 +287,27 @@ void LLSideTrayTab::toggleTabDocked() // Open/close the floater *after* we reparent the tab panel, // so that it doesn't receive redundant visibility change notifications. - LLFloaterReg::toggleInstance("side_bar_tab", tab_name); + 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; + } + + toggleTabDocked(); +} + +bool LLSideTrayTab::isDocked() const +{ + return dynamic_cast<LLSideTray*>(getParent()) != NULL; } BOOL LLSideTrayTab::handleScrollWheel(S32 x, S32 y, S32 clicks) @@ -417,6 +456,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. @@ -464,7 +508,7 @@ public: LLSideTrayTab* tab = side_tray->getTab(getName()); if (!tab) return FALSE; - tab->toggleTabDocked(); + tab->setDocked(false); LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab->getName()); if (!floater_tab) return FALSE; @@ -489,18 +533,36 @@ public: return FALSE; } + void setBadgeDriver(LLSideTrayTabBadgeDriver* driver) + { + mBadgeDriver = driver; + } + protected: LLSideTrayButton(const LLButton::Params& p) - : LLButton(p) - , mDragLastScreenX(0) - , mDragLastScreenY(0) + : LLButton(p) + , mDragLastScreenX(0) + , mDragLastScreenY(0) + , mBadgeDriver(NULL) {} friend class LLUICtrlFactory; + void draw() + { + if (mBadgeDriver) + { + setBadgeLabel(mBadgeDriver->getBadgeString()); + } + + LLButton::draw(); + } + private: S32 mDragLastScreenX; S32 mDragLastScreenY; + + LLSideTrayTabBadgeDriver* mBadgeDriver; }; ////////////////////////////////////////////////////////////////////////////// @@ -530,6 +592,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) @@ -579,11 +643,31 @@ BOOL LLSideTray::postBuild() return true; } +void LLSideTray::setTabButtonBadgeDriver(std::string tabName, LLSideTrayTabBadgeDriver* driver) +{ + mTabButtonBadgeDrivers[tabName] = driver; +} + void LLSideTray::handleLoginComplete() { //reset tab to "home" tab if it was changesd during login process selectTabByName("sidebar_home"); + for (badge_map_t::iterator it = mTabButtonBadgeDrivers.begin(); it != mTabButtonBadgeDrivers.end(); ++it) + { + LLButton* button = mTabButtons[it->first]; + LLSideTrayButton* side_button = dynamic_cast<LLSideTrayButton*>(button); + + if (side_button) + { + side_button->setBadgeDriver(it->second); + } + else + { + llwarns << "Unable to find button " << it->first << " to set the badge driver. " << llendl; + } + } + detachTabs(); } @@ -629,8 +713,16 @@ LLPanel* LLSideTray::openChildPanel(LLSideTrayTab* tab, const std::string& panel 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 (isTabAttached(tab_name)) + if (tab_attached) { selectTabByName(tab_name); if (mCollapsed) @@ -641,14 +733,7 @@ LLPanel* LLSideTray::openChildPanel(LLSideTrayTab* tab, const std::string& panel LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab_name); if (!floater_tab) return NULL; - // Restore the floater if it was minimized. - if (floater_tab->isMinimized()) - { - floater_tab->setMinimized(FALSE); - } - - // Send the floater to the front. - floater_tab->setFrontmost(); + floater_tab->openFloater(tab_name); } LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent()); @@ -729,51 +814,6 @@ bool LLSideTray::selectTabByName(const std::string& name, bool keep_prev_visible return true; } -LLButton* LLSideTray::createButton (const std::string& name,const std::string& image,const std::string& tooltip, - LLUICtrl::commit_callback_t callback) -{ - static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); - - LLButton::Params bparams; - - LLRect rect; - rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height); - - bparams.name(name); - bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP); - bparams.rect (rect); - bparams.tab_stop(false); - bparams.image_unselected(sidetray_params.tab_btn_image_normal); - bparams.image_selected(sidetray_params.tab_btn_image_selected); - bparams.image_disabled(sidetray_params.tab_btn_image_normal); - bparams.image_disabled_selected(sidetray_params.tab_btn_image_selected); - - LLButton* button; - if (name == "sidebar_openclose") - { - // "Open/Close" button shouldn't allow "tear off" - // hence it is created as LLButton instance. - button = LLUICtrlFactory::create<LLButton>(bparams); - } - else - { - button = LLUICtrlFactory::create<LLSideTrayButton>(bparams); - } - - button->setClickedCallback(callback); - - button->setToolTip(tooltip); - - if(image.length()) - { - button->setImageOverlay(image); - } - - mButtonsPanel->addChildInBack(button); - - return button; -} - bool LLSideTray::addChild(LLView* view, S32 tab_group) { LLSideTrayTab* tab_panel = dynamic_cast<LLSideTrayTab*>(view); @@ -901,7 +941,56 @@ bool LLSideTray::addTab(LLSideTrayTab* tab) return true; } -void LLSideTray::createButtons () +LLButton* LLSideTrayTab::createButton(bool allowTearOff, LLUICtrl::commit_callback_t callback) +{ + static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); + + LLRect rect; + rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height); + + LLButton::Params bparams; + + // Append "_button" to the side tray tab name + std::string button_name = getName() + "_button"; + bparams.name(button_name); + bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP); + bparams.rect (rect); + bparams.tab_stop(false); + bparams.image_unselected(sidetray_params.tab_btn_image_normal); + bparams.image_selected(sidetray_params.tab_btn_image_selected); + bparams.image_disabled(sidetray_params.tab_btn_image_normal); + bparams.image_disabled_selected(sidetray_params.tab_btn_image_selected); + + if (mHasBadge) + { + bparams.badge = mBadgeParams; + } + + LLButton* button; + if (allowTearOff) + { + button = LLUICtrlFactory::create<LLSideTrayButton>(bparams); + } + else + { + // "Open/Close" button shouldn't allow "tear off" + // hence it is created as LLButton instance. + button = LLUICtrlFactory::create<LLButton>(bparams); + } + + button->setClickedCallback(callback); + + button->setToolTip(mTabTitle); + + if(mImage.length()) + { + button->setImageOverlay(mImage); + } + + return button; +} + +void LLSideTray::createButtons() { //create buttons for tabs child_vector_const_iter_t child_it = mTabs.begin(); @@ -914,17 +1003,22 @@ void LLSideTray::createButtons () // The "OpenClose" button will open/close the whole panel if (name == "sidebar_openclose") { - mCollapseButton = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(), - boost::bind(&LLSideTray::onToggleCollapse, this)); + mCollapseButton = sidebar_tab->createButton(false, boost::bind(&LLSideTray::onToggleCollapse, this)); + + mButtonsPanel->addChildInBack(mCollapseButton); + LLHints::registerHintTarget("side_panel_btn", mCollapseButton->getHandle()); } else { - LLButton* button = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(), - boost::bind(&LLSideTray::onTabButtonClick, this, name)); + LLButton* button = sidebar_tab->createButton(true, boost::bind(&LLSideTray::onTabButtonClick, this, name)); + + mButtonsPanel->addChildInBack(button); + mTabButtons[name] = button; } } + LLHints::registerHintTarget("inventory_btn", mTabButtons["sidebar_inventory"]->getHandle()); } @@ -979,16 +1073,7 @@ void LLSideTray::reflectCollapseChange() { updateSidetrayVisibility(); - if(mCollapsed) - { - gFloaterView->setSnapOffsetRight(0); - setFocus(FALSE); - } - else - { - gFloaterView->setSnapOffsetRight(getRect().getWidth()); - setFocus(TRUE); - } + setFocus(!mCollapsed); gFloaterView->refresh(); } @@ -1062,7 +1147,7 @@ void LLSideTray::detachTabs() if (!is_visible) continue; llassert(isTabAttached(tab->getName())); - tab->toggleTabDocked(); + tab->setDocked(false); } } @@ -1152,6 +1237,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. @@ -1161,21 +1278,68 @@ void LLSideTray::reshape(S32 width, S32 height, BOOL called_from_parent) */ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& params) { + 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) { - LLPanel* panel = openChildPanel(*child_it, panel_name, params); - if (panel) return panel; - } + 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) + { + new_panel = openChildPanel(*child_it, panel_name, params); + if (new_panel) break; + } + + return new_panel; +} + +bool LLSideTray::hidePanel(const std::string& panel_name) +{ + bool panelHidden = false; + + LLPanel* panelp = getPanel(panel_name); + + 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) { - LLPanel* panel = openChildPanel(*child_it, panel_name, params); - if (panel) return panel; + // 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 NULL; + + return panelHidden; } void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params) @@ -1195,38 +1359,6 @@ 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) -{ - 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; -} - LLPanel* LLSideTray::getPanel(const std::string& panel_name) { // Look up the panel in the list of detached tabs. @@ -1267,6 +1399,35 @@ 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 |