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.cpp687
1 files changed, 687 insertions, 0 deletions
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
new file mode 100644
index 0000000000..afa8e5f072
--- /dev/null
+++ b/indra/newview/llsidetray.cpp
@@ -0,0 +1,687 @@
+/**
+ * @file llsidetray.cpp
+ * @brief SideBar implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltextbox.h"
+
+#include "llbottomtray.h"
+#include "llsidetray.h"
+#include "llviewerwindow.h"
+#include "llaccordionctrl.h"
+#include "llfocusmgr.h"
+#include "llrootview.h"
+#include "llnavigationbar.h"
+
+#include "llaccordionctrltab.h"
+
+#include "llfloater.h" //for gFloaterView
+#include "lliconctrl.h"//for Home tab icon
+#include "llsidetraypanelcontainer.h"
+#include "llwindow.h"//for SetCursor
+
+//#include "llscrollcontainer.h"
+
+using namespace std;
+
+static LLRootViewRegistry::Register<LLSideTray> t1("side_tray");
+static LLDefaultChildRegistry::Register<LLSideTrayTab> t2("sidetray_tab");
+
+static const std::string COLLAPSED_NAME = "<<";
+static const std::string EXPANDED_NAME = ">>";
+
+static const std::string TAB_PANEL_CAPTION_NAME = "sidetray_tab_panel";
+static const std::string TAB_PANEL_CAPTION_TITLE_BOX = "sidetray_tab_title";
+
+LLSideTray* LLSideTray::sInstance = 0;
+
+class LLSideTrayInfoPanel: public LLPanel
+{
+
+public:
+ LLSideTrayInfoPanel():LLPanel()
+ {
+ setBorderVisible(true);
+ }
+
+ BOOL handleHover(S32 x, S32 y, MASK mask)
+ {
+ getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
+ }
+
+ BOOL handleMouseUp(S32 x, S32 y, MASK mask)
+ {
+ std::string name = getName();
+ onCommit();
+ LLSideTray::getInstance()->selectTabByName(name);
+ return LLPanel::handleMouseUp(x,y,mask);
+ }
+ void reshape (S32 width, S32 height, BOOL called_from_parent )
+ {
+ return LLPanel::reshape(width, height, called_from_parent);
+ }
+
+};
+
+static LLRegisterPanelClassWrapper<LLSideTrayInfoPanel> t_people("panel_sidetray_home_info");
+
+LLSideTray* LLSideTray::getInstance()
+{
+ if (!sInstance)
+ {
+ sInstance = LLUICtrlFactory::createFromFile<LLSideTray>("panel_side_tray.xml",gViewerWindow->getRootView(), LLRootView::child_registry_t::instance());
+ }
+
+ return sInstance;
+}
+
+bool LLSideTray::instanceCreated ()
+{
+ return sInstance!=0;
+}
+
+LLSideTrayTab::LLSideTrayTab(const Params& params):mMainPanel(0)
+{
+ mImagePath = params.image_path;
+ mTabTitle = params.tab_title;
+ mDescription = params.description;
+
+ // Necessary for focus movement among child controls
+ setFocusRoot(TRUE);
+}
+
+LLSideTrayTab::~LLSideTrayTab()
+{
+}
+
+bool LLSideTrayTab::addChild(LLView* view, S32 tab_group)
+{
+ if(mMainPanel == 0 && TAB_PANEL_CAPTION_NAME != view->getName())//skip our caption panel
+ mMainPanel = view;
+ return LLPanel::addChild(view,tab_group);
+ //return res;
+}
+
+
+
+//virtual
+BOOL LLSideTrayTab::postBuild()
+{
+ LLPanel* title_panel = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>("panel_side_tray_tab_caption.xml",this, child_registry_t::instance());
+ string name = title_panel->getName();
+ LLPanel::addChild(title_panel);
+
+ title_panel->getChild<LLTextBox>(TAB_PANEL_CAPTION_TITLE_BOX)->setValue(mTabTitle);
+
+ static LLUIColor default_background_color = LLUIColorTable::instance().getColor("FloaterDefaultBackgroundColor");
+ static LLUIColor focus_background_color = LLUIColorTable::instance().getColor("FloaterFocusBackgroundColor");
+
+ setTransparentColor(default_background_color);
+ setBackgroundColor(focus_background_color);
+
+ return true;
+}
+
+static const S32 splitter_margin = 1;
+
+//virtual
+void LLSideTrayTab::arrange(S32 width, S32 height )
+{
+ if(!mMainPanel)
+ return;
+
+ S32 offset = 0;
+
+ LLView* title_panel = findChildView(TAB_PANEL_CAPTION_NAME, true);
+
+ if(title_panel)
+ {
+ title_panel->setOrigin( 0, height - title_panel->getRect().getHeight() );
+ offset = title_panel->getRect().getHeight();
+ }
+
+ LLRect sRect = mMainPanel->getRect();
+ sRect.setLeftTopAndSize( splitter_margin, height - offset - splitter_margin, width - 2*splitter_margin, height - offset - 2*splitter_margin);
+ mMainPanel->reshape(sRect.getWidth(),sRect.getHeight());
+ mMainPanel->setRect(sRect);
+
+
+
+}
+
+void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent )
+{
+ if(!mMainPanel)
+ return;
+ S32 offset = 0;
+
+ LLView* title_panel = findChildView(TAB_PANEL_CAPTION_NAME, true);
+
+ if(title_panel)
+ {
+ title_panel->setOrigin( 0, height - title_panel->getRect().getHeight() );
+ title_panel->reshape(width,title_panel->getRect().getHeight());
+ offset = title_panel->getRect().getHeight();
+ }
+
+
+
+ LLRect sRect = mMainPanel->getRect();
+ sRect.setLeftTopAndSize( splitter_margin, height - offset - splitter_margin, width - 2*splitter_margin, height - offset - 2*splitter_margin);
+ //mMainPanel->setMaxWidth(sRect.getWidth());
+ mMainPanel->reshape(sRect.getWidth(), sRect.getHeight());
+
+ mMainPanel->setRect(sRect);
+
+}
+
+void LLSideTrayTab::draw()
+{
+ LLPanel::draw();
+
+ //border
+ gl_rect_2d(0,0,getRect().getWidth() - 1,getRect().getHeight() - 1,LLColor4::black,false);
+
+
+}
+
+void LLSideTrayTab::onOpen (const LLSD& key)
+{
+ LLPanel* panel = dynamic_cast<LLPanel*>(mMainPanel);
+ if(panel)
+ panel->onOpen(key);
+}
+
+LLSideTrayTab* LLSideTrayTab::createInstance ()
+{
+ LLSideTrayTab::Params tab_params;
+ tab_params.tab_title("Home");
+
+ LLSideTrayTab* tab = LLUICtrlFactory::create<LLSideTrayTab>(tab_params);
+ return tab;
+}
+
+
+//virtual
+LLSideTray::LLSideTray(Params& params)
+ : LLPanel(params)
+ ,mActiveTab(0)
+ ,mCollapsed(false)
+ ,mCollapseButton(0)
+ ,mMaxBarWidth(params.rect.width)
+{
+ mCollapsed=params.collapsed;
+}
+
+
+BOOL LLSideTray::postBuild()
+{
+ createButtons();
+
+ arrange();
+ selectTabByName("sidebar_home");
+
+ if(mCollapsed)
+ collapseSideBar();
+
+ setMouseOpaque(false);
+ return true;
+}
+
+/**
+ * add new panel to tab with tab_name name
+ * @param tab_name - name of sidebar tab to add new panel
+ * @param panel - pointer to panel
+ */
+bool LLSideTray::addPanel ( const std::string& tab_name
+ ,LLPanel* panel )
+{
+ return false;
+}
+/**
+ * Add new tab to side bar
+ * @param tab_name - name of the new tab
+ * @param image - image for new sidebar button
+ * @param title - title for new tab
+ */
+bool LLSideTray::addTab ( const std::string& tab_name
+ ,const std::string& image
+ ,const std::string& title)
+{
+ LLSideTrayTab::Params params;
+ params.image_path = image;
+ params.tab_title = title;
+ LLSideTrayTab* tab = LLUICtrlFactory::create<LLSideTrayTab> (params);
+ addChild(tab,1);
+ return true;
+}
+
+
+LLSideTrayTab* LLSideTray::getTab(const std::string& name)
+{
+ return getChild<LLSideTrayTab>(name,false);
+}
+
+
+
+void LLSideTray::toggleTabButton (LLSideTrayTab* tab)
+{
+ if(tab == NULL)
+ return;
+ string name = tab->getName();
+ std::map<std::string,LLButton*>::iterator tIt = mTabButtons.find(name);
+ if(tIt!=mTabButtons.end())
+ tIt->second->setToggleState(!tIt->second->getToggleState());
+}
+
+bool LLSideTray::selectTabByIndex(size_t index)
+{
+ if(index>=mTabs.size())
+ return false;
+
+ LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(mTabs[index]);
+ if(sidebar_tab == NULL)
+ return false;
+ return selectTabByName(sidebar_tab->getName());
+}
+
+bool LLSideTray::selectTabByName (const std::string& name)
+{
+ LLSideTrayTab* side_bar = getTab(name);
+
+ if(side_bar == mActiveTab)
+ return false;
+ //deselect old tab
+ toggleTabButton(mActiveTab);
+ if(mActiveTab)
+ mActiveTab->setVisible(false);
+
+ //select new tab
+ mActiveTab = side_bar;
+ toggleTabButton(mActiveTab);
+ LLSD key;//empty
+ mActiveTab->onOpen(key);
+
+ mActiveTab->setVisible(true);
+
+ //arrange();
+
+ //hide all tabs - show active tab
+ child_vector_const_iter_t child_it;
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
+ if(sidebar_tab == NULL)
+ continue;
+ sidebar_tab->setVisible(sidebar_tab == mActiveTab);
+ }
+ return true;
+}
+
+LLButton* LLSideTray::createButton (const std::string& name,const std::string& image,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_BOTTOM);
+ bparams.rect (rect);
+ bparams.tab_stop(false);
+ bparams.image_unselected.name(sidetray_params.tab_btn_image_normal);
+ bparams.image_selected.name(sidetray_params.tab_btn_image_selected);
+ bparams.image_disabled.name(sidetray_params.tab_btn_image_normal);
+ bparams.image_disabled_selected.name(sidetray_params.tab_btn_image_selected);
+
+ LLButton* button = LLUICtrlFactory::create<LLButton> (bparams);
+ button->setLabel(name);
+ button->setClickedCallback(callback);
+
+ if(image.length())
+ {
+ button->setImageOverlay(image);
+ }
+
+ addChildInBack(button);
+
+ return button;
+}
+
+bool LLSideTray::addChild(LLView* view, S32 tab_group)
+{
+ LLSideTrayTab* tab_panel = dynamic_cast<LLSideTrayTab*>(view);
+
+ if (tab_panel)
+ {
+ mTabs.push_back(tab_panel);
+ }
+
+ return LLUICtrl::addChild(view, tab_group);
+}
+
+
+void LLSideTray::createButtons ()
+{
+ //create show/hide button
+ mCollapseButton = createButton(EXPANDED_NAME,"",boost::bind(&LLSideTray::onToggleCollapse, this));
+
+ //create buttons for tabs
+ child_vector_const_iter_t child_it = mTabs.begin();
+ ++child_it;
+
+ for ( ; child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
+ if(sidebar_tab == NULL)
+ continue;
+
+ string name = sidebar_tab->getName();
+
+ LLButton* button = createButton("",sidebar_tab->mImagePath,boost::bind(&LLSideTray::onTabButtonClick, this, sidebar_tab->getName()));
+ mTabButtons[sidebar_tab->getName()] = button;
+ }
+
+}
+
+void LLSideTray::onTabButtonClick(string name)
+{
+
+ selectTabByName (name);
+ if(mCollapsed)
+ expandSideBar();
+}
+
+void LLSideTray::onToggleCollapse()
+{
+ if(mCollapsed)
+ {
+ expandSideBar();
+ selectTabByName("sidebar_home");
+ }
+ else
+ collapseSideBar();
+}
+
+
+void LLSideTray::reflectCollapseChange()
+{
+ setPanelRect();
+
+ if(mCollapsed)
+ gFloaterView->setSnapOffsetRight(0);
+ else
+ gFloaterView->setSnapOffsetRight(mMaxBarWidth);
+
+ gFloaterView->refresh();
+
+ setFocus( FALSE );
+}
+
+void LLSideTray::arrange ()
+{
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+
+ setPanelRect();
+
+ LLRect ctrl_rect;
+ ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-sidetray_params.default_button_width
+ ,sidetray_params.default_button_width
+ ,sidetray_params.default_button_height);
+
+ mCollapseButton->setRect(ctrl_rect);
+
+ //arrange tab buttons
+ //arrange tab buttons
+ child_vector_const_iter_t child_it;
+ int offset = (sidetray_params.default_button_height+sidetray_params.default_button_margin)*2;
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
+ if(sidebar_tab == NULL)
+ continue;
+
+ ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-offset
+ ,sidetray_params.default_button_width
+ ,sidetray_params.default_button_height);
+
+ if(mTabButtons.find(sidebar_tab->getName()) == mTabButtons.end())
+ continue;
+
+ LLButton* btn = mTabButtons[sidebar_tab->getName()];
+
+ btn->setRect(ctrl_rect);
+ offset+=sidetray_params.default_button_height;
+ offset+=sidetray_params.default_button_margin;
+
+ btn->setVisible(ctrl_rect.mBottom > 0);
+ }
+
+ ctrl_rect.setLeftTopAndSize(sidetray_params.default_button_width,getRect().getHeight(),mMaxBarWidth,getRect().getHeight());
+
+ //arrange tabs
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
+ if(sidebar_tab == NULL)
+ continue;
+
+ sidebar_tab->setRect(ctrl_rect);
+ sidebar_tab->arrange(mMaxBarWidth,getRect().getHeight());
+ }
+}
+
+void LLSideTray::collapseSideBar ()
+{
+ mCollapsed = true;
+ mCollapseButton->setLabel(COLLAPSED_NAME);
+ mActiveTab->setVisible(FALSE);
+ reflectCollapseChange();
+ setFocus( FALSE );
+
+}
+void LLSideTray::expandSideBar ()
+{
+ mCollapsed = false;
+ mCollapseButton->setLabel(EXPANDED_NAME);
+ LLSD key;//empty
+ mActiveTab->onOpen(key);
+ mActiveTab->setVisible(TRUE);
+
+ reflectCollapseChange();
+
+}
+
+void LLSideTray::highlightFocused()
+{
+ if(!mActiveTab)
+ return;
+ /* uncomment in case something change
+ BOOL dependent_has_focus = gFocusMgr.childHasKeyboardFocus(this);
+ setBackgroundOpaque( dependent_has_focus );
+ mActiveTab->setBackgroundOpaque( dependent_has_focus );
+ */
+ mActiveTab->setBackgroundOpaque( true );
+
+
+}
+//virtual
+BOOL LLSideTray::handleMouseDown (S32 x, S32 y, MASK mask)
+{
+ BOOL ret = LLPanel::handleMouseDown(x,y,mask);
+ if(ret)
+ setFocus(true);
+ return ret;
+}
+void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent)
+{
+
+ LLPanel::reshape(width, height, called_from_parent);
+ if(!mActiveTab)
+ return;
+
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+
+ setPanelRect();
+
+ LLRect ctrl_rect;
+ ctrl_rect.setLeftTopAndSize(0
+ ,getRect().getHeight()-sidetray_params.default_button_width
+ ,sidetray_params.default_button_width
+ ,sidetray_params.default_button_height);
+
+ mCollapseButton->setRect(ctrl_rect);
+
+ //arrange tab buttons
+ child_vector_const_iter_t child_it;
+ int offset = (sidetray_params.default_button_height+sidetray_params.default_button_margin)*2;
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
+ if(sidebar_tab == NULL)
+ continue;
+
+ ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-offset
+ ,sidetray_params.default_button_width
+ ,sidetray_params.default_button_height);
+
+ if(mTabButtons.find(sidebar_tab->getName()) == mTabButtons.end())
+ continue;
+
+ LLButton* btn = mTabButtons[sidebar_tab->getName()];
+
+ btn->setRect(ctrl_rect);
+ offset+=sidetray_params.default_button_height;
+ offset+=sidetray_params.default_button_margin;
+
+ btn->setVisible(ctrl_rect.mBottom > 0);
+ }
+
+ //arrange tabs
+
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
+ if(sidebar_tab == NULL)
+ continue;
+ sidebar_tab->reshape(mMaxBarWidth,getRect().getHeight());
+ ctrl_rect.setLeftTopAndSize(sidetray_params.default_button_width,getRect().getHeight(),mMaxBarWidth,getRect().getHeight());
+ sidebar_tab->setRect(ctrl_rect);
+
+ }
+}
+
+/**
+ * Activate tab with "panel_name" panel
+ * if no such tab - return false, otherwise true.
+ * TODO* In some cases a pointer to a panel of
+ * a specific class may be needed so this method
+ * would need to use templates.
+ */
+LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& params)
+{
+ //arrange tabs
+ child_vector_const_iter_t child_it;
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLView* view = (*child_it)->findChildView(panel_name,true);
+ if(view)
+ {
+ onTabButtonClick((*child_it)->getName());
+
+ 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;
+ }
+ }
+ return NULL;
+}
+
+// *TODO: Eliminate magic constants.
+static const S32 fake_offset = 132;
+static const S32 fake_top_offset = 18;
+
+void LLSideTray::resetPanelRect ()
+{
+ const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
+
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+
+ S32 panel_width = sidetray_params.default_button_width;
+ panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth;
+
+ S32 panel_height = parent_rect.getHeight()-fake_top_offset;
+
+ reshape(panel_width,panel_height);
+}
+
+void LLSideTray::setPanelRect ()
+{
+ LLNavigationBar* nav_bar = LLNavigationBar::getInstance();
+ LLRect nav_rect = nav_bar->getRect();
+
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+
+ const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
+
+ S32 panel_width = sidetray_params.default_button_width;
+ panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth;
+
+ S32 panel_height = parent_rect.getHeight()-fake_top_offset - nav_rect.getHeight();
+ S32 panel_top = parent_rect.mTop-fake_top_offset - nav_rect.getHeight();
+
+ LLRect panel_rect;
+ panel_rect.setLeftTopAndSize( parent_rect.mRight-panel_width, panel_top, panel_width, panel_height);
+ setRect(panel_rect);
+}
+
+S32 LLSideTray::getTrayWidth()
+{
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+ return getRect().getWidth() - (sidetray_params.default_button_width + sidetray_params.default_button_margin);
+}