diff options
Diffstat (limited to 'indra/newview/llsidetray.cpp')
-rw-r--r-- | indra/newview/llsidetray.cpp | 746 |
1 files changed, 746 insertions, 0 deletions
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp new file mode 100644 index 0000000000..e7008abe60 --- /dev/null +++ b/indra/newview/llsidetray.cpp @@ -0,0 +1,746 @@ +/** + * @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 "llsidetray.h" +#include "llviewerwindow.h" +#include "llaccordionpanel.h" +#include "llfocusmgr.h" +#include "llrootview.h" + +#include "llcollapsiblectrl.h" + +#include "llfloater.h" //for gFloaterView +#include "lliconctrl.h"//for Home tab icon +#include "llwindow.h"//for SetCursor +#include "llbottomtray.h"//for reshape + +//#include "llscrollcontainer.h" + +using namespace std; + +static LLRootViewRegistry::Register<LLSideTray> t1("side_tray"); +static LLDefaultWidgetRegistry::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 +{ +protected: + LLSideTrayInfoPanel(){} +public: + static LLSideTrayInfoPanel* createInstance(const string& image, const string& name,const string& description) + { + LLSideTrayInfoPanel* panel = new LLSideTrayInfoPanel(); + LLUICtrlFactory::getInstance()->buildPanel(panel,"panel_sidetray_tab_info.xml"); + if(panel) + panel->setData(image, name,description); + panel->setBorderVisible(true); + return panel; + + } + void setData(const string& image, const string& name,const string& description) + { + getChild<LLTextBox>("tab_name",false,false)->setValue(name); + getChild<LLTextBox>("tab_description",false,false)->setValue(description); + getChild<LLIconCtrl>("tab_icon",false,false)->setValue(image); + } + + BOOL handleHover(S32 x, S32 y, MASK mask) + { + getWindow()->setCursor(UI_CURSOR_HAND); + return TRUE; + } + + BOOL handleMouseUp(S32 x, S32 y, MASK mask) + { + onCommit(); + return LLPanel::handleMouseUp(x,y,mask); + } + +}; + + +LLSideTray* LLSideTray::getInstance() +{ + if (!sInstance) + { + sInstance = LLUICtrlFactory::createFromFile<LLSideTray>("panel_side_tray.xml",gViewerWindow->getRootView()); + } + + return sInstance; +} + +bool LLSideTray::instanceCreated () +{ + return sInstance!=0; +} + +LLSideTrayTab::LLSideTrayTab(const Params& params):mAccordionPanel(0) + +{ + mImagePath = params.image_path; + mTabTitle = params.tab_title; + mDescription = params.tab_description; +} +LLSideTrayTab::~LLSideTrayTab() +{ +} + +void LLSideTrayTab::addPanel(LLPanel* panel) +{ + //addChild(panel,false); +} + +bool LLSideTrayTab::addChild(LLView* view, S32 tab_group) +{ + if(mAccordionPanel == 0) + { + mAccordionPanel = new LLAccordionPanel(); + mAccordionPanel->setVisible(TRUE); + LLPanel::addChild(mAccordionPanel,tab_group); + } + + + bool res = true; + if(TAB_PANEL_CAPTION_NAME != view->getName())//skip our caption panel + { + mAccordionPanel->addCollapsibleCtrl(view); + } + else + res = 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); + string name = title_panel->getName(); + LLPanel::addChild(title_panel); + + title_panel->getChild<LLTextBox>(TAB_PANEL_CAPTION_TITLE_BOX)->setValue(mTabTitle); + + static LLUICachedControl<LLColor4> default_background_color ("FloaterDefaultBackgroundColor", *(new LLColor4)); + static LLUICachedControl<LLColor4> focus_background_color ("FloaterFocusBackgroundColor", *(new LLColor4)); + + setTransparentColor(default_background_color); + setBackgroundColor(focus_background_color); + + return true; +} + +S32 LLSideTrayTab::getMaxSideBarTabWidth() +{ + return (mAccordionPanel)?mAccordionPanel->getMaxPanelWidth():0; +} + +static const S32 splitter_margin = 1; + +//virtual +void LLSideTrayTab::arrange(S32 width, S32 height ) +{ + S32 offset = 0; + + LLView* title_panel = getChildView(TAB_PANEL_CAPTION_NAME, true, false); + + if(title_panel) + { + title_panel->setOrigin( 0, height - title_panel->getRect().getHeight() ); + offset = title_panel->getRect().getHeight(); + } + + LLRect sRect = mAccordionPanel->getRect(); + sRect.setLeftTopAndSize( splitter_margin, height - offset - splitter_margin, width - 2*splitter_margin, height - offset - 2*splitter_margin); + mAccordionPanel->setRect(sRect); + + mAccordionPanel->setMaxWidth(sRect.getWidth()); + mAccordionPanel->arrange(); +} + +void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent ) +{ + if(!mAccordionPanel) + return; + S32 offset = 0; + + LLView* title_panel = getChildView(TAB_PANEL_CAPTION_NAME, true, false); + + 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 = mAccordionPanel->getRect(); + sRect.setLeftTopAndSize( splitter_margin, height - offset - splitter_margin, width - 2*splitter_margin, height - offset - 2*splitter_margin); + mAccordionPanel->setMaxWidth(sRect.getWidth()); + mAccordionPanel->reshape(sRect.getWidth(), sRect.getHeight()); + + mAccordionPanel->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) +{ + mAccordionPanel->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) + :mActiveTab(0) + ,mCollapsed(false) + ,mCollapseButton(0) + ,mMaxBarWidth(0) + ,mHomeTab(0) +{ + mCollapsed=params.collapsed; +} + + +BOOL LLSideTray::postBuild() +{ + calcMaxSideBarWidth(); + + createButtons(); + + createHomeTab(); + + arrange(); + selectTabByName("home_tab"); + + 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,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 == 0 && name == "home_tab") + side_bar = mHomeTab; + + if(side_bar == NULL || 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::Params>()); + + 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; + + for ( child_it = mTabs.begin(); 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("home_tab"); + } + 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::Params>()); + + calcMaxSideBarWidth(); + + + + 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()); + } + + mHomeTab->setRect(ctrl_rect); + mHomeTab->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); + mActiveTab->setVisible(TRUE); + + reflectCollapseChange(); + +} + +void LLSideTray::calcMaxSideBarWidth() +{ + + S32 max_bar_width = 0; + + + 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; + max_bar_width = llmax(max_bar_width,sidebar_tab->getMaxSideBarTabWidth()); + } + + if(max_bar_width > 0) + mMaxBarWidth = max_bar_width; + +} +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::Params>()); + + 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); + + } + + mHomeTab->reshape(mMaxBarWidth,getRect().getHeight()); + ctrl_rect.setLeftTopAndSize(sidetray_params.default_button_width,getRect().getHeight(),mMaxBarWidth,getRect().getHeight()); + mHomeTab->setRect(ctrl_rect); + + +} + +/** + * Activate tab with "panel_name" panel + * if no such tab - return false, otherwise true + */ +bool 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)->getChildView(panel_name,true,false); + if(view) + { + onTabButtonClick((*child_it)->getName()); + LLPanel* panel = dynamic_cast<LLPanel*>(view); + if(panel) + panel->onOpen(params); + return true; + } + } + return false; +} + +void LLSideTray::createHomeTab() +{ + mHomeTab = LLSideTrayTab::createInstance(); + child_vector_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; + + LLPanel* panel = LLSideTrayInfoPanel::createInstance(sidebar_tab->mImagePath,sidebar_tab->getTabTitle(),sidebar_tab->getDescription()); + + panel->setCommitCallback(boost::bind(&LLSideTray::onTabButtonClick, this, sidebar_tab->getName())); + + LLCollapsibleCtrl::Params panel_params; + panel_params.display_children(true); + panel_params.collapsible(false); + panel_params.header_visible(false); + panel_params.can_resize(false); + panel_params.min_height(200); + panel_params.padding_left(10); + panel_params.padding_right(10); + panel_params.padding_top(5); + panel_params.padding_bottom(5); + + LLCollapsibleCtrl* ctrl = LLUICtrlFactory::create<LLCollapsibleCtrl>(panel_params); + + + ctrl->setPanel(panel); + ctrl->postBuild(); + mHomeTab->addChild(ctrl,0); + } + + mHomeTab->setBackgroundVisible(true); + mHomeTab->postBuild(); + + LLUICtrl::addChild(mHomeTab, 0); +} +static const S32 fake_offset = 132; +static const S32 fake_top_offset = 78; + +void LLSideTray::setPanelRect () +{ + static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray::Params>()); + + const LLRect& parent_rect = gViewerWindow->getRootView()->getRect(); + + S32 panel_width = sidetray_params.default_button_width+sidetray_params.default_button_margin; + if(!mCollapsed) + panel_width+=mMaxBarWidth; + + S32 panel_height = parent_rect.getHeight()-fake_top_offset; + panel_height -= LLBottomTray::getInstance()->getRect().getHeight(); + + LLRect panel_rect; + panel_rect.setLeftTopAndSize( parent_rect.mRight-panel_width, parent_rect.mTop-fake_top_offset, panel_width, panel_height); + setRect(panel_rect); +} + +S32 LLSideTray::getTrayWidth() +{ + static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray::Params>()); + return getRect().getWidth() - (sidetray_params.default_button_width + sidetray_params.default_button_margin); +} |