summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llfloater.cpp90
-rw-r--r--indra/llui/llfloater.h7
-rw-r--r--indra/llui/llfloaterreg.h1
-rw-r--r--indra/llui/llmenugl.cpp114
-rw-r--r--indra/llui/llmenugl.h41
-rw-r--r--indra/llui/llnotifications.cpp4
-rw-r--r--indra/llui/llpanel.cpp4
-rw-r--r--indra/llui/llresizebar.cpp55
-rw-r--r--indra/llui/llresizehandle.cpp58
-rw-r--r--indra/llui/llstatbar.cpp153
-rw-r--r--indra/llui/llstatbar.h52
-rw-r--r--indra/llui/llstatgraph.cpp119
-rw-r--r--indra/llui/llstatgraph.h101
-rw-r--r--indra/llui/lltextbase.cpp19
-rw-r--r--indra/llui/lltextbase.h15
-rw-r--r--indra/llui/lltexteditor.cpp80
-rw-r--r--indra/llui/lltexteditor.h6
-rw-r--r--indra/llui/lltoggleablemenu.cpp5
-rw-r--r--indra/llui/lltoggleablemenu.h2
-rw-r--r--indra/llui/lltooltip.cpp18
-rw-r--r--indra/llui/lltooltip.h4
-rw-r--r--indra/llui/lluictrl.cpp21
-rw-r--r--indra/llui/lluictrlfactory.h10
-rw-r--r--indra/llui/lluistring.cpp2
-rw-r--r--indra/llui/llview.cpp2
-rw-r--r--indra/llui/llview.h4
-rw-r--r--indra/llui/llviewmodel.cpp7
-rw-r--r--indra/llui/llviewmodel.h7
-rw-r--r--indra/llui/llxuiparser.cpp16
-rw-r--r--indra/llui/llxuiparser.h18
30 files changed, 706 insertions, 329 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 054b9173d3..a29ad12d23 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1105,17 +1105,26 @@ void LLFloater::handleReshape(const LLRect& new_rect, bool by_user)
const LLRect old_rect = getRect();
LLView::handleReshape(new_rect, by_user);
- if (by_user && !isMinimized())
+ if (by_user && !getHost())
{
+ static_cast<LLFloaterView*>(getParent())->adjustToFitScreen(this, !isMinimized());
+ }
+
+ // if not minimized, adjust all snapped dependents to new shape
+ if (!isMinimized())
+ {
+ if (by_user)
+ {
+ if (isDocked())
+ {
+ setDocked( false, false);
+ }
storeRectControl();
mPositioning = LLFloaterEnums::POSITIONING_RELATIVE;
LLRect screen_rect = calcScreenRect();
mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert();
}
- // if not minimized, adjust all snapped dependents to new shape
- if (!isMinimized())
- {
// gather all snapped dependents
for(handle_set_iter_t dependent_it = mDependents.begin();
dependent_it != mDependents.end(); ++dependent_it)
@@ -1712,55 +1721,9 @@ void LLFloater::onClickHelp( LLFloater* self )
}
// static
-LLFloater* LLFloater::getClosableFloaterFromFocus()
-{
- LLFloater* focused_floater = NULL;
- LLInstanceTracker<LLFloater>::instance_iter it = beginInstances();
- LLInstanceTracker<LLFloater>::instance_iter end_it = endInstances();
- for (; it != end_it; ++it)
- {
- if (it->hasFocus())
- {
- LLFloater& floater = *it;
- focused_floater = &floater;
- break;
- }
- }
-
- if (it == endInstances())
- {
- // nothing found, return
- return NULL;
- }
-
- // The focused floater may not be closable,
- // Find and close a parental floater that is closeable, if any.
- LLFloater* prev_floater = NULL;
- for(LLFloater* floater_to_close = focused_floater;
- NULL != floater_to_close;
- floater_to_close = gFloaterView->getParentFloater(floater_to_close))
- {
- if(floater_to_close->isCloseable())
- {
- return floater_to_close;
- }
-
- // If floater has as parent root view
- // gFloaterView->getParentFloater(floater_to_close) returns
- // the same floater_to_close, so we need to check this.
- if (prev_floater == floater_to_close) {
- break;
- }
- prev_floater = floater_to_close;
- }
-
- return NULL;
-}
-
-// static
-void LLFloater::closeFocusedFloater()
+void LLFloater::closeFrontmostFloater()
{
- LLFloater* floater_to_close = LLFloater::getClosableFloaterFromFocus();
+ LLFloater* floater_to_close = gFloaterView->getFrontmostClosableFloater();
if(floater_to_close)
{
floater_to_close->closeFloater();
@@ -2478,6 +2441,24 @@ void LLFloaterView::highlightFocusedFloater()
}
}
+LLFloater* LLFloaterView::getFrontmostClosableFloater()
+{
+ child_list_const_iter_t child_it;
+ LLFloater* frontmost_floater = NULL;
+
+ for ( child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
+ {
+ frontmost_floater = (LLFloater *)(*child_it);
+
+ if (frontmost_floater->isInVisibleChain() && frontmost_floater->isCloseable())
+ {
+ return frontmost_floater;
+ }
+ }
+
+ return NULL;
+}
+
void LLFloaterView::unhighlightFocusedFloater()
{
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
@@ -3104,7 +3085,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
parser.readXUI(node, output_params, LLUICtrlFactory::getInstance()->getCurFileName());
setupParamsForExport(output_params, parent);
output_node->setName(node->getName()->mString);
- parser.writeXUI(output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
return TRUE;
}
@@ -3134,9 +3115,8 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
{
Params output_params(params);
setupParamsForExport(output_params, parent);
- Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>());
output_node->setName(node->getName()->mString);
- parser.writeXUI(output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
}
// Default floater position to top-left corner of screen
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index e64b6d04d3..aef63bcf93 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -325,12 +325,10 @@ public:
virtual void setTornOff(bool torn_off) { mTornOff = torn_off; }
- // Return a closeable floater, if any, given the current focus.
- static LLFloater* getClosableFloaterFromFocus();
- // Close the floater returned by getClosableFloaterFromFocus() and
+ // Close the floater returned by getFrontmostClosableFloater() and
// handle refocusing.
- static void closeFocusedFloater();
+ static void closeFrontmostFloater();
// LLNotification::Params contextualNotification(const std::string& name)
// {
@@ -559,6 +557,7 @@ public:
S32 getZOrder(LLFloater* child);
void setFloaterSnapView(LLHandle<LLView> snap_view) {mSnapView = snap_view; }
+ LLFloater* getFrontmostClosableFloater();
private:
void hiddenFloaterClosed(LLFloater* floater);
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index a1e1f8a988..e3b17dcb4f 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -30,6 +30,7 @@
#include "llrect.h"
#include "llsd.h"
+#include <list>
#include <boost/function.hpp>
//*******************************************************
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index efb9848a90..cd6cc6a75e 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -1764,6 +1764,25 @@ bool LLMenuGL::addChild(LLView* view, S32 tab_group)
return false;
}
+// Used in LLContextMenu and in LLTogleableMenu
+// to add an item of context menu branch
+bool LLMenuGL::addContextChild(LLView* view, S32 tab_group)
+{
+ LLContextMenu* context = dynamic_cast<LLContextMenu*>(view);
+ if (context)
+ return appendContextSubMenu(context);
+
+ LLMenuItemSeparatorGL* separator = dynamic_cast<LLMenuItemSeparatorGL*>(view);
+ if (separator)
+ return append(separator);
+
+ LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(view);
+ if (item)
+ return append(item);
+
+ return false;
+}
+
void LLMenuGL::removeChild( LLView* ctrl)
{
// previously a dynamic_cast with if statement to check validity
@@ -2501,6 +2520,30 @@ BOOL LLMenuGL::appendMenu( LLMenuGL* menu )
return success;
}
+// add a context menu branch
+BOOL LLMenuGL::appendContextSubMenu(LLMenuGL *menu)
+{
+ if (menu == this)
+ {
+ llerrs << "Can't attach a context menu to itself" << llendl;
+ }
+
+ LLContextMenuBranch *item;
+ LLContextMenuBranch::Params p;
+ p.name = menu->getName();
+ p.label = menu->getLabel();
+ p.branch = (LLContextMenu *)menu;
+ p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor");
+ p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor");
+ p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor");
+ p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor");
+
+ item = LLUICtrlFactory::create<LLContextMenuBranch>(p);
+ LLMenuGL::sMenuContainer->addChild(item->getBranch());
+
+ return append( item );
+}
+
void LLMenuGL::setEnabledSubMenus(BOOL enable)
{
setEnabled(enable);
@@ -3725,39 +3768,6 @@ void LLTearOffMenu::closeTearOff()
mMenu->setDropShadowed(TRUE);
}
-
-//-----------------------------------------------------------------------------
-// class LLContextMenuBranch
-// A branch to another context menu
-//-----------------------------------------------------------------------------
-class LLContextMenuBranch : public LLMenuItemGL
-{
-public:
- struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
- {
- Mandatory<LLContextMenu*> branch;
- };
-
- LLContextMenuBranch(const Params&);
-
- virtual ~LLContextMenuBranch()
- {}
-
- // called to rebuild the draw label
- virtual void buildDrawLabel( void );
-
- // onCommit() - do the primary funcationality of the menu item.
- virtual void onCommit( void );
-
- LLContextMenu* getBranch() { return mBranch.get(); }
- void setHighlight( BOOL highlight );
-
-protected:
- void showSubMenu();
-
- LLHandle<LLContextMenu> mBranch;
-};
-
LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p)
: LLMenuItemGL(p),
mBranch( p.branch()->getHandle() )
@@ -4034,44 +4044,8 @@ void LLContextMenu::draw()
LLMenuGL::draw();
}
-BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu)
-{
-
- if (menu == this)
- {
- llerrs << "Can't attach a context menu to itself" << llendl;
- }
-
- LLContextMenuBranch *item;
- LLContextMenuBranch::Params p;
- p.name = menu->getName();
- p.label = menu->getLabel();
- p.branch = menu;
- p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor");
- p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor");
- p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor");
- p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor");
-
- item = LLUICtrlFactory::create<LLContextMenuBranch>(p);
- LLMenuGL::sMenuContainer->addChild(item->getBranch());
-
- return append( item );
-}
-
bool LLContextMenu::addChild(LLView* view, S32 tab_group)
{
- LLContextMenu* context = dynamic_cast<LLContextMenu*>(view);
- if (context)
- return appendContextSubMenu(context);
-
- LLMenuItemSeparatorGL* separator = dynamic_cast<LLMenuItemSeparatorGL*>(view);
- if (separator)
- return append(separator);
-
- LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(view);
- if (item)
- return append(item);
-
- return false;
+ return addContextChild(view, tab_group);
}
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 67b3e1fbe6..00899020bc 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -519,6 +519,9 @@ public:
void resetScrollPositionOnShow(bool reset_scroll_pos) { mResetScrollPositionOnShow = reset_scroll_pos; }
bool isScrollPositionOnShowReset() { return mResetScrollPositionOnShow; }
+ // add a context menu branch
+ BOOL appendContextSubMenu(LLMenuGL *menu);
+
protected:
void createSpilloverBranch();
void cleanupSpilloverBranch();
@@ -528,6 +531,10 @@ protected:
// add a menu - this will create a cascading menu
virtual BOOL appendMenu( LLMenuGL* menu );
+ // Used in LLContextMenu and in LLTogleableMenu
+ // to add an item of context menu branch
+ bool addContextChild(LLView* view, S32 tab_group);
+
// TODO: create accessor methods for these?
typedef std::list< LLMenuItemGL* > item_list_t;
item_list_t mItems;
@@ -679,8 +686,6 @@ public:
virtual bool addChild (LLView* view, S32 tab_group = 0);
- BOOL appendContextSubMenu(LLContextMenu *menu);
-
LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); }
LLView* getSpawningView() const { return mSpawningViewHandle.get(); }
@@ -694,6 +699,38 @@ protected:
};
+//-----------------------------------------------------------------------------
+// class LLContextMenuBranch
+// A branch to another context menu
+//-----------------------------------------------------------------------------
+class LLContextMenuBranch : public LLMenuItemGL
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Mandatory<LLContextMenu*> branch;
+ };
+
+ LLContextMenuBranch(const Params&);
+
+ virtual ~LLContextMenuBranch()
+ {}
+
+ // called to rebuild the draw label
+ virtual void buildDrawLabel( void );
+
+ // onCommit() - do the primary funcationality of the menu item.
+ virtual void onCommit( void );
+
+ LLContextMenu* getBranch() { return mBranch.get(); }
+ void setHighlight( BOOL highlight );
+
+protected:
+ void showSubMenu();
+
+ LLHandle<LLContextMenu> mBranch;
+};
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuBarGL
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 210a320f41..137c6efc53 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -464,7 +464,7 @@ LLNotification::LLNotification(const LLNotification::Params& p) :
mTimestamp(p.time_stamp),
mSubstitutions(p.substitutions),
mPayload(p.payload),
- mExpiresAt(0),
+ mExpiresAt(0.0),
mTemporaryResponder(false),
mRespondedTo(false),
mPriority(p.priority),
@@ -1433,7 +1433,7 @@ bool LLNotifications::loadTemplates()
std::string base_filename = search_paths.front();
LLXMLNodePtr root;
BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths);
-
+
if (!success || root.isNull() || !root->hasName( "notifications" ))
{
llerrs << "Problem reading XML from UI Notifications file: " << base_filename << llendl;
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 67472ad166..188a0fea74 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -520,7 +520,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
Params output_params(params);
setupParamsForExport(output_params, parent);
output_node->setName(node->getName()->mString);
- parser.writeXUI(output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
return TRUE;
}
@@ -551,7 +551,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
Params output_params(params);
setupParamsForExport(output_params, parent);
output_node->setName(node->getName()->mString);
- parser.writeXUI(output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
}
params.from_xui = true;
diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp
index 87aeb4d7a7..ba90fa5e0c 100644
--- a/indra/llui/llresizebar.cpp
+++ b/indra/llui/llresizebar.cpp
@@ -139,13 +139,6 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
if( valid_rect.localPointInRect( screen_x, screen_y ) && mResizingView )
{
- // undock floater when user resize it
- LLFloater* parent = dynamic_cast<LLFloater*>( getParent());
- if (parent && parent->isDocked())
- {
- parent->setDocked( false, false);
- }
-
// Resize the parent
LLRect orig_rect = mResizingView->getRect();
LLRect scaled_rect = orig_rect;
@@ -219,20 +212,66 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
// update last valid mouse cursor position based on resized view's actual size
LLRect new_rect = mResizingView->getRect();
+
switch(mSide)
{
case LEFT:
- mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
+ {
+ S32 actual_delta_x = new_rect.mLeft - orig_rect.mLeft;
+ if (actual_delta_x != delta_x)
+ {
+ // restore everything by left
+ new_rect.mBottom = orig_rect.mBottom;
+ new_rect.mTop = orig_rect.mTop;
+ new_rect.mRight = orig_rect.mRight;
+ mResizingView->setShape(new_rect, true);
+ }
+ mDragLastScreenX += actual_delta_x;
+
break;
+ }
case RIGHT:
+ {
+ S32 actual_delta_x = new_rect.mRight - orig_rect.mRight;
+ if (actual_delta_x != delta_x)
+ {
+ // restore everything by left
+ new_rect.mBottom = orig_rect.mBottom;
+ new_rect.mTop = orig_rect.mTop;
+ new_rect.mLeft = orig_rect.mLeft;
+ mResizingView->setShape(new_rect, true);
+ }
mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
break;
+ }
case TOP:
+ {
+ S32 actual_delta_y = new_rect.mTop - orig_rect.mTop;
+ if (actual_delta_y != delta_y)
+ {
+ // restore everything by left
+ new_rect.mBottom = orig_rect.mBottom;
+ new_rect.mLeft = orig_rect.mLeft;
+ new_rect.mRight = orig_rect.mRight;
+ mResizingView->setShape(new_rect, true);
+ }
mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
break;
+ }
case BOTTOM:
+ {
+ S32 actual_delta_y = new_rect.mBottom - orig_rect.mBottom;
+ if (actual_delta_y != delta_y)
+ {
+ // restore everything by left
+ new_rect.mTop = orig_rect.mTop;
+ new_rect.mLeft = orig_rect.mLeft;
+ new_rect.mRight = orig_rect.mRight;
+ mResizingView->setShape(new_rect, true);
+ }
mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
break;
+ }
default:
break;
}
diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp
index c3a51c36c9..24794305ac 100644
--- a/indra/llui/llresizehandle.cpp
+++ b/indra/llui/llresizehandle.cpp
@@ -257,23 +257,65 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
// update last valid mouse cursor position based on resized view's actual size
LLRect new_rect = resizing_view->getRect();
+ S32 actual_delta_x = 0;
+ S32 actual_delta_y = 0;
switch(mCorner)
{
case LEFT_TOP:
- mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
- mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
+ actual_delta_x = new_rect.mLeft - orig_rect.mLeft;
+ actual_delta_y = new_rect.mTop - orig_rect.mTop;
+ if (actual_delta_x != delta_x
+ || actual_delta_y != delta_y)
+ {
+ new_rect.mRight = orig_rect.mRight;
+ new_rect.mBottom = orig_rect.mBottom;
+ resizing_view->setShape(new_rect, true);
+ }
+
+ mDragLastScreenX += actual_delta_x;
+ mDragLastScreenY += actual_delta_y;
break;
case LEFT_BOTTOM:
- mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft;
- mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
+ actual_delta_x = new_rect.mLeft - orig_rect.mLeft;
+ actual_delta_y = new_rect.mBottom - orig_rect.mBottom;
+ if (actual_delta_x != delta_x
+ || actual_delta_y != delta_y)
+ {
+ new_rect.mRight = orig_rect.mRight;
+ new_rect.mTop = orig_rect.mTop;
+ resizing_view->setShape(new_rect, true);
+ }
+
+ mDragLastScreenX += actual_delta_x;
+ mDragLastScreenY += actual_delta_y;
break;
case RIGHT_TOP:
- mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
- mDragLastScreenY += new_rect.mTop - orig_rect.mTop;
+ actual_delta_x = new_rect.mRight - orig_rect.mRight;
+ actual_delta_y = new_rect.mTop - orig_rect.mTop;
+ if (actual_delta_x != delta_x
+ || actual_delta_y != delta_y)
+ {
+ new_rect.mLeft = orig_rect.mLeft;
+ new_rect.mBottom = orig_rect.mBottom;
+ resizing_view->setShape(new_rect, true);
+ }
+
+ mDragLastScreenX += actual_delta_x;
+ mDragLastScreenY += actual_delta_y;
break;
case RIGHT_BOTTOM:
- mDragLastScreenX += new_rect.mRight - orig_rect.mRight;
- mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom;
+ actual_delta_x = new_rect.mRight - orig_rect.mRight;
+ actual_delta_y = new_rect.mBottom - orig_rect.mBottom;
+ if (actual_delta_x != delta_x
+ || actual_delta_y != delta_y)
+ {
+ new_rect.mLeft = orig_rect.mLeft;
+ new_rect.mTop = orig_rect.mTop;
+ resizing_view->setShape(new_rect, true);
+ }
+
+ mDragLastScreenX += actual_delta_x;
+ mDragLastScreenY += actual_delta_y;
break;
default:
break;
diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp
index 04cce7878e..1bc9a9fc67 100644
--- a/indra/llui/llstatbar.cpp
+++ b/indra/llui/llstatbar.cpp
@@ -34,8 +34,8 @@
#include "llgl.h"
#include "llfontgl.h"
-#include "llstat.h"
#include "lluictrlfactory.h"
+#include "lltracerecording.h"
///////////////////////////////////////////////////////////////////////////////////
@@ -45,17 +45,20 @@ LLStatBar::LLStatBar(const Params& p)
mUnitLabel(p.unit_label),
mMinBar(p.bar_min),
mMaxBar(p.bar_max),
- mStatp(LLStat::getStat(p.stat)),
+ mCountFloatp(LLTrace::Count<>::getInstance(p.stat)),
+ mCountIntp(LLTrace::Count<S64>::getInstance(p.stat)),
+ mMeasurementFloatp(LLTrace::Measurement<>::getInstance(p.stat)),
+ mMeasurementIntp(LLTrace::Measurement<S64>::getInstance(p.stat)),
mTickSpacing(p.tick_spacing),
mLabelSpacing(p.label_spacing),
mPrecision(p.precision),
mUpdatesPerSec(p.update_rate),
+ mUnitScale(p.unit_scale),
mPerSec(p.show_per_sec),
mDisplayBar(p.show_bar),
mDisplayHistory(p.show_history),
mDisplayMean(p.show_mean)
-{
-}
+{}
BOOL LLStatBar::handleMouseDown(S32 x, S32 y, MASK mask)
{
@@ -84,29 +87,72 @@ BOOL LLStatBar::handleMouseDown(S32 x, S32 y, MASK mask)
void LLStatBar::draw()
{
- if (!mStatp)
+ F32 current = 0.f,
+ min = 0.f,
+ max = 0.f,
+ mean = 0.f;
+
+ LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+
+ if (mCountFloatp)
{
-// llinfos << "No stats for statistics bar!" << llendl;
- return;
+ LLTrace::Recording& last_frame_recording = frame_recording.getLastRecordingPeriod();
+
+ if (mPerSec)
+ {
+ current = last_frame_recording.getPerSec(*mCountFloatp);
+ min = frame_recording.getPeriodMinPerSec(*mCountFloatp);
+ max = frame_recording.getPeriodMaxPerSec(*mCountFloatp);
+ mean = frame_recording.getPeriodMeanPerSec(*mCountFloatp);
+ }
+ else
+ {
+ current = last_frame_recording.getSum(*mCountFloatp);
+ min = frame_recording.getPeriodMin(*mCountFloatp);
+ max = frame_recording.getPeriodMax(*mCountFloatp);
+ mean = frame_recording.getPeriodMean(*mCountFloatp);
+ }
}
+ else if (mCountIntp)
+ {
+ LLTrace::Recording& last_frame_recording = frame_recording.getLastRecordingPeriod();
- // Get the values.
- F32 current, min, max, mean;
- if (mPerSec)
+ if (mPerSec)
+ {
+ current = last_frame_recording.getPerSec(*mCountIntp);
+ min = frame_recording.getPeriodMinPerSec(*mCountIntp);
+ max = frame_recording.getPeriodMaxPerSec(*mCountIntp);
+ mean = frame_recording.getPeriodMeanPerSec(*mCountIntp);
+ }
+ else
+ {
+ current = last_frame_recording.getSum(*mCountIntp);
+ min = frame_recording.getPeriodMin(*mCountIntp);
+ max = frame_recording.getPeriodMax(*mCountIntp);
+ mean = frame_recording.getPeriodMean(*mCountIntp);
+ }
+ }
+ else if (mMeasurementFloatp)
{
- current = mStatp->getCurrentPerSec();
- min = mStatp->getMinPerSec();
- max = mStatp->getMaxPerSec();
- mean = mStatp->getMeanPerSec();
+ LLTrace::Recording& recording = frame_recording.getTotalRecording();
+ current = recording.getLastValue(*mMeasurementFloatp);
+ min = recording.getMin(*mMeasurementFloatp);
+ max = recording.getMax(*mMeasurementFloatp);
+ mean = recording.getMean(*mMeasurementFloatp);
}
- else
+ else if (mMeasurementIntp)
{
- current = mStatp->getCurrent();
- min = mStatp->getMin();
- max = mStatp->getMax();
- mean = mStatp->getMean();
+ LLTrace::Recording& recording = frame_recording.getTotalRecording();
+ current = recording.getLastValue(*mMeasurementIntp);
+ min = recording.getMin(*mMeasurementIntp);
+ max = recording.getMax(*mMeasurementIntp);
+ mean = recording.getMean(*mMeasurementIntp);
}
+ current *= mUnitScale;
+ min *= mUnitScale;
+ max *= mUnitScale;
+ mean *= mUnitScale;
if ((mUpdatesPerSec == 0.f) || (mUpdateTimer.getElapsedTimeF32() > 1.f/mUpdatesPerSec) || (mValue == 0.f))
{
@@ -153,7 +199,7 @@ void LLStatBar::draw()
LLFontGL::RIGHT, LLFontGL::TOP);
value_format = llformat( "%%.%df", mPrecision);
- if (mDisplayBar)
+ if (mDisplayBar && (mCountFloatp || mCountIntp || mMeasurementFloatp || mMeasurementIntp))
{
std::string tick_label;
@@ -196,7 +242,7 @@ void LLStatBar::draw()
right = width;
gl_rect_2d(left, top, right, bottom, LLColor4(0.f, 0.f, 0.f, 0.25f));
- if (mStatp->getNumValues() == 0)
+ if (frame_recording.getNumPeriods() == 0)
{
// No data, don't draw anything...
return;
@@ -213,26 +259,58 @@ void LLStatBar::draw()
right = (S32) ((max - mMinBar) * value_scale);
gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 0.25f));
- S32 num_values = mStatp->getNumValues() - 1;
- if (mDisplayHistory)
+ if (mDisplayHistory && (mCountFloatp || mCountIntp || mMeasurementFloatp || mMeasurementIntp))
{
+ S32 num_values = frame_recording.getNumPeriods() - 1;
S32 i;
- for (i = 0; i < num_values; i++)
+ for (i = 1; i <= num_values; i++)
{
- if (i == mStatp->getNextBin())
- {
- continue;
- }
if (mPerSec)
{
- left = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale);
- right = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale) + 1;
+ if (mCountFloatp)
+ {
+ left = (S32)((frame_recording.getPrevRecordingPeriod(i).getPerSec(*mCountFloatp) - mMinBar) * value_scale);
+ right = (S32)((frame_recording.getPrevRecordingPeriod(i).getPerSec(*mCountFloatp) - mMinBar) * value_scale) + 1;
+ }
+ else if (mCountIntp)
+ {
+ left = (S32)((frame_recording.getPrevRecordingPeriod(i).getPerSec(*mCountIntp) - mMinBar) * value_scale);
+ right = (S32)((frame_recording.getPrevRecordingPeriod(i).getPerSec(*mCountIntp) - mMinBar) * value_scale) + 1;
+ }
+ else if (mMeasurementFloatp)
+ {
+ left = (S32)((frame_recording.getPrevRecordingPeriod(i).getPerSec(*mMeasurementFloatp) - mMinBar) * value_scale);
+ right = (S32)((frame_recording.getPrevRecordingPeriod(i).getPerSec(*mMeasurementFloatp) - mMinBar) * value_scale) + 1;
+ }
+ else if (mMeasurementIntp)
+ {
+ left = (S32)((frame_recording.getPrevRecordingPeriod(i).getPerSec(*mMeasurementIntp) - mMinBar) * value_scale);
+ right = (S32)((frame_recording.getPrevRecordingPeriod(i).getPerSec(*mMeasurementIntp) - mMinBar) * value_scale) + 1;
+ }
gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f));
}
else
{
- left = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale);
- right = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale) + 1;
+ if (mCountFloatp)
+ {
+ left = (S32)((frame_recording.getPrevRecordingPeriod(i).getSum(*mCountFloatp) - mMinBar) * value_scale);
+ right = (S32)((frame_recording.getPrevRecordingPeriod(i).getSum(*mCountFloatp) - mMinBar) * value_scale) + 1;
+ }
+ else if (mCountIntp)
+ {
+ left = (S32)((frame_recording.getPrevRecordingPeriod(i).getSum(*mCountIntp) - mMinBar) * value_scale);
+ right = (S32)((frame_recording.getPrevRecordingPeriod(i).getSum(*mCountIntp) - mMinBar) * value_scale) + 1;
+ }
+ else if (mMeasurementFloatp)
+ {
+ left = (S32)((frame_recording.getPrevRecordingPeriod(i).getSum(*mMeasurementFloatp) - mMinBar) * value_scale);
+ right = (S32)((frame_recording.getPrevRecordingPeriod(i).getSum(*mMeasurementFloatp) - mMinBar) * value_scale) + 1;
+ }
+ else if (mMeasurementIntp)
+ {
+ left = (S32)((frame_recording.getPrevRecordingPeriod(i).getSum(*mMeasurementIntp) - mMinBar) * value_scale);
+ right = (S32)((frame_recording.getPrevRecordingPeriod(i).getSum(*mMeasurementIntp) - mMinBar) * value_scale) + 1;
+ }
gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f));
}
}
@@ -256,6 +334,15 @@ void LLStatBar::draw()
LLView::draw();
}
+void LLStatBar::setStat(const std::string& stat_name)
+{
+ mCountFloatp = LLTrace::Count<>::getInstance(stat_name);
+ mCountIntp = LLTrace::Count<S64>::getInstance(stat_name);
+ mMeasurementFloatp = LLTrace::Measurement<>::getInstance(stat_name);
+ mMeasurementIntp = LLTrace::Measurement<S64>::getInstance(stat_name);
+}
+
+
void LLStatBar::setRange(F32 bar_min, F32 bar_max, F32 tick_spacing, F32 label_spacing)
{
mMinBar = bar_min;
@@ -272,7 +359,7 @@ LLRect LLStatBar::getRequiredRect()
{
if (mDisplayHistory)
{
- rect.mTop = 35 + mStatp->getNumBins();
+ rect.mTop = 35 + LLTrace::get_frame_recording().getNumPeriods();
}
else
{
diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h
index 513fff3234..c366fd65db 100644
--- a/indra/llui/llstatbar.h
+++ b/indra/llui/llstatbar.h
@@ -29,27 +29,33 @@
#include "llview.h"
#include "llframetimer.h"
-
-class LLStat;
+#include "lltracerecording.h"
class LLStatBar : public LLView
{
public:
+
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
- Optional<std::string> label;
- Optional<std::string> unit_label;
- Optional<F32> bar_min;
- Optional<F32> bar_max;
- Optional<F32> tick_spacing;
- Optional<F32> label_spacing;
- Optional<U32> precision;
- Optional<F32> update_rate;
- Optional<bool> show_per_sec;
- Optional<bool> show_bar;
- Optional<bool> show_history;
- Optional<bool> show_mean;
- Optional<std::string> stat;
+ Optional<std::string> label,
+ unit_label;
+
+ Optional<F32> bar_min,
+ bar_max,
+ tick_spacing,
+ label_spacing,
+ update_rate,
+ unit_scale;
+
+ Optional<U32> precision;
+
+ Optional<bool> show_per_sec,
+ show_bar,
+ show_history,
+ show_mean;
+
+ Optional<std::string> stat;
+
Params()
: label("label"),
unit_label("unit_label"),
@@ -59,10 +65,11 @@ public:
label_spacing("label_spacing", 10.0f),
precision("precision", 0),
update_rate("update_rate", 5.0f),
- show_per_sec("show_per_sec", TRUE),
+ unit_scale("unit_scale", 1.f),
+ show_per_sec("show_per_sec", true),
show_bar("show_bar", TRUE),
- show_history("show_history", FALSE),
- show_mean("show_mean", TRUE),
+ show_history("show_history", false),
+ show_mean("show_mean", true),
stat("stat")
{
changeDefault(follows.flags, FOLLOWS_TOP | FOLLOWS_LEFT);
@@ -73,7 +80,8 @@ public:
virtual void draw();
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- void setStat(LLStat* stat) { mStatp = stat; }
+ void setStat(const std::string& stat_name);
+
void setRange(F32 bar_min, F32 bar_max, F32 tick_spacing, F32 label_spacing);
void getRange(F32& bar_min, F32& bar_max) { bar_min = mMinBar; bar_max = mMaxBar; }
@@ -86,12 +94,16 @@ private:
F32 mLabelSpacing;
U32 mPrecision;
F32 mUpdatesPerSec;
+ F32 mUnitScale;
BOOL mPerSec; // Use the per sec stats.
BOOL mDisplayBar; // Display the bar graph.
BOOL mDisplayHistory;
BOOL mDisplayMean; // If true, display mean, if false, display current value
- LLStat* mStatp;
+ LLTrace::TraceType<LLTrace::CountAccumulator<F64> >* mCountFloatp;
+ LLTrace::TraceType<LLTrace::CountAccumulator<S64> >* mCountIntp;
+ LLTrace::TraceType<LLTrace::MeasurementAccumulator<F64> >* mMeasurementFloatp;
+ LLTrace::TraceType<LLTrace::MeasurementAccumulator<S64> >* mMeasurementIntp;
LLFrameTimer mUpdateTimer;
LLUIString mLabel;
diff --git a/indra/llui/llstatgraph.cpp b/indra/llui/llstatgraph.cpp
index e44887ebf0..22c276a018 100644
--- a/indra/llui/llstatgraph.cpp
+++ b/indra/llui/llstatgraph.cpp
@@ -32,48 +32,73 @@
#include "llmath.h"
#include "llui.h"
-#include "llstat.h"
#include "llgl.h"
#include "llglheaders.h"
+#include "lltracerecording.h"
+#include "lltracethreadrecorder.h"
//#include "llviewercontrol.h"
///////////////////////////////////////////////////////////////////////////////////
-LLStatGraph::LLStatGraph(const LLView::Params& p)
-: LLView(p)
+LLStatGraph::LLStatGraph(const Params& p)
+: LLView(p),
+ mMin(p.min),
+ mMax(p.max),
+ mPerSec(true),
+ mPrecision(p.precision),
+ mValue(p.value),
+ mNewStatFloatp(p.stat.count_stat_float),
+ mNewStatIntp(p.stat.count_stat_int)
{
- mStatp = NULL;
setToolTip(p.name());
- mNumThresholds = 3;
- mThresholdColors[0] = LLColor4(0.f, 1.f, 0.f, 1.f);
- mThresholdColors[1] = LLColor4(1.f, 1.f, 0.f, 1.f);
- mThresholdColors[2] = LLColor4(1.f, 0.f, 0.f, 1.f);
- mThresholdColors[3] = LLColor4(1.f, 0.f, 0.f, 1.f);
- mThresholds[0] = 50.f;
- mThresholds[1] = 75.f;
- mThresholds[2] = 100.f;
- mMin = 0.f;
- mMax = 125.f;
- mPerSec = TRUE;
- mValue = 0.f;
- mPrecision = 0;
+
+ for(LLInitParam::ParamIterator<ThresholdParams>::const_iterator it = p.thresholds.threshold.begin(), end_it = p.thresholds.threshold.end();
+ it != end_it;
+ ++it)
+ {
+ mThresholds.push_back(Threshold(it->value(), it->color));
+ }
+
+ //mThresholdColors[0] = LLColor4(0.f, 1.f, 0.f, 1.f);
+ //mThresholdColors[1] = LLColor4(1.f, 1.f, 0.f, 1.f);
+ //mThresholdColors[2] = LLColor4(1.f, 0.f, 0.f, 1.f);
+ //mThresholdColors[3] = LLColor4(1.f, 0.f, 0.f, 1.f);
+ //mThresholds[0] = 50.f;
+ //mThresholds[1] = 75.f;
+ //mThresholds[2] = 100.f;
}
void LLStatGraph::draw()
{
F32 range, frac;
range = mMax - mMin;
- if (mStatp)
+ if (mNewStatFloatp)
{
+ LLTrace::Recording& recording = LLTrace::get_frame_recording().getLastRecordingPeriod();
+
if (mPerSec)
{
- mValue = mStatp->getMeanPerSec();
+ mValue = recording.getPerSec(*mNewStatFloatp);
}
else
{
- mValue = mStatp->getMean();
+ mValue = recording.getSum(*mNewStatFloatp);
}
}
+ else if (mNewStatIntp)
+ {
+ LLTrace::Recording& recording = LLTrace::get_frame_recording().getLastRecordingPeriod();
+
+ if (mPerSec)
+ {
+ mValue = recording.getPerSec(*mNewStatIntp);
+ }
+ else
+ {
+ mValue = recording.getSum(*mNewStatIntp);
+ }
+ }
+
frac = (mValue - mMin) / range;
frac = llmax(0.f, frac);
frac = llmin(1.f, frac);
@@ -91,19 +116,22 @@ void LLStatGraph::draw()
LLColor4 color;
- S32 i;
- for (i = 0; i < mNumThresholds - 1; i++)
+ //S32 i;
+ //for (i = 0; i < mNumThresholds - 1; i++)
+ //{
+ // if (mThresholds[i] > mValue)
+ // {
+ // break;
+ // }
+ //}
+
+ threshold_vec_t::iterator it = std::lower_bound(mThresholds.begin(), mThresholds.end(), Threshold(mValue / mMax, LLUIColor()));
+
+ if (it != mThresholds.begin())
{
- if (mThresholds[i] > mValue)
- {
- break;
- }
+ it--;
}
- //gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
- // LLUIColorTable::instance().getColor("ColorDropShadow"),
- // (S32) gSavedSettings.getF32("DropShadowFloater") );
-
color = LLUIColorTable::instance().getColor( "MenuDefaultBgColor" );
gGL.color4fv(color.mV);
gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, TRUE);
@@ -111,16 +139,11 @@ void LLStatGraph::draw()
gGL.color4fv(LLColor4::black.mV);
gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, FALSE);
- color = mThresholdColors[i];
+ color = it->mColor;
gGL.color4fv(color.mV);
gl_rect_2d(1, llround(frac*getRect().getHeight()), getRect().getWidth() - 1, 0, TRUE);
}
-void LLStatGraph::setValue(const LLSD& value)
-{
- mValue = (F32)value.asReal();
-}
-
void LLStatGraph::setMin(const F32 min)
{
mMin = min;
@@ -131,27 +154,3 @@ void LLStatGraph::setMax(const F32 max)
mMax = max;
}
-void LLStatGraph::setStat(LLStat *statp)
-{
- mStatp = statp;
-}
-
-void LLStatGraph::setLabel(const std::string& label)
-{
- mLabel = label;
-}
-
-void LLStatGraph::setUnits(const std::string& units)
-{
- mUnits = units;
-}
-
-void LLStatGraph::setPrecision(const S32 precision)
-{
- mPrecision = precision;
-}
-
-void LLStatGraph::setThreshold(const S32 i, F32 value)
-{
- mThresholds[i] = value;
-}
diff --git a/indra/llui/llstatgraph.h b/indra/llui/llstatgraph.h
index 757525e232..57856ff6f2 100644
--- a/indra/llui/llstatgraph.h
+++ b/indra/llui/llstatgraph.h
@@ -30,29 +30,86 @@
#include "llview.h"
#include "llframetimer.h"
#include "v4color.h"
-
-class LLStat;
+#include "lltrace.h"
class LLStatGraph : public LLView
{
public:
- LLStatGraph(const LLView::Params&);
+ struct ThresholdParams : public LLInitParam::Block<ThresholdParams>
+ {
+ Mandatory<F32> value;
+ Optional<LLUIColor> color;
- virtual void draw();
+ ThresholdParams()
+ : value("value"),
+ color("color", LLColor4::white)
+ {}
+ };
+
+ struct Thresholds : public LLInitParam::Block<Thresholds>
+ {
+ Multiple<ThresholdParams> threshold;
+
+ Thresholds()
+ : threshold("threshold")
+ {}
+ };
+
+ struct StatParams : public LLInitParam::ChoiceBlock<StatParams>
+ {
+ Alternative<LLTrace::TraceType<LLTrace::CountAccumulator<F64> >* > count_stat_float;
+ Alternative<LLTrace::TraceType<LLTrace::CountAccumulator<S64> >* > count_stat_int;
+ Alternative<LLTrace::TraceType<LLTrace::MeasurementAccumulator<F64> >* > measurement_stat_float;
+ Alternative<LLTrace::TraceType<LLTrace::MeasurementAccumulator<S64> >* > measurement_stat_int;
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Mandatory<StatParams> stat;
+ Optional<std::string> label,
+ units;
+ Optional<S32> precision;
+ Optional<F32> min,
+ max;
+ Optional<bool> per_sec;
+ Optional<F32> value;
+
+ Optional<Thresholds> thresholds;
+
+ Params()
+ : stat("stat"),
+ label("label"),
+ units("units"),
+ precision("precision", 0),
+ min("min", 0.f),
+ max("max", 125.f),
+ per_sec("per_sec", true),
+ value("value", 0.f),
+ thresholds("thresholds")
+ {
+ Thresholds _thresholds;
+ _thresholds.threshold.add(ThresholdParams().value(0.f).color(LLColor4::green))
+ .add(ThresholdParams().value(0.33f).color(LLColor4::yellow))
+ .add(ThresholdParams().value(0.5f).color(LLColor4::red))
+ .add(ThresholdParams().value(0.75f).color(LLColor4::red));
+ thresholds = _thresholds;
+ }
+ };
+ LLStatGraph(const Params&);
- void setLabel(const std::string& label);
- void setUnits(const std::string& units);
- void setPrecision(const S32 precision);
- void setStat(LLStat *statp);
- void setThreshold(const S32 i, F32 value);
void setMin(const F32 min);
void setMax(const F32 max);
+ virtual void draw();
+
/*virtual*/ void setValue(const LLSD& value);
- LLStat *mStatp;
- BOOL mPerSec;
private:
+ LLTrace::TraceType<LLTrace::CountAccumulator<F64> >* mNewStatFloatp;
+ LLTrace::TraceType<LLTrace::CountAccumulator<S64> >* mNewStatIntp;
+
+ BOOL mPerSec;
+
F32 mValue;
F32 mMin;
@@ -62,9 +119,25 @@ private:
std::string mUnits;
S32 mPrecision; // Num of digits of precision after dot
- S32 mNumThresholds;
- F32 mThresholds[4];
- LLColor4 mThresholdColors[4];
+ struct Threshold
+ {
+ Threshold(F32 value, const LLUIColor& color)
+ : mValue(value),
+ mColor(color)
+ {}
+
+ F32 mValue;
+ LLUIColor mColor;
+ bool operator <(const Threshold& other)
+ {
+ return mValue < other.mValue;
+ }
+ };
+ typedef std::vector<Threshold> threshold_vec_t;
+ threshold_vec_t mThresholds;
+ //S32 mNumThresholds;
+ //F32 mThresholds[4];
+ //LLColor4 mThresholdColors[4];
};
#endif // LL_LLSTATGRAPH_H
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 3815eec447..74e966560e 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -47,6 +47,8 @@
const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
const S32 CURSOR_THICKNESS = 2;
+LLTrace::MemStat LLTextSegment::sMemStat("LLTextSegment");
+
LLTextBase::line_info::line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num)
: mDocIndexStart(index_start),
mDocIndexEnd(index_end),
@@ -561,7 +563,7 @@ void LLTextBase::drawText()
if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) )
{
const LLWString& wstrText = getWText();
- mMisspellRanges.clear();
+ memDisclaim(mMisspellRanges).clear();
segment_set_t::const_iterator seg_it = getSegIterContaining(start);
while (mSegments.end() != seg_it)
@@ -632,6 +634,7 @@ void LLTextBase::drawText()
mSpellCheckStart = start;
mSpellCheckEnd = end;
+ memClaim(mMisspellRanges);
}
}
@@ -890,10 +893,12 @@ void LLTextBase::createDefaultSegment()
// ensures that there is always at least one segment
if (mSegments.empty())
{
+ memDisclaim(mSegments);
LLStyleConstSP sp(new LLStyle(getDefaultStyleParams()));
LLTextSegmentPtr default_segment = new LLNormalTextSegment( sp, 0, getLength() + 1, *this);
mSegments.insert(default_segment);
default_segment->linkToDocument(this);
+ memClaim(mSegments);
}
}
@@ -904,6 +909,8 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
return;
}
+ memDisclaim(mSegments);
+
segment_set_t::iterator cur_seg_iter = getSegIterContaining(segment_to_insert->getStart());
S32 reflow_start_index = 0;
@@ -976,6 +983,7 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
// layout potentially changed
needsReflow(reflow_start_index);
+ memClaim(mSegments);
}
BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -1271,8 +1279,11 @@ void LLTextBase::replaceWithSuggestion(U32 index)
removeStringNoUndo(it->first, it->second - it->first);
// Insert the suggestion in its place
+ memDisclaim(mSuggestionList);
LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]);
insertStringNoUndo(it->first, utf8str_to_wstring(mSuggestionList[index]));
+ memClaim(mSuggestionList);
+
setCursorPos(it->first + (S32)suggestion.length());
break;
@@ -1334,7 +1345,7 @@ bool LLTextBase::isMisspelledWord(U32 pos) const
void LLTextBase::onSpellCheckSettingsChange()
{
// Recheck the spelling on every change
- mMisspellRanges.clear();
+ memDisclaim(mMisspellRanges).clear();
mSpellCheckStart = mSpellCheckEnd = -1;
}
@@ -1593,7 +1604,7 @@ LLRect LLTextBase::getTextBoundingRect()
void LLTextBase::clearSegments()
{
- mSegments.clear();
+ memDisclaim(mSegments).clear();
createDefaultSegment();
}
@@ -3057,7 +3068,9 @@ void LLNormalTextSegment::setToolTip(const std::string& tooltip)
llwarns << "LLTextSegment::setToolTip: cannot replace keyword tooltip." << llendl;
return;
}
+ memDisclaim(mTooltip);
mTooltip = tooltip;
+ memClaim(mTooltip);
}
bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 90b147cee1..7d791ec75a 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -50,7 +50,10 @@ class LLUrlMatch;
/// includes a start/end offset from the start of the string, a
/// style to render with, an optional tooltip, etc.
///
-class LLTextSegment : public LLRefCount, public LLMouseHandler
+class LLTextSegment
+: public LLRefCount,
+ public LLMouseHandler,
+ public LLTrace::MemTrackable<LLTextSegment>
{
public:
LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){};
@@ -91,10 +94,12 @@ public:
/*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
/*virtual*/ BOOL hasMouseCapture();
- S32 getStart() const { return mStart; }
- void setStart(S32 start) { mStart = start; }
- S32 getEnd() const { return mEnd; }
- void setEnd( S32 end ) { mEnd = end; }
+ S32 getStart() const { return mStart; }
+ void setStart(S32 start) { mStart = start; }
+ S32 getEnd() const { return mEnd; }
+ void setEnd( S32 end ) { mEnd = end; }
+
+ static LLTrace::MemStat sMemStat;
protected:
S32 mStart;
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 144b6960a1..46fbd1e6a0 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -239,7 +239,8 @@ LLTextEditor::Params::Params()
show_line_numbers("show_line_numbers", false),
default_color("default_color"),
commit_on_focus_lost("commit_on_focus_lost", false),
- show_context_menu("show_context_menu")
+ show_context_menu("show_context_menu"),
+ enable_tooltip_paste("enable_tooltip_paste")
{
addSynonym(prevalidate_callback, "text_type");
}
@@ -258,7 +259,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mTabsToNextField(p.ignore_tab),
mPrevalidateFunc(p.prevalidate_callback()),
mContextMenu(NULL),
- mShowContextMenu(p.show_context_menu)
+ mShowContextMenu(p.show_context_menu),
+ mEnableTooltipPaste(p.enable_tooltip_paste)
{
mSourceID.generate();
@@ -1411,6 +1413,23 @@ void LLTextEditor::pasteHelper(bool is_primary)
// Clean up string (replace tabs and remove characters that our fonts don't support).
LLWString clean_string(paste);
+ cleanStringForPaste(clean_string);
+
+ // Insert the new text into the existing text.
+
+ //paste text with linebreaks.
+ pasteTextWithLinebreaks(clean_string);
+
+ deselect();
+
+ onKeyStroke();
+ mParseOnTheFly = TRUE;
+}
+
+
+// Clean up string (replace tabs and remove characters that our fonts don't support).
+void LLTextEditor::cleanStringForPaste(LLWString & clean_string)
+{
LLWStringUtil::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB);
if( mAllowEmbeddedItems )
{
@@ -1429,10 +1448,11 @@ void LLTextEditor::pasteHelper(bool is_primary)
}
}
}
+}
- // Insert the new text into the existing text.
- //paste text with linebreaks.
+void LLTextEditor::pasteTextWithLinebreaks(LLWString & clean_string)
+{
std::basic_string<llwchar>::size_type start = 0;
std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start);
@@ -1451,15 +1471,8 @@ void LLTextEditor::pasteHelper(bool is_primary)
std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start);
setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
-
- deselect();
-
- onKeyStroke();
- mParseOnTheFly = TRUE;
}
-
-
// copy selection to primary
void LLTextEditor::copyPrimary()
{
@@ -1680,19 +1693,50 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
{
return FALSE;
}
-
+
if (mReadOnly && mScroller)
{
handled = (mScroller && mScroller->handleKeyHere( key, mask ))
|| handleSelectionKey(key, mask)
|| handleControlKey(key, mask);
+ }
+ else
+ {
+ if (mEnableTooltipPaste &&
+ LLToolTipMgr::instance().toolTipVisible() &&
+ KEY_TAB == key)
+ { // Paste the first line of a tooltip into the editor
+ std::string message;
+ LLToolTipMgr::instance().getToolTipMessage(message);
+ LLWString tool_tip_text(utf8str_to_wstring(message));
+
+ if (tool_tip_text.size() > 0)
+ {
+ // Delete any selected characters (the tooltip text replaces them)
+ if(hasSelection())
+ {
+ deleteSelection(TRUE);
+ }
+
+ std::basic_string<llwchar>::size_type pos = tool_tip_text.find('\n',0);
+ if (pos != -1)
+ { // Extract the first line of the tooltip
+ tool_tip_text = std::basic_string<llwchar>(tool_tip_text, 0, pos);
+ }
+
+ // Add the text
+ cleanStringForPaste(tool_tip_text);
+ pasteTextWithLinebreaks(tool_tip_text);
+ handled = TRUE;
+ }
+ }
+ else
+ { // Normal key handling
+ handled = handleNavigationKey( key, mask )
+ || handleSelectionKey(key, mask)
+ || handleControlKey(key, mask)
+ || handleSpecialKey(key, mask);
}
- else
- {
- handled = handleNavigationKey( key, mask )
- || handleSelectionKey(key, mask)
- || handleControlKey(key, mask)
- || handleSpecialKey(key, mask);
}
if( handled )
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 40821ae9fb..e60fe03e58 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -64,7 +64,8 @@ public:
ignore_tab,
show_line_numbers,
commit_on_focus_lost,
- show_context_menu;
+ show_context_menu,
+ enable_tooltip_paste;
//colors
Optional<LLUIColor> default_color;
@@ -288,6 +289,8 @@ private:
// Methods
//
void pasteHelper(bool is_primary);
+ void cleanStringForPaste(LLWString & clean_string);
+ void pasteTextWithLinebreaks(LLWString & clean_string);
void drawLineNumbers();
@@ -321,6 +324,7 @@ private:
BOOL mAllowEmbeddedItems;
bool mShowContextMenu;
bool mParseOnTheFly;
+ bool mEnableTooltipPaste;
LLUUID mSourceID;
diff --git a/indra/llui/lltoggleablemenu.cpp b/indra/llui/lltoggleablemenu.cpp
index e4d1a37569..00d52fe10d 100644
--- a/indra/llui/lltoggleablemenu.cpp
+++ b/indra/llui/lltoggleablemenu.cpp
@@ -101,3 +101,8 @@ bool LLToggleableMenu::toggleVisibility()
return true;
}
+
+bool LLToggleableMenu::addChild(LLView* view, S32 tab_group)
+{
+ return addContextChild(view, tab_group);
+}
diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h
index 2094bd776f..4717b0d0ba 100644
--- a/indra/llui/lltoggleablemenu.h
+++ b/indra/llui/lltoggleablemenu.h
@@ -47,6 +47,8 @@ public:
virtual void handleVisibilityChange (BOOL curVisibilityIn);
+ virtual bool addChild (LLView* view, S32 tab_group = 0);
+
const LLRect& getButtonRect() const { return mButtonRect; }
// Converts the given local button rect to a screen rect
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index f737d48abf..7f1566d64a 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -390,6 +390,15 @@ bool LLToolTip::hasClickCallback()
return mHasClickCallback;
}
+void LLToolTip::getToolTipMessage(std::string & message)
+{
+ if (mTextBox)
+ {
+ message = mTextBox->getText();
+ }
+}
+
+
//
// LLToolTipMgr
@@ -594,5 +603,14 @@ void LLToolTipMgr::updateToolTipVisibility()
}
+// Return the current tooltip text
+void LLToolTipMgr::getToolTipMessage(std::string & message)
+{
+ if (toolTipVisible())
+ {
+ mToolTip->getToolTipMessage(message);
+ }
+}
+
// EOF
diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h
index d71a944c3d..fad127fc4c 100644
--- a/indra/llui/lltooltip.h
+++ b/indra/llui/lltooltip.h
@@ -105,6 +105,8 @@ public:
LLToolTip(const Params& p);
void initFromParams(const LLToolTip::Params& params);
+ void getToolTipMessage(std::string & message);
+
private:
class LLTextBox* mTextBox;
class LLButton* mInfoButton;
@@ -142,6 +144,8 @@ public:
LLRect getMouseNearRect();
void updateToolTipVisibility();
+ void getToolTipMessage(std::string & message);
+
private:
void createToolTip(const LLToolTip::Params& params);
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index b9c843e931..08358484ef 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -118,6 +118,7 @@ LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)
mDoubleClickSignal(NULL),
mTransparencyType(TT_DEFAULT)
{
+ memClaim(viewmodel.get());
}
void LLUICtrl::initFromParams(const Params& p)
@@ -940,7 +941,7 @@ boost::signals2::connection LLUICtrl::setCommitCallback( boost::function<void (L
}
boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb )
{
- if (!mValidateSignal) mValidateSignal = new enable_signal_t();
+ if (!mValidateSignal) mValidateSignal = memClaim(new enable_signal_t());
return mValidateSignal->connect(boost::bind(cb, _2));
}
@@ -1003,55 +1004,55 @@ boost::signals2::connection LLUICtrl::setValidateCallback(const EnableCallbackPa
boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb )
{
- if (!mCommitSignal) mCommitSignal = new commit_signal_t();
+ if (!mCommitSignal) mCommitSignal = memClaim(new commit_signal_t());
return mCommitSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb )
{
- if (!mValidateSignal) mValidateSignal = new enable_signal_t();
+ if (!mValidateSignal) mValidateSignal = memClaim(new enable_signal_t());
return mValidateSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb )
{
- if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t();
+ if (!mMouseEnterSignal) mMouseEnterSignal = memClaim(new commit_signal_t());
return mMouseEnterSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb )
{
- if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t();
+ if (!mMouseLeaveSignal) mMouseLeaveSignal = memClaim(new commit_signal_t());
return mMouseLeaveSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
{
- if (!mMouseDownSignal) mMouseDownSignal = new mouse_signal_t();
+ if (!mMouseDownSignal) mMouseDownSignal = memClaim(new mouse_signal_t());
return mMouseDownSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t::slot_type& cb )
{
- if (!mMouseUpSignal) mMouseUpSignal = new mouse_signal_t();
+ if (!mMouseUpSignal) mMouseUpSignal = memClaim(new mouse_signal_t());
return mMouseUpSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_signal_t::slot_type& cb )
{
- if (!mRightMouseDownSignal) mRightMouseDownSignal = new mouse_signal_t();
+ if (!mRightMouseDownSignal) mRightMouseDownSignal = memClaim(new mouse_signal_t());
return mRightMouseDownSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signal_t::slot_type& cb )
{
- if (!mRightMouseUpSignal) mRightMouseUpSignal = new mouse_signal_t();
+ if (!mRightMouseUpSignal) mRightMouseUpSignal = memClaim(new mouse_signal_t());
return mRightMouseUpSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setDoubleClickCallback( const mouse_signal_t::slot_type& cb )
{
- if (!mDoubleClickSignal) mDoubleClickSignal = new mouse_signal_t();
+ if (!mDoubleClickSignal) mDoubleClickSignal = memClaim(new mouse_signal_t());
return mDoubleClickSignal->connect(cb);
}
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index f6971261d7..e6e9c66aef 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -165,17 +165,17 @@ public:
static T* createFromFile(const std::string &filename, LLView *parent, const widget_registry_t& registry)
{
T* widget = NULL;
-
+
instance().pushFileName(filename);
{
LLXMLNodePtr root_node;
if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
- {
+ {
llwarns << "Couldn't parse XUI file: " << instance().getCurFileName() << llendl;
goto fail;
}
-
+
LLView* view = getInstance()->createFromXML(root_node, parent, filename, registry, NULL);
if (view)
{
@@ -260,10 +260,8 @@ private:
// We always want to output top-left coordinates
typename T::Params output_params(params);
T::setupParamsForExport(output_params, parent);
- // Export only the differences between this any default params
- typename T::Params default_params(getDefaultParams<T>());
copyName(node, output_node);
- parser.writeXUI(output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &getDefaultParams<T>());
}
// Apply layout transformations, usually munging rect
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index c4e073ccdb..23fc53ea88 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -26,6 +26,8 @@
#include "linden_common.h"
#include "lluistring.h"
+
+#include "llfasttimer.h"
#include "llsd.h"
#include "lltrans.h"
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index ad9bec9f61..47bf410af6 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -30,7 +30,6 @@
#define LLVIEW_CPP
#include "llview.h"
-#include <cassert>
#include <sstream>
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
@@ -68,6 +67,7 @@ LLView* LLView::sPreviewClickedElement = NULL;
BOOL LLView::sDrawPreviewHighlights = FALSE;
S32 LLView::sLastLeftXML = S32_MIN;
S32 LLView::sLastBottomXML = S32_MIN;
+LLTrace::MemStat LLView::sMemStat("LLView");
std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack;
LLView::DrilldownFunc LLView::sDrilldown =
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 1c35349510..256f86c00d 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -101,7 +101,8 @@ class LLView
: public LLMouseHandler, // handles mouse events
public LLFocusableElement, // handles keyboard events
public LLMortician, // lazy deletion
- public LLHandleProvider<LLView> // passes out weak references to self
+ public LLHandleProvider<LLView>, // passes out weak references to self
+ public LLTrace::MemTrackable<LLView> // track memory usage
{
public:
struct Follows : public LLInitParam::ChoiceBlock<Follows>
@@ -672,6 +673,7 @@ public:
static S32 sLastLeftXML;
static S32 sLastBottomXML;
static BOOL sForceReshape;
+ static LLTrace::MemStat sMemStat;
};
class LLCompareByTabOrder
diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp
index a9f8acc440..1bd09e8086 100644
--- a/indra/llui/llviewmodel.cpp
+++ b/indra/llui/llviewmodel.cpp
@@ -35,6 +35,8 @@
// external library headers
// other Linden headers
+LLTrace::MemStat LLViewModel::sMemStat("LLViewModel");
+
///
LLViewModel::LLViewModel()
: mDirty(false)
@@ -80,7 +82,10 @@ LLTextViewModel::LLTextViewModel(const LLSD& value)
void LLTextViewModel::setValue(const LLSD& value)
{
LLViewModel::setValue(value);
+ memDisclaim(mDisplay);
mDisplay = utf8str_to_wstring(value.asString());
+ memClaim(mDisplay);
+
// mDisplay and mValue agree
mUpdateFromDisplay = false;
}
@@ -91,7 +96,9 @@ void LLTextViewModel::setDisplay(const LLWString& value)
// and do the utf8str_to_wstring() to get the corresponding mDisplay
// value. But a text editor might want to edit the display string
// directly, then convert back to UTF8 on commit.
+ memDisclaim(mDisplay);
mDisplay = value;
+ memClaim(mDisplay);
mDirty = true;
// Don't immediately convert to UTF8 -- do it lazily -- we expect many
// more setDisplay() calls than getValue() calls. Just flag that it needs
diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h
index ef2e314799..214780393b 100644
--- a/indra/llui/llviewmodel.h
+++ b/indra/llui/llviewmodel.h
@@ -39,6 +39,7 @@
#include "llrefcount.h"
#include "stdenums.h"
#include "llstring.h"
+#include "lltrace.h"
#include <string>
class LLScrollListItem;
@@ -60,7 +61,9 @@ typedef LLPointer<LLListViewModel> LLListViewModelPtr;
* LLViewModel data. This way, the LLViewModel is quietly deleted when the
* last referencing widget is destroyed.
*/
-class LLViewModel: public LLRefCount
+class LLViewModel
+: public LLRefCount,
+ public LLTrace::MemTrackable<LLViewModel>
{
public:
LLViewModel();
@@ -80,6 +83,8 @@ public:
//
void setDirty() { mDirty = true; }
+ static LLTrace::MemStat sMemStat;
+
protected:
LLSD mValue;
bool mDirty;
diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp
index afc76024d1..903f10ce10 100644
--- a/indra/llui/llxuiparser.cpp
+++ b/indra/llui/llxuiparser.cpp
@@ -29,7 +29,7 @@
#include "llxuiparser.h"
#include "llxmlnode.h"
-
+#include "llfasttimer.h"
#ifdef LL_STANDALONE
#include <expat.h>
#else
@@ -861,11 +861,11 @@ bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& blo
return any_parsed;
}
-void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block)
+void LLXUIParser::writeXUIImpl(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block)
{
mWriteRootNode = node;
name_stack_t name_stack = Parser::name_stack_t();
- block.serializeBlock(*this, name_stack, diff_block);
+ block.serializeBlock(*this, name_stack, rules, diff_block);
mOutNodes.clear();
}
@@ -880,16 +880,24 @@ LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack)
it = next_it)
{
++next_it;
+ bool force_new_node = false;
+
if (it->first.empty())
{
it->second = false;
continue;
}
+ if (next_it != stack.end() && next_it->first.empty() && next_it->second)
+ {
+ force_new_node = true;
+ }
+
+
out_nodes_t::iterator found_it = mOutNodes.find(it->first);
// node with this name not yet written
- if (found_it == mOutNodes.end() || it->second)
+ if (found_it == mOutNodes.end() || it->second || force_new_node)
{
// make an attribute if we are the last element on the name stack
bool is_attribute = next_it == stack.end();
diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h
index d7cd256967..8d0276a8ad 100644
--- a/indra/llui/llxuiparser.h
+++ b/indra/llui/llxuiparser.h
@@ -109,9 +109,25 @@ public:
/*virtual*/ void parserError(const std::string& message);
void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false);
- void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL);
+ template<typename BLOCK>
+ void writeXUI(LLXMLNodePtr node,
+ const BLOCK& block,
+ const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(),
+ const LLInitParam::BaseBlock* diff_block = NULL)
+ {
+ if (!diff_block
+ && !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE))
+ {
+ diff_block = &LLInitParam::defaultValue<BLOCK>();
+ }
+ writeXUIImpl(node, block, rules, diff_block);
+ }
private:
+ void writeXUIImpl(LLXMLNodePtr node,
+ const LLInitParam::BaseBlock& block,
+ const LLInitParam::predicate_rule_t rules,
+ const LLInitParam::BaseBlock* diff_block);
bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block);
bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);