summaryrefslogtreecommitdiff
path: root/indra/llui/lllayoutstack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/lllayoutstack.cpp')
-rw-r--r--indra/llui/lllayoutstack.cpp214
1 files changed, 169 insertions, 45 deletions
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 39dac296ea..0ff7557ead 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -2,31 +2,25 @@
* @file lllayoutstack.cpp
* @brief LLLayout class - dynamic stacking of UI elements
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&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.
*
- * 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 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.
*
- * 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.
+ * 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.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,10 +29,13 @@
#include "linden_common.h"
#include "lllayoutstack.h"
+
+#include "lllocalcliprect.h"
+#include "llpanel.h"
#include "llresizebar.h"
#include "llcriticaldamp.h"
-static LLDefaultWidgetRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack", &LLLayoutStack::fromXML);
+static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack", &LLLayoutStack::fromXML);
//
@@ -46,9 +43,11 @@ static LLDefaultWidgetRegistry::Register<LLLayoutStack> register_layout_stack("l
//
struct LLLayoutStack::LayoutPanel
{
- LayoutPanel(LLPanel* panelp, ELayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) : mPanel(panelp),
+ LayoutPanel(LLPanel* panelp, ELayoutOrientation orientation, S32 min_width, S32 min_height, S32 max_width, S32 max_height, BOOL auto_resize, BOOL user_resize) : mPanel(panelp),
mMinWidth(min_width),
mMinHeight(min_height),
+ mMaxWidth(max_width),
+ mMaxHeight(max_height),
mAutoResize(auto_resize),
mUserResize(user_resize),
mOrientation(orientation),
@@ -109,6 +108,11 @@ struct LLLayoutStack::LayoutPanel
LLPanel* mPanel;
S32 mMinWidth;
S32 mMinHeight;
+
+ // mMaxWidth & mMaxHeight are added to make configurable max width of the nearby chat bar. EXT-5589
+ // they are not processed by LLLayoutStack but they can be if necessary
+ S32 mMaxWidth;
+ S32 mMaxHeight;
BOOL mAutoResize;
BOOL mUserResize;
BOOL mCollapsed;
@@ -120,7 +124,8 @@ struct LLLayoutStack::LayoutPanel
LLLayoutStack::Params::Params()
: orientation("orientation", std::string("vertical")),
- animate("animate", TRUE),
+ animate("animate", true),
+ clip("clip", true),
border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))
{
name="stack";
@@ -132,7 +137,9 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
mMinHeight(0),
mPanelSpacing(p.border_size),
mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL),
- mAnimate(p.animate)
+ mAnimate(p.animate),
+ mAnimatedThisFrame(false),
+ mClip(p.clip)
{}
LLLayoutStack::~LLLayoutStack()
@@ -163,10 +170,11 @@ void LLLayoutStack::draw()
LLPanel* panelp = (*panel_it)->mPanel;
- LLLocalClipRect clip(clip_rect);
+ LLLocalClipRect clip(clip_rect, mClip);
// only force drawing invisible children if visible amount is non-zero
- drawChild(panelp, 0, 0, !clip_rect.isNull());
+ drawChild(panelp, 0, 0, !clip_rect.isEmpty());
}
+ mAnimatedThisFrame = false;
}
void LLLayoutStack::removeChild(LLView* view)
@@ -223,8 +231,8 @@ static void get_attribute_bool_and_write(LLXMLNodePtr node,
//static
LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
- LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams<LLLayoutStack::Params>());
- LLXUIParser::instance().readXUI(node, p);
+ LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams<LLLayoutStack>());
+ LLXUIParser::instance().readXUI(node, p, LLUICtrlFactory::getInstance()->getCurFileName());
// Export must happen before setupParams() mungles rectangles and before
// this item gets added to parent (otherwise screws up last_child_rect
@@ -233,13 +241,14 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
{
Params output_params(p);
setupParamsForExport(output_params, parent);
- LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams<LLLayoutStack::Params>());
+ LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams<LLLayoutStack>());
output_node->setName(node->getName()->mString);
LLXUIParser::instance().writeXUI(
output_node, output_params, &default_params);
}
- setupParams(p, parent);
+ p.from_xui = true;
+ applyXUILayout(p, parent);
LLLayoutStack* layout_stackp = LLUICtrlFactory::create<LLLayoutStack>(p);
if (parent && layout_stackp)
@@ -253,10 +262,14 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
{
const S32 DEFAULT_MIN_WIDTH = 0;
const S32 DEFAULT_MIN_HEIGHT = 0;
+ const S32 DEFAULT_MAX_WIDTH = S32_MAX;
+ const S32 DEFAULT_MAX_HEIGHT = S32_MAX;
const BOOL DEFAULT_AUTO_RESIZE = TRUE;
S32 min_width = DEFAULT_MIN_WIDTH;
S32 min_height = DEFAULT_MIN_HEIGHT;
+ S32 max_width = DEFAULT_MAX_WIDTH;
+ S32 max_height = DEFAULT_MAX_HEIGHT;
BOOL auto_resize = DEFAULT_AUTO_RESIZE;
LLXMLNodePtr output_child;
@@ -273,6 +286,10 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
DEFAULT_MIN_WIDTH, output_child);
get_attribute_s32_and_write(child_node, "min_height", &min_height,
DEFAULT_MIN_HEIGHT, output_child);
+ get_attribute_s32_and_write(child_node, "max_width", &max_width,
+ DEFAULT_MAX_WIDTH, output_child);
+ get_attribute_s32_and_write(child_node, "max_height", &max_height,
+ DEFAULT_MAX_HEIGHT, output_child);
get_attribute_bool_and_write(child_node, "auto_resize", &auto_resize,
DEFAULT_AUTO_RESIZE, output_child);
@@ -285,7 +302,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
if (panelp)
{
panelp->setFollowsNone();
- layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
+ layout_stackp->addPanel(panelp, min_width, min_height, max_width, max_height, auto_resize, user_resize);
}
}
else
@@ -295,12 +312,13 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
FALSE, output_child);
LLPanel::Params p;
+ p.mouse_opaque(false);
LLPanel* panelp = LLUICtrlFactory::create<LLPanel>(p);
- LLView* new_child = LLUICtrlFactory::getInstance()->createFromXML(child_node, panelp, LLStringUtil::null, output_child, parent ? parent->getChildRegistry() : LLDefaultWidgetRegistry::instance());
+ LLView* new_child = LLUICtrlFactory::getInstance()->createFromXML(child_node, panelp, LLStringUtil::null, LLPanel::child_registry_t::instance(), output_child);
if (new_child)
{
// put child in new embedded panel
- layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
+ layout_stackp->addPanel(panelp, min_width, min_height, max_width, max_height, auto_resize, user_resize);
// resize panel to contain widget and move widget to be contained in panel
panelp->setRect(new_child->getRect());
new_child->setOrigin(0, 0);
@@ -350,14 +368,30 @@ S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
return cur_width;
}
-void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
+void LLLayoutStack::movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front)
+{
+ LayoutPanel* embedded_panel_to_move = findEmbeddedPanel(panel_to_move);
+ LayoutPanel* embedded_target_panel = move_to_front ? *mPanels.begin() : findEmbeddedPanel(target_panel);
+
+ if (!embedded_panel_to_move || !embedded_target_panel || embedded_panel_to_move == embedded_target_panel)
+ {
+ llwarns << "One of the panels was not found in stack or NULL was passed instead of valid panel" << llendl;
+ return;
+ }
+ e_panel_list_t::iterator it = std::find(mPanels.begin(), mPanels.end(), embedded_panel_to_move);
+ mPanels.erase(it);
+ it = move_to_front ? mPanels.begin() : std::find(mPanels.begin(), mPanels.end(), embedded_target_panel);
+ mPanels.insert(it, embedded_panel_to_move);
+}
+
+void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, S32 max_width, S32 max_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
{
// panel starts off invisible (collapsed)
if (animate == ANIMATE)
{
panel->setVisible(FALSE);
}
- LayoutPanel* embedded_panel = new LayoutPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
+ LayoutPanel* embedded_panel = new LayoutPanel(panel, mOrientation, min_width, min_height, max_width, max_height, auto_resize, user_resize);
mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
@@ -395,8 +429,56 @@ void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
panel_container->mCollapsed = collapsed;
}
+void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize)
+{
+ LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+ if (panel)
+ {
+ panel->mAutoResize = auto_resize;
+ }
+}
+
+void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize)
+{
+ LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+ if (panel)
+ {
+ panel->mUserResize = user_resize;
+ }
+}
+
+bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp)
+{
+ LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+ if (panel)
+ {
+ if (min_widthp) *min_widthp = panel->mMinWidth;
+ if (min_heightp) *min_heightp = panel->mMinHeight;
+ }
+
+ return NULL != panel;
+}
+
+bool LLLayoutStack::getPanelMaxSize(const std::string& panel_name, S32* max_widthp, S32* max_heightp)
+{
+ LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+ if (panel)
+ {
+ if (max_widthp) *max_widthp = panel->mMaxWidth;
+ if (max_heightp) *max_heightp = panel->mMaxHeight;
+ }
+
+ return NULL != panel;
+}
+
+static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks");
void LLLayoutStack::updateLayout(BOOL force_resize)
{
+ LLFastTimer ft(FTM_UPDATE_LAYOUT);
static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0);
calcMinExtents();
@@ -415,10 +497,13 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
if (mAnimate)
{
- (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
- if ((*panel_it)->mVisibleAmt > 0.99f)
+ if (!mAnimatedThisFrame)
{
- (*panel_it)->mVisibleAmt = 1.f;
+ (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
+ if ((*panel_it)->mVisibleAmt > 0.99f)
+ {
+ (*panel_it)->mVisibleAmt = 1.f;
+ }
}
}
else
@@ -430,10 +515,13 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
if (mAnimate)
{
- (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
- if ((*panel_it)->mVisibleAmt < 0.001f)
+ if (!mAnimatedThisFrame)
{
- (*panel_it)->mVisibleAmt = 0.f;
+ (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
+ if ((*panel_it)->mVisibleAmt < 0.001f)
+ {
+ (*panel_it)->mVisibleAmt = 0.f;
+ }
}
}
else
@@ -615,10 +703,10 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
// adjust running headroom count based on new sizes
shrink_headroom_total += delta_size;
- panelp->reshape(new_width, new_height);
- panelp->setOrigin(cur_x, cur_y - new_height);
+ LLRect panel_rect;
+ panel_rect.setLeftTopAndSize(cur_x, cur_y, new_width, new_height);
+ panelp->setShape(panel_rect);
- LLRect panel_rect = panelp->getRect();
LLRect resize_bar_rect = panel_rect;
if (mOrientation == HORIZONTAL)
{
@@ -689,6 +777,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
llassert_always(force_resize == FALSE);
updateLayout(TRUE);
}
+
+ mAnimatedThisFrame = true;
} // end LLLayoutStack::updateLayout
@@ -707,6 +797,24 @@ LLLayoutStack::LayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) co
return NULL;
}
+LLLayoutStack::LayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const
+{
+ LayoutPanel* result = NULL;
+
+ for (e_panel_list_t::const_iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LayoutPanel* p = *panel_it;
+
+ if (p->mPanel->getName() == name)
+ {
+ result = p;
+ break;
+ }
+ }
+
+ return result;
+}
+
// Compute sum of min_width or min_height of children
void LLLayoutStack::calcMinExtents()
{
@@ -738,3 +846,19 @@ void LLLayoutStack::calcMinExtents()
}
}
}
+
+// update layout stack animations, etc. once per frame
+// NOTE: we use this to size world view based on animating UI, *before* we draw the UI
+// we might still need to call updateLayout during UI draw phase, in case UI elements
+// are resizing themselves dynamically
+//static
+void LLLayoutStack::updateClass()
+{
+ LLInstanceTrackerScopedGuard guard;
+ for (LLLayoutStack::instance_iter it = guard.beginInstances();
+ it != guard.endInstances();
+ ++it)
+ {
+ it->updateLayout();
+ }
+}