diff options
Diffstat (limited to 'indra/llui/llfloater.cpp')
-rw-r--r-- | indra/llui/llfloater.cpp | 252 |
1 files changed, 183 insertions, 69 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 0199fe3f57..eb5d7a6b6a 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2,31 +2,25 @@ * @file llfloater.cpp * @brief LLFloater base class * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * 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 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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 + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * 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. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -169,6 +163,7 @@ LLFloater::Params::Params() save_rect("save_rect", false), save_visibility("save_visibility", false), can_dock("can_dock", false), + open_centered("open_centered", false), header_height("header_height", 0), legacy_header_height("legacy_header_height", 0), close_image("close_image"), @@ -329,6 +324,7 @@ void LLFloater::addDragHandle() addChild(mDragHandle); } layoutDragHandle(); + applyTitle(); } void LLFloater::layoutDragHandle() @@ -345,9 +341,8 @@ void LLFloater::layoutDragHandle() { rect = getLocalRect(); } - mDragHandle->setRect(rect); - updateButtons(); - applyTitle(); + mDragHandle->setShape(rect); + updateTitleButtons(); } void LLFloater::addResizeCtrls() @@ -450,6 +445,14 @@ void LLFloater::enableResizeCtrls(bool enable) } } +void LLFloater::destroy() +{ + // LLFloaterReg should be synchronized with "dead" floater to avoid returning dead instance before + // it was deleted via LLMortician::updateClass(). See EXT-8458. + LLFloaterReg::removeInstance(mInstanceName, mKey); + die(); +} + // virtual LLFloater::~LLFloater() { @@ -496,7 +499,7 @@ void LLFloater::storeRectControl() { if( mRectControl.size() > 1 ) { - LLUI::sSettingGroups["floater"]->setRect( mRectControl, getRect() ); + getControlGroup()->setRect( mRectControl, getRect() ); } } @@ -504,7 +507,7 @@ void LLFloater::storeVisibilityControl() { if( !sQuitting && mVisibilityControl.size() > 1 ) { - LLUI::sSettingGroups["floater"]->setBOOL( mVisibilityControl, getVisible() ); + getControlGroup()->setBOOL( mVisibilityControl, getVisible() ); } } @@ -512,10 +515,47 @@ void LLFloater::storeDockStateControl() { if( !sQuitting && mDocStateControl.size() > 1 ) { - LLUI::sSettingGroups["floater"]->setBOOL( mDocStateControl, isDocked() ); + getControlGroup()->setBOOL( mDocStateControl, isDocked() ); } } +LLRect LLFloater::getSavedRect() const +{ + LLRect rect; + + if (mRectControl.size() > 1) + { + rect = getControlGroup()->getRect(mRectControl); + } + + return rect; +} + +bool LLFloater::hasSavedRect() const +{ + return !getSavedRect().isEmpty(); +} + +// static +std::string LLFloater::getControlName(const std::string& name, const LLSD& key) +{ + std::string ctrl_name = name; + + // Add the key to the control name if appropriate. + if (key.isString() && !key.asString().empty()) + { + ctrl_name += "_" + key.asString(); + } + + return ctrl_name; +} + +// static +LLControlGroup* LLFloater::getControlGroup() +{ + // Floater size, position, visibility, etc are saved in per-account settings. + return LLUI::sSettingGroups["account"]; +} void LLFloater::setVisible( BOOL visible ) { @@ -527,10 +567,7 @@ void LLFloater::setVisible( BOOL visible ) if( !visible ) { - if( gFocusMgr.childIsTopCtrl( this ) ) - { - gFocusMgr.setTopCtrl(NULL); - } + LLUI::removePopup(this); if( gFocusMgr.childHasMouseCapture( this ) ) { @@ -566,6 +603,7 @@ void LLFloater::handleVisibilityChange ( BOOL new_visibility ) void LLFloater::openFloater(const LLSD& key) { + llinfos << "Opening floater " << getName() << llendl; mKey = key; // in case we need to open ourselves again if (getSoundFlags() != SILENT @@ -606,6 +644,7 @@ void LLFloater::openFloater(const LLSD& key) void LLFloater::closeFloater(bool app_quitting) { + llinfos << "Closing floater " << getName() << llendl; if (app_quitting) { LLFloater::sQuitting = true; @@ -704,10 +743,7 @@ void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent) void LLFloater::releaseFocus() { - if( gFocusMgr.childIsTopCtrl( this ) ) - { - gFocusMgr.setTopCtrl(NULL); - } + LLUI::removePopup(this); setFocus(FALSE); @@ -767,9 +803,16 @@ void LLFloater::applySavedVariables() void LLFloater::applyRectControl() { + // first, center on screen if requested + if (mOpenCentered) + { + center(); + } + + // override center if we have saved rect control if (mRectControl.size() > 1) { - const LLRect& rect = LLUI::sSettingGroups["floater"]->getRect(mRectControl); + const LLRect& rect = getControlGroup()->getRect(mRectControl); if (rect.getWidth() > 0 && rect.getHeight() > 0) { translate( rect.mLeft - getRect().mLeft, rect.mBottom - getRect().mBottom); @@ -785,7 +828,7 @@ void LLFloater::applyDockState() { if (mDocStateControl.size() > 1) { - bool dockState = LLUI::sSettingGroups["floater"]->getBOOL(mDocStateControl); + bool dockState = getControlGroup()->getBOOL(mDocStateControl); setDocked(dockState); } @@ -806,6 +849,11 @@ void LLFloater::applyTitle() { mDragHandle->setTitle ( mTitle ); } + + if (getHost()) + { + getHost()->updateFloaterTitle(this); + } } std::string LLFloater::getCurrentTitle() const @@ -1067,11 +1115,10 @@ void LLFloater::setMinimized(BOOL minimize) // Reshape *after* setting mMinimized reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); } - - applyTitle (); make_ui_sound("UISndWindowClose"); - updateButtons(); + updateTitleButtons(); + applyTitle (); } void LLFloater::setFocus( BOOL b ) @@ -1127,6 +1174,7 @@ void LLFloater::setIsChrome(BOOL is_chrome) setFocus(FALSE); // can't Ctrl-Tab to "chrome" floaters setFocusRoot(FALSE); + mButtons[BUTTON_CLOSE]->setToolTip(LLStringExplicit(getButtonTooltip(Params(), BUTTON_CLOSE, is_chrome))); } // no titles displayed on "chrome" floaters @@ -1196,7 +1244,7 @@ void LLFloater::setHost(LLMultiFloater* host) mButtonScale = 1.f; //mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE; } - updateButtons(); + updateTitleButtons(); if (host) { mHostHandle = host->getHandle(); @@ -1360,7 +1408,6 @@ void LLFloater::bringToFront( S32 x, S32 y ) // virtual void LLFloater::setVisibleAndFrontmost(BOOL take_focus) { - gFocusMgr.setTopCtrl(NULL); setVisible(TRUE); setFrontmost(take_focus); } @@ -1396,7 +1443,7 @@ void LLFloater::setCanDock(bool b) mButtonsEnabled[BUTTON_DOCK] = FALSE; } } - updateButtons(); + updateTitleButtons(); } void LLFloater::setDocked(bool docked, bool pop_on_undock) @@ -1405,7 +1452,7 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock) { mDocked = docked; mButtonsEnabled[BUTTON_DOCK] = !mDocked; - updateButtons(); + updateTitleButtons(); storeDockStateControl(); } @@ -1458,7 +1505,7 @@ void LLFloater::onClickTearOff(LLFloater* self) } self->setTornOff(false); } - self->updateButtons(); + self->updateTitleButtons(); } // static @@ -1554,7 +1601,12 @@ void LLFloater::onClickClose( LLFloater* self ) { if (!self) return; - self->closeFloater(false); + self->onClickCloseBtn(); +} + +void LLFloater::onClickCloseBtn() +{ + closeFloater(false); } @@ -1574,22 +1626,25 @@ void LLFloater::draw() LLUIImage* image = NULL; LLColor4 color; + LLColor4 overlay_color; if (isBackgroundOpaque()) { // NOTE: image may not be set image = getBackgroundImage(); color = getBackgroundColor(); + overlay_color = getBackgroundImageOverlay(); } else { image = getTransparentImage(); color = getTransparentColor(); + overlay_color = getTransparentImageOverlay(); } if (image) { // We're using images for this floater's backgrounds - image->draw(getLocalRect(), UI_VERTEX_COLOR % alpha); + image->draw(getLocalRect(), overlay_color % alpha); } else { @@ -1690,7 +1745,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize) mButtonsEnabled[BUTTON_MINIMIZE] = can_minimize && !isMinimized(); mButtonsEnabled[BUTTON_RESTORE] = can_minimize && isMinimized(); - updateButtons(); + updateTitleButtons(); } void LLFloater::setCanClose(BOOL can_close) @@ -1698,7 +1753,7 @@ void LLFloater::setCanClose(BOOL can_close) mCanClose = can_close; mButtonsEnabled[BUTTON_CLOSE] = can_close; - updateButtons(); + updateTitleButtons(); } void LLFloater::setCanTearOff(BOOL can_tear_off) @@ -1706,7 +1761,7 @@ void LLFloater::setCanTearOff(BOOL can_tear_off) mCanTearOff = can_tear_off; mButtonsEnabled[BUTTON_TEAR_OFF] = mCanTearOff && !mHostHandle.isDead(); - updateButtons(); + updateTitleButtons(); } @@ -1730,10 +1785,11 @@ void LLFloater::setCanDrag(BOOL can_drag) } } -void LLFloater::updateButtons() +void LLFloater::updateTitleButtons() { static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0); static LLUICachedControl<S32> close_box_from_top ("UICloseBoxFromTop", 0); + LLRect buttons_rect; S32 button_count = 0; for (S32 i = 0; i < BUTTON_COUNT; i++) { @@ -1784,6 +1840,18 @@ void LLFloater::updateButtons() llround((F32)floater_close_box_size * mButtonScale)); } + // first time here, init 'buttons_rect' + if(1 == button_count) + { + buttons_rect = btn_rect; + } + else + { + // if mDragOnLeft=true then buttons are on top-left side vertically aligned + // title is not displayed in this case, calculating 'buttons_rect' for future use + mDragOnLeft ? buttons_rect.mBottom -= btn_rect.mBottom : + buttons_rect.mLeft = btn_rect.mLeft; + } mButtons[i]->setRect(btn_rect); mButtons[i]->setVisible(TRUE); // the restore button should have a tab stop so that it takes action when you Ctrl-Tab to a minimized floater @@ -1795,7 +1863,10 @@ void LLFloater::updateButtons() } } if (mDragHandle) - mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (floater_close_box_size + 1))); + { + localRectToOtherView(buttons_rect, &buttons_rect, mDragHandle); + mDragHandle->setButtonsRect(buttons_rect); + } } void LLFloater::buildButtons(const Params& floater_params) @@ -1843,7 +1914,7 @@ void LLFloater::buildButtons(const Params& floater_params) p.click_callback.function(boost::bind(sButtonCallbacks[i], this)); p.tab_stop(false); p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); - p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i); + p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i, getIsChrome()); p.scale_image(true); p.chrome(true); @@ -1852,7 +1923,7 @@ void LLFloater::buildButtons(const Params& floater_params) mButtons[i] = buttonp; } - updateButtons(); + updateTitleButtons(); } // static @@ -1898,8 +1969,15 @@ LLUIImage* LLFloater::getButtonPressedImage(const Params& p, EFloaterButton e) } // static -std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e) +std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e, bool is_chrome) { + // EXT-4081 (Lag Meter: Ctrl+W does not close floater) + // If floater is chrome set 'Close' text for close button's tooltip + if(is_chrome && BUTTON_CLOSE == e) + { + static std::string close_tooltip_chrome = LLTrans::getString("BUTTON_CLOSE_CHROME"); + return close_tooltip_chrome; + } // TODO: per-floater localizable tooltips set in XML return sButtonToolTips[e]; } @@ -1913,6 +1991,7 @@ LLFloaterView::LLFloaterView (const Params& p) : LLUICtrl (p), mFocusCycleMode(FALSE), + mMinimizePositionVOffset(0), mSnapOffsetBottom(0), mSnapOffsetRight(0) { @@ -2238,6 +2317,7 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) S32 floater_header_size = default_params.header_height; static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0); LLRect snap_rect_local = getLocalSnapRect(); + snap_rect_local.mTop += mMinimizePositionVOffset; for(S32 col = snap_rect_local.mLeft; col < snap_rect_local.getWidth() - minimized_width; col += minimized_width) @@ -2310,7 +2390,9 @@ void LLFloaterView::closeAllChildren(bool app_quitting) // Attempt to close floater. This will cause the "do you want to save" // dialogs to appear. - if (floaterp->canClose() && !floaterp->isDead()) + // Skip invisible floaters if we're not quitting (STORM-192). + if (floaterp->canClose() && !floaterp->isDead() && + (app_quitting || floaterp->getVisible())) { floaterp->closeFloater(app_quitting); } @@ -2335,6 +2417,19 @@ BOOL LLFloaterView::allChildrenClosed() return true; } +void LLFloaterView::shiftFloaters(S32 x_offset, S32 y_offset) +{ + for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it) + { + LLFloater* floaterp = dynamic_cast<LLFloater*>(*it); + + if (floaterp && floaterp->isMinimized()) + { + floaterp->translate(x_offset, y_offset); + } + } +} + void LLFloaterView::refresh() { // Constrain children to be entirely on the screen @@ -2387,10 +2482,17 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out LLRect new_rect; new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height); - floater->reshape( new_width, new_height, TRUE ); - floater->setRect(new_rect); + floater->setShape(new_rect); + + if (floater->followsRight()) + { + floater->translate(old_width - new_width, 0); + } - floater->translateIntoRect( getLocalRect(), false ); + if (floater->followsTop()) + { + floater->translate(0, old_height - new_height); + } } } @@ -2478,7 +2580,7 @@ LLFloater *LLFloaterView::getBackmost() const void LLFloaterView::syncFloaterTabOrder() { - // look for a visible modal dialog, starting from first (should be only one) + // look for a visible modal dialog, starting from first LLModalDialog* modal_dialog = NULL; for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2493,10 +2595,7 @@ void LLFloaterView::syncFloaterTabOrder() if (modal_dialog) { // If we have a visible modal dialog, make sure that it has focus - if( gFocusMgr.getTopCtrl() != modal_dialog ) - { - gFocusMgr.setTopCtrl( modal_dialog ); - } + LLUI::addPopup(modal_dialog); if( !gFocusMgr.childHasKeyboardFocus( modal_dialog ) ) { @@ -2605,18 +2704,20 @@ void LLFloater::setInstanceName(const std::string& name) mInstanceName = name; if (!mInstanceName.empty()) { + std::string ctrl_name = getControlName(mInstanceName, mKey); + // save_rect and save_visibility only apply to registered floaters if (!mRectControl.empty()) { - mRectControl = LLFloaterReg::declareRectControl(mInstanceName); + mRectControl = LLFloaterReg::declareRectControl(ctrl_name); } if (!mVisibilityControl.empty()) { - mVisibilityControl = LLFloaterReg::declareVisibilityControl(mInstanceName); + mVisibilityControl = LLFloaterReg::declareVisibilityControl(ctrl_name); } if(!mDocStateControl.empty()) { - mDocStateControl = LLFloaterReg::declareDockStateControl(mInstanceName); + mDocStateControl = LLFloaterReg::declareDockStateControl(ctrl_name); } } @@ -2681,6 +2782,7 @@ void LLFloater::initFromParams(const LLFloater::Params& p) mLegacyHeaderHeight = p.legacy_header_height; mSingleInstance = p.single_instance; mAutoTile = p.auto_tile; + mOpenCentered = p.open_centered; if (p.save_rect) { @@ -2710,10 +2812,10 @@ void LLFloater::initFromParams(const LLFloater::Params& p) LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build"); -bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) +bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node) { Params params(LLUICtrlFactory::getDefaultParams<LLFloater>()); - LLXUIParser::instance().readXUI(node, params); // *TODO: Error checking + LLXUIParser::instance().readXUI(node, params, filename); // *TODO: Error checking if (output_node) { @@ -2805,3 +2907,15 @@ bool LLFloater::isShown(const LLFloater* floater) { return floater && floater->isShown(); } + +/* static */ +bool LLFloater::isMinimized(const LLFloater* floater) +{ + return floater && floater->isMinimized(); +} + +/* static */ +bool LLFloater::isVisible(const LLFloater* floater) +{ + return floater && floater->getVisible(); +} |