summaryrefslogtreecommitdiff
path: root/indra/newview/llsidetray.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llsidetray.cpp')
-rw-r--r--indra/newview/llsidetray.cpp350
1 files changed, 211 insertions, 139 deletions
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 4f18ee1da2..a7c4057846 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"
@@ -113,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:
@@ -127,8 +132,6 @@ protected:
void undock(LLFloater* floater_tab);
LLSideTray* getSideTray();
-
- void onFloaterClose(LLSD::Boolean app_quitting);
public:
virtual ~LLSideTrayTab();
@@ -142,17 +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;
@@ -160,7 +165,9 @@ private:
std::string mDescription;
LLView* mMainPanel;
- boost::signals2::connection mFloaterCloseConn;
+
+ bool mHasBadge;
+ LLBadge::Params mBadgeParams;
};
LLSideTrayTab::LLSideTrayTab(const Params& p)
@@ -169,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()
@@ -185,8 +194,6 @@ bool LLSideTrayTab::addChild(LLView* view, S32 tab_group)
//return res;
}
-
-
//virtual
BOOL LLSideTrayTab::postBuild()
{
@@ -196,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;
@@ -253,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.
@@ -278,7 +287,10 @@ 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.
@@ -298,18 +310,6 @@ bool LLSideTrayTab::isDocked() const
return dynamic_cast<LLSideTray*>(getParent()) != NULL;
}
-void LLSideTrayTab::onFloaterClose(LLSD::Boolean app_quitting)
-{
- // If user presses Ctrl-Shift-W, handle that gracefully by docking all
- // undocked tabs before their floaters get destroyed (STORM-1016).
-
- // Don't dock on quit for the current dock state to be correctly saved.
- if (app_quitting) return;
-
- lldebugs << "Forcibly docking tab " << getName() << llendl;
- setDocked(true);
-}
-
BOOL LLSideTrayTab::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
// Let children handle the event
@@ -333,7 +333,6 @@ void LLSideTrayTab::dock(LLFloater* floater_tab)
return;
}
- mFloaterCloseConn.disconnect();
setRect(side_tray->getLocalRect());
reshape(getRect().getWidth(), getRect().getHeight());
@@ -382,7 +381,6 @@ void LLSideTrayTab::undock(LLFloater* floater_tab)
}
floater_tab->addChild(this);
- mFloaterCloseConn = floater_tab->setCloseCallback(boost::bind(&LLSideTrayTab::onFloaterClose, this, _2));
floater_tab->setTitle(mTabTitle);
floater_tab->setName(getName());
@@ -498,7 +496,7 @@ public:
LLSideTray* side_tray = LLSideTray::getInstance();
// Check if the tab we are dragging is docked.
- if (!side_tray->isTabAttached(getName())) return FALSE;
+ if (!side_tray->isTabAttached(mTabName)) return FALSE;
// Same value is hardcoded in LLDragHandle::handleHover().
const S32 undock_threshold = 12;
@@ -507,10 +505,10 @@ public:
if (delta_x <= -undock_threshold || delta_x >= undock_threshold ||
delta_y <= -undock_threshold || delta_y >= undock_threshold)
{
- LLSideTrayTab* tab = side_tray->getTab(getName());
+ LLSideTrayTab* tab = side_tray->getTab(mTabName);
if (!tab) return FALSE;
- tab->toggleTabDocked();
+ tab->setDocked(false);
LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab->getName());
if (!floater_tab) return FALSE;
@@ -535,18 +533,42 @@ 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)
+ {
+ // Find out the tab name to use in handleHover().
+ size_t pos = getName().find("_button");
+ llassert(pos != std::string::npos);
+ mTabName = getName().substr(0, pos);
+ }
friend class LLUICtrlFactory;
+ void draw()
+ {
+ if (mBadgeDriver)
+ {
+ setBadgeLabel(mBadgeDriver->getBadgeString());
+ }
+
+ LLButton::draw();
+ }
+
private:
S32 mDragLastScreenX;
S32 mDragLastScreenY;
+
+ std::string mTabName;
+ LLSideTrayTabBadgeDriver* mBadgeDriver;
};
//////////////////////////////////////////////////////////////////////////////
@@ -627,11 +649,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();
}
@@ -643,6 +685,7 @@ LLSideTrayTab* LLSideTray::getTab(const std::string& name)
bool LLSideTray::isTabAttached(const std::string& name)
{
LLSideTrayTab* tab = getTab(name);
+ llassert(tab);
if (!tab) return false;
return std::find(mTabs.begin(), mTabs.end(), tab) != mTabs.end();
@@ -681,7 +724,7 @@ LLPanel* LLSideTray::openChildPanel(LLSideTrayTab* tab, const std::string& panel
if (tab_attached && LLUI::sSettingGroups["config"]->getBOOL("OpenSidePanelsInFloaters"))
{
- tab->toggleTabDocked();
+ tab->setDocked(false);
tab_attached = false;
}
@@ -778,51 +821,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);
@@ -950,7 +948,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();
@@ -963,17 +1010,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());
}
@@ -1102,7 +1154,7 @@ void LLSideTray::detachTabs()
if (!is_visible) continue;
llassert(isTabAttached(tab->getName()));
- tab->toggleTabDocked();
+ tab->setDocked(false);
}
}
@@ -1192,6 +1244,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.
@@ -1221,23 +1305,50 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para
return new_panel;
}
-void LLSideTray::hidePanel(const std::string& panel_name)
+bool LLSideTray::hidePanel(const std::string& panel_name)
{
+ bool panelHidden = false;
+
LLPanel* panelp = getPanel(panel_name);
+
if (panelp)
{
- if(isTabAttached(panel_name))
+ 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
{
- LLFloaterReg::hideInstance("side_bar_tab", panel_name);
+ panelHidden = LLFloaterReg::hideInstance("side_bar_tab", panel_name);
+
+ if (!panelHidden)
+ {
+ // 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 panelHidden;
}
-
void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params)
{
if(!sub_panel)
@@ -1255,38 +1366,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.
@@ -1327,8 +1406,9 @@ bool LLSideTray::isPanelActive(const std::string& panel_name)
return (panel->getName() == panel_name);
}
-void LLSideTray::setTabDocked(const std::string& tab_name, bool dock)
+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
@@ -1345,20 +1425,12 @@ void LLSideTray::setTabDocked(const std::string& tab_name, bool dock)
}
- if (tab)
- {
- bool tab_attached = isTabAttached(tab_name);
- LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab_name);
- if (!floater_tab) return;
+ llassert(tab != NULL);
- if (dock && !tab_attached)
- {
- tab->dock(floater_tab);
- }
- else if (!dock && tab_attached)
- {
- tab->undock(floater_tab);
- }
+ // Toggle its dock state.
+ if (tab && tab->isDocked() != dock)
+ {
+ tab->toggleTabDocked(toggle_floater);
}
}