llmultifloater.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:14k
- /**
- * @file llmultifloater.cpp
- * @brief LLFloater that hosts other floaters
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2010, 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$
- */
- // Floating "windows" within the GL display, like the inventory floater,
- // mini-map floater, etc.
- #include "linden_common.h"
- #include "llmultifloater.h"
- #include "llresizehandle.h"
- //
- // LLMultiFloater
- //
- LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params)
- : LLFloater(key),
- mTabContainer(NULL),
- mTabPos(LLTabContainer::TOP),
- mAutoResize(TRUE),
- mOrigMinWidth(0),
- mOrigMinHeight(0)
- {
- }
- void LLMultiFloater::buildTabContainer()
- {
- const LLFloater::Params& default_params = LLFloater::getDefaultParams();
- S32 floater_header_size = default_params.header_height;
-
- LLTabContainer::Params p;
- p.name(std::string("Preview Tabs"));
- p.rect(LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - floater_header_size, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0));
- p.tab_position(mTabPos);
- p.follows.flags(FOLLOWS_ALL);
- p.commit_callback.function(boost::bind(&LLMultiFloater::onTabSelected, this));
- mTabContainer = LLUICtrlFactory::create<LLTabContainer>(p);
- addChild(mTabContainer);
-
- if (isResizable())
- {
- mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
- }
- }
- void LLMultiFloater::onOpen(const LLSD& key)
- {
- // if (mTabContainer->getTabCount() <= 0)
- // {
- // // for now, don't allow multifloaters
- // // without any child floaters
- // closeFloater();
- // }
- }
- void LLMultiFloater::draw()
- {
- if (mTabContainer->getTabCount() == 0)
- {
- //RN: could this potentially crash in draw hierarchy?
- closeFloater();
- }
- else
- {
- LLFloater::draw();
- }
- }
- BOOL LLMultiFloater::closeAllFloaters()
- {
- S32 tabToClose = 0;
- S32 lastTabCount = mTabContainer->getTabCount();
- while (tabToClose < mTabContainer->getTabCount())
- {
- LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose);
- first_floater->closeFloater();
- if(lastTabCount == mTabContainer->getTabCount())
- {
- //Tab did not actually close, possibly due to a pending Save Confirmation dialog..
- //so try and close the next one in the list...
- tabToClose++;
- }
- else
- {
- //Tab closed ok.
- lastTabCount = mTabContainer->getTabCount();
- }
- }
- if( mTabContainer->getTabCount() != 0 )
- return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE.
- return TRUE; //else all tabs were successfully closed...
- }
- void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
- {
- static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
- const LLFloater::Params& default_params = LLFloater::getDefaultParams();
- S32 floater_header_size = default_params.header_height;
- S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
- S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
- S32 new_height = llmax(getRect().getHeight(), content_height + floater_header_size + tabcntr_header_height);
- if (isMinimized())
- {
- LLRect newrect;
- newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height);
- setExpandedRect(newrect);
- }
- else
- {
- S32 old_height = getRect().getHeight();
- reshape(new_width, new_height);
- // keep top left corner in same position
- translate(0, old_height - new_height);
- }
- }
- /**
- void addFloater(LLFloater* floaterp, BOOL select_added_floater)
- Adds the LLFloater pointed to by floaterp to this.
- If floaterp is already hosted by this, then it is re-added to get
- new titles, etc.
- If select_added_floater is true, the LLFloater pointed to by floaterp will
- become the selected tab in this
- Affects: mTabContainer, floaterp
- **/
- void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point)
- {
- if (!floaterp)
- {
- return;
- }
- if (!mTabContainer)
- {
- llerrs << "Tab Container used without having been initialized." << llendl;
- return;
- }
- if (floaterp->getHost() == this)
- {
- // already hosted by me, remove
- // do this so we get updated title, etc.
- mFloaterDataMap.erase(floaterp->getHandle());
- mTabContainer->removeTabPanel(floaterp);
- }
- else if (floaterp->getHost())
- {
- // floaterp is hosted by somebody else and
- // this is adding it, so remove it from it's old host
- floaterp->getHost()->removeFloater(floaterp);
- }
- else if (floaterp->getParent() == gFloaterView)
- {
- // rehost preview floater as child panel
- gFloaterView->removeChild(floaterp);
- }
- // store original configuration
- LLFloaterData floater_data;
- floater_data.mWidth = floaterp->getRect().getWidth();
- floater_data.mHeight = floaterp->getRect().getHeight();
- floater_data.mCanMinimize = floaterp->isMinimizeable();
- floater_data.mCanResize = floaterp->isResizable();
- // remove minimize and close buttons
- floaterp->setCanMinimize(FALSE);
- floaterp->setCanResize(FALSE);
- floaterp->setCanDrag(FALSE);
- floaterp->storeRectControl();
- // avoid double rendering of floater background (makes it more opaque)
- floaterp->setBackgroundVisible(FALSE);
- if (mAutoResize)
- {
- growToFit(floater_data.mWidth, floater_data.mHeight);
- }
- //add the panel, add it to proper maps
- mTabContainer->addTabPanel(
- LLTabContainer::TabPanelParams()
- .panel(floaterp)
- .label(floaterp->getShortTitle())
- .insert_at(insertion_point));
- mFloaterDataMap[floaterp->getHandle()] = floater_data;
- updateResizeLimits();
- if ( select_added_floater )
- {
- mTabContainer->selectTabPanel(floaterp);
- }
- else
- {
- // reassert visible tab (hiding new floater if necessary)
- mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
- }
- floaterp->setHost(this);
- if (isMinimized())
- {
- floaterp->setVisible(FALSE);
- }
-
- // Tabs sometimes overlap resize handle
- moveResizeHandlesToFront();
- }
- /**
- BOOL selectFloater(LLFloater* floaterp)
- If the LLFloater pointed to by floaterp is hosted by this,
- then its tab is selected and returns true. Otherwise returns false.
- Affects: mTabContainer
- **/
- BOOL LLMultiFloater::selectFloater(LLFloater* floaterp)
- {
- return mTabContainer->selectTabPanel(floaterp);
- }
- // virtual
- void LLMultiFloater::selectNextFloater()
- {
- mTabContainer->selectNextTab();
- }
- // virtual
- void LLMultiFloater::selectPrevFloater()
- {
- mTabContainer->selectPrevTab();
- }
- void LLMultiFloater::showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point)
- {
- if(!floaterp) return;
- // we won't select a panel that already is selected
- // it is hard to do this internally to tab container
- // as tab selection is handled via index and the tab at a given
- // index might have changed
- if (floaterp != mTabContainer->getCurrentPanel() &&
- !mTabContainer->selectTabPanel(floaterp))
- {
- addFloater(floaterp, TRUE, insertion_point);
- }
- }
- void LLMultiFloater::removeFloater(LLFloater* floaterp)
- {
- if (!floaterp || floaterp->getHost() != this )
- return;
- floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle());
- if (found_data_it != mFloaterDataMap.end())
- {
- LLFloaterData& floater_data = found_data_it->second;
- floaterp->setCanMinimize(floater_data.mCanMinimize);
- if (!floater_data.mCanResize)
- {
- // restore original size
- floaterp->reshape(floater_data.mWidth, floater_data.mHeight);
- }
- floaterp->setCanResize(floater_data.mCanResize);
- mFloaterDataMap.erase(found_data_it);
- }
- mTabContainer->removeTabPanel(floaterp);
- floaterp->setBackgroundVisible(TRUE);
- floaterp->setCanDrag(TRUE);
- floaterp->setHost(NULL);
- floaterp->applyRectControl();
- updateResizeLimits();
- tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
- }
- void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click)
- {
- // default implementation does nothing
- }
- void LLMultiFloater::tabClose()
- {
- if (mTabContainer->getTabCount() == 0)
- {
- // no more children, close myself
- closeFloater();
- }
- }
- void LLMultiFloater::setVisible(BOOL visible)
- {
- // *FIX: shouldn't have to do this, fix adding to minimized multifloater
- LLFloater::setVisible(visible);
-
- if (mTabContainer)
- {
- LLPanel* cur_floaterp = mTabContainer->getCurrentPanel();
- if (cur_floaterp)
- {
- cur_floaterp->setVisible(visible);
- }
- // if no tab selected, and we're being shown,
- // select last tab to be added
- if (visible && !cur_floaterp)
- {
- mTabContainer->selectLastTab();
- }
- }
- }
- BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask)
- {
- if (key == 'W' && mask == MASK_CONTROL)
- {
- LLFloater* floater = getActiveFloater();
- // is user closeable and is system closeable
- if (floater && floater->canClose() && floater->isCloseable())
- {
- floater->closeFloater();
- }
- return TRUE;
- }
- return LLFloater::handleKeyHere(key, mask);
- }
- bool LLMultiFloater::addChild(LLView* child, S32 tab_group)
- {
- LLTabContainer* tab_container = dynamic_cast<LLTabContainer*>(child);
- if (tab_container)
- {
- // store pointer to tab container
- setTabContainer(tab_container);
- }
- // then go ahead and add child as usual
- return LLFloater::addChild(child, tab_group);
- }
- LLFloater* LLMultiFloater::getActiveFloater()
- {
- return (LLFloater*)mTabContainer->getCurrentPanel();
- }
- S32 LLMultiFloater::getFloaterCount()
- {
- return mTabContainer->getTabCount();
- }
- /**
- BOOL isFloaterFlashing(LLFloater* floaterp)
- Returns true if the LLFloater pointed to by floaterp
- is currently in a flashing state and is hosted by this.
- False otherwise.
- Requires: floaterp != NULL
- **/
- BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp)
- {
- if ( floaterp && floaterp->getHost() == this )
- return mTabContainer->getTabPanelFlashing(floaterp);
- return FALSE;
- }
- /**
- BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
- Sets the current flashing state of the LLFloater pointed
- to by floaterp to be the BOOL flashing if the LLFloater pointed
- to by floaterp is hosted by this.
- Requires: floaterp != NULL
- **/
- void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
- {
- if ( floaterp && floaterp->getHost() == this )
- mTabContainer->setTabPanelFlashing(floaterp, flashing);
- }
- void LLMultiFloater::onTabSelected()
- {
- LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getCurrentPanel());
- if (floaterp)
- {
- tabOpen(floaterp, true);
- }
- }
- void LLMultiFloater::setCanResize(BOOL can_resize)
- {
- LLFloater::setCanResize(can_resize);
- if (!mTabContainer) return;
- if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
- {
- mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
- }
- else
- {
- mTabContainer->setRightTabBtnOffset(0);
- }
- }
- BOOL LLMultiFloater::postBuild()
- {
- mCloseSignal.connect(boost::bind(&LLMultiFloater::closeAllFloaters, this));
-
- // remember any original xml minimum size
- getResizeLimits(&mOrigMinWidth, &mOrigMinHeight);
- if (mTabContainer)
- {
- return TRUE;
- }
- mTabContainer = getChild<LLTabContainer>("Preview Tabs");
-
- setCanResize(mResizable);
- return TRUE;
- }
- void LLMultiFloater::updateResizeLimits()
- {
- static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
- const LLFloater::Params& default_params = LLFloater::getDefaultParams();
- S32 floater_header_size = default_params.header_height;
- S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
- // initialize minimum size constraint to the original xml values.
- S32 new_min_width = mOrigMinWidth;
- S32 new_min_height = mOrigMinHeight;
- // possibly increase minimum size constraint due to children's minimums.
- for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
- {
- LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
- if (floaterp)
- {
- new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
- new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height);
- }
- }
- setResizeLimits(new_min_width, new_min_height);
- S32 cur_height = getRect().getHeight();
- S32 new_width = llmax(getRect().getWidth(), new_min_width);
- S32 new_height = llmax(getRect().getHeight(), new_min_height);
- if (isMinimized())
- {
- const LLRect& expanded = getExpandedRect();
- LLRect newrect;
- newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height));
- setExpandedRect(newrect);
- }
- else
- {
- reshape(new_width, new_height);
- // make sure upper left corner doesn't move
- translate(0, cur_height - getRect().getHeight());
- // make sure this window is visible on screen when it has been modified
- // (tab added, etc)
- gFloaterView->adjustToFitScreen(this, TRUE);
- }
- }