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.cpp623
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);
+}