summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/CMakeLists.txt1
-rw-r--r--indra/llui/llaccordionctrl.cpp2
-rw-r--r--indra/llui/llaccordionctrltab.cpp1
-rw-r--r--indra/llui/llaccordionctrltab.h10
-rw-r--r--indra/llui/llcheckboxctrl.cpp9
-rw-r--r--indra/llui/llcheckboxctrl.h2
-rw-r--r--indra/llui/llcombobox.cpp16
-rw-r--r--indra/llui/llcombobox.h7
-rw-r--r--indra/llui/llfloater.cpp68
-rw-r--r--indra/llui/llfloater.h1
-rw-r--r--indra/llui/llfloaterreg.cpp2
-rw-r--r--indra/llui/lllayoutstack.cpp408
-rw-r--r--indra/llui/lllayoutstack.h78
-rw-r--r--indra/llui/lllineeditor.cpp48
-rw-r--r--indra/llui/lllineeditor.h14
-rw-r--r--indra/llui/llmultislider.cpp4
-rw-r--r--indra/llui/llmultisliderctrl.cpp2
-rw-r--r--indra/llui/llnotifications.cpp570
-rw-r--r--indra/llui/llnotifications.h228
-rw-r--r--indra/llui/llnotificationslistener.cpp7
-rw-r--r--indra/llui/llnotificationtemplate.h282
-rw-r--r--indra/llui/llpanel.cpp122
-rw-r--r--indra/llui/llpanel.h62
-rw-r--r--indra/llui/llradiogroup.cpp4
-rw-r--r--indra/llui/llrngwriter.cpp5
-rw-r--r--indra/llui/llscrolllistctrl.cpp43
-rw-r--r--indra/llui/llsdparam.cpp207
-rw-r--r--indra/llui/llsdparam.h43
-rw-r--r--indra/llui/llspinctrl.cpp2
-rw-r--r--indra/llui/llstyle.cpp6
-rw-r--r--indra/llui/llstyle.h2
-rw-r--r--indra/llui/lltextbase.cpp83
-rw-r--r--indra/llui/lltextbase.h7
-rw-r--r--indra/llui/lltooltip.cpp9
-rw-r--r--indra/llui/llui.cpp11
-rw-r--r--indra/llui/lluicolortable.cpp10
-rw-r--r--indra/llui/lluictrlfactory.cpp222
-rw-r--r--indra/llui/lluictrlfactory.h203
-rw-r--r--indra/llui/lluistring.cpp19
-rw-r--r--indra/llui/lluistring.h9
-rw-r--r--indra/llui/llurlentry.cpp309
-rw-r--r--indra/llui/llurlentry.h91
-rw-r--r--indra/llui/llurlmatch.cpp9
-rw-r--r--indra/llui/llurlmatch.h22
-rw-r--r--indra/llui/llurlregistry.cpp20
-rw-r--r--indra/llui/llurlregistry.h8
-rw-r--r--indra/llui/llview.cpp24
-rw-r--r--indra/llui/llview.h30
-rw-r--r--indra/llui/tests/llurlentry_stub.cpp126
-rw-r--r--indra/llui/tests/llurlentry_test.cpp21
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp153
51 files changed, 2290 insertions, 1352 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 8e78a5fefd..e98201ea63 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -158,6 +158,7 @@ set(llui_HEADER_FILES
llnotifications.h
llnotificationslistener.h
llnotificationsutil.h
+ llnotificationtemplate.h
llpanel.h
llprogressbar.h
llradiogroup.h
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index f9ffaaa646..d636161baf 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -83,7 +83,7 @@ LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
mSingleExpansion = false;
mFitParent = false;
- LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml");
+ buildFromFile( "accordion_parent.xml");
}
//---------------------------------------------------------------------------------
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 32112c6c51..179b32098a 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -141,6 +141,7 @@ LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader(
textboxParams.use_ellipses = true;
textboxParams.bg_visible = false;
textboxParams.mouse_opaque = false;
+ textboxParams.parse_urls = false;
mHeaderTextbox = LLUICtrlFactory::create<LLTextBox>(textboxParams);
addChild(mHeaderTextbox);
}
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index d6ac8cbc8f..dddaa581e6 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -85,10 +85,10 @@ public:
Optional<bool> selection_enabled;
- Optional<S32> padding_left;
- Optional<S32> padding_right;
- Optional<S32> padding_top;
- Optional<S32> padding_bottom;
+ Optional<S32> padding_left,
+ padding_right,
+ padding_top,
+ padding_bottom;
Params();
};
@@ -170,7 +170,7 @@ public:
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
- virtual bool addChild(LLView* child, S32 tab_group);
+ virtual bool addChild(LLView* child, S32 tab_group = 0 );
bool isExpanded() const { return mDisplayChildren; }
diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp
index cbc8f12472..bbd8db2645 100644
--- a/indra/llui/llcheckboxctrl.cpp
+++ b/indra/llui/llcheckboxctrl.cpp
@@ -50,9 +50,7 @@ template class LLCheckBoxCtrl* LLView::getChild<class LLCheckBoxCtrl>(
const std::string& name, BOOL recurse) const;
LLCheckBoxCtrl::Params::Params()
-: text_enabled_color("text_enabled_color"),
- text_disabled_color("text_disabled_color"),
- initial_value("initial_value", false),
+: initial_value("initial_value", false),
label_text("label_text"),
check_button("check_button"),
radio_style("radio_style")
@@ -61,8 +59,8 @@ LLCheckBoxCtrl::Params::Params()
LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
: LLUICtrl(p),
- mTextEnabledColor(p.text_enabled_color()),
- mTextDisabledColor(p.text_disabled_color()),
+ mTextEnabledColor(p.label_text.text_color()),
+ mTextDisabledColor(p.label_text.text_readonly_color()),
mFont(p.font())
{
mViewModel->setValue(LLSD(p.initial_value));
@@ -89,7 +87,6 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
{
tbparams.font(p.font);
}
- tbparams.text_color( p.enabled() ? p.text_enabled_color() : p.text_disabled_color() );
mLabel = LLUICtrlFactory::create<LLTextBox> (tbparams);
addChild(mLabel);
diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h
index 0147088280..67d8091a97 100644
--- a/indra/llui/llcheckboxctrl.h
+++ b/indra/llui/llcheckboxctrl.h
@@ -52,8 +52,6 @@ public:
struct Params
: public LLInitParam::Block<Params, LLUICtrl::Params>
{
- Optional<LLUIColor> text_enabled_color;
- Optional<LLUIColor> text_disabled_color;
Optional<bool> initial_value; // override LLUICtrl initial_value
Optional<LLTextBox::Params> label_text;
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 910bab9a97..2dabbc7767 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -52,8 +52,6 @@
#include "lltooltip.h"
// Globals
-S32 LLCOMBOBOX_HEIGHT = 0;
-S32 LLCOMBOBOX_WIDTH = 0;
S32 MAX_COMBO_WIDTH = 500;
static LLDefaultChildRegistry::Register<LLComboBox> register_combo_box("combo_box");
@@ -139,8 +137,8 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p)
// Grab the mouse-up event and make sure the button state is correct
mList->setMouseUpCallback(boost::bind(&LLComboBox::onListMouseUp, this));
- for (LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items().begin();
- it != p.items().end();
+ for (LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items.begin();
+ it != p.items.end();
++it)
{
LLScrollListItem::Params item_params = *it;
@@ -486,7 +484,7 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p)
LLLineEditor::Params params = p.combo_editor;
params.rect(text_entry_rect);
params.default_text(LLStringUtil::null);
- params.max_length_bytes(mMaxChars);
+ params.max_length.bytes(mMaxChars);
params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2));
params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1));
params.commit_on_focus_lost(false);
@@ -705,10 +703,10 @@ void LLComboBox::onItemSelected(const LLSD& data)
setLabel(getSelectedItemLabel());
if (mAllowTextEntry)
- {
- gFocusMgr.setKeyboardFocus(mTextEntry);
- mTextEntry->selectAll();
- }
+ {
+ gFocusMgr.setKeyboardFocus(mTextEntry);
+ mTextEntry->selectAll();
+ }
}
// hiding the list reasserts the old value stored in the text editor/dropdown button
hideList();
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index f369147ded..5f0e4a6843 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -43,9 +43,6 @@
class LLFontGL;
class LLViewBorder;
-extern S32 LLCOMBOBOX_HEIGHT;
-extern S32 LLCOMBOBOX_WIDTH;
-
class LLComboBox
: public LLUICtrl, public LLCtrlListInterface
{
@@ -224,8 +221,8 @@ private:
commit_callback_t mPrearrangeCallback;
commit_callback_t mTextEntryCallback;
commit_callback_t mSelectionCallback;
- boost::signals2::connection mTopLostSignalConnection;
- S32 mLastSelectedIndex;
+ boost::signals2::connection mTopLostSignalConnection;
+ S32 mLastSelectedIndex;
};
// A combo box with icons for the list of items.
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index d23b876543..b758070419 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -36,6 +36,7 @@
#include "lluictrlfactory.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
+#include "lldir.h"
#include "lldraghandle.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
@@ -2829,7 +2830,8 @@ LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build");
bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node)
{
Params params(LLUICtrlFactory::getDefaultParams<LLFloater>());
- LLXUIParser::instance().readXUI(node, params, filename); // *TODO: Error checking
+ LLXUIParser parser;
+ parser.readXUI(node, params, filename); // *TODO: Error checking
if (output_node)
{
@@ -2837,8 +2839,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
setupParamsForExport(output_params, parent);
Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>());
output_node->setName(node->getName()->mString);
- LLXUIParser::instance().writeXUI(
- output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, &default_params);
}
// Default floater position to top-left corner of screen
@@ -2933,3 +2934,64 @@ bool LLFloater::isVisible(const LLFloater* floater)
{
return floater && floater->getVisible();
}
+
+static LLFastTimer::DeclareTimer FTM_BUILD_FLOATERS("Build Floaters");
+
+bool LLFloater::buildFromFile(const std::string& filename, LLXMLNodePtr output_node)
+{
+ LLFastTimer timer(FTM_BUILD_FLOATERS);
+ LLXMLNodePtr root;
+
+ //if exporting, only load the language being exported,
+ //instead of layering localized version on top of english
+ if (output_node)
+ {
+ if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
+ {
+ llwarns << "Couldn't parse floater from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
+ return false;
+ }
+ }
+ else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
+ {
+ llwarns << "Couldn't parse floater from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
+ return false;
+ }
+
+ // root must be called floater
+ if( !(root->hasName("floater") || root->hasName("multi_floater")) )
+ {
+ llwarns << "Root node should be named floater in: " << filename << llendl;
+ return false;
+ }
+
+ bool res = true;
+
+ lldebugs << "Building floater " << filename << llendl;
+ LLUICtrlFactory::instance().pushFileName(filename);
+ {
+ if (!getFactoryMap().empty())
+ {
+ LLPanel::sFactoryStack.push_front(&getFactoryMap());
+ }
+
+ // for local registry callbacks; define in constructor, referenced in XUI or postBuild
+ getCommitCallbackRegistrar().pushScope();
+ getEnableCallbackRegistrar().pushScope();
+
+ res = initFloaterXML(root, getParent(), filename, output_node);
+
+ setXMLFilename(filename);
+
+ getCommitCallbackRegistrar().popScope();
+ getEnableCallbackRegistrar().popScope();
+
+ if (!getFactoryMap().empty())
+ {
+ LLPanel::sFactoryStack.pop_front();
+ }
+ }
+ LLUICtrlFactory::instance().popFileName();
+
+ return res;
+}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index d26f41b4c7..32d03f9f83 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -141,6 +141,7 @@ public:
// Don't export top/left for rect, only height/width
static void setupParamsForExport(Params& p, LLView* parent);
+ bool buildFromFile(const std::string &filename, LLXMLNodePtr output_node = NULL);
boost::signals2::connection setMinimizeCallback( const commit_signal_t::slot_type& cb );
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 4720ebb822..4677d535db 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -121,7 +121,7 @@ LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key)
res = build_func(key);
- bool success = LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL);
+ bool success = res->buildFromFile(xui_file, NULL);
if (!success)
{
llwarns << "Failed to build floater type: '" << name << "'." << llendl;
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 0ff7557ead..940c7e7e18 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -35,95 +35,66 @@
#include "llresizebar.h"
#include "llcriticaldamp.h"
-static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack", &LLLayoutStack::fromXML);
-
+static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");
+static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel");
//
-// LLLayoutStack
+// LLLayoutPanel
//
-struct LLLayoutStack::LayoutPanel
-{
- 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),
+LLLayoutPanel::LLLayoutPanel(const Params& p)
+: LLPanel(p),
+ mMinDim(p.min_dim),
+ mMaxDim(p.max_dim),
+ mAutoResize(p.auto_resize),
+ mUserResize(p.user_resize),
mCollapsed(FALSE),
mCollapseAmt(0.f),
mVisibleAmt(1.f), // default to fully visible
mResizeBar(NULL)
{
- LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
- LLRect resize_bar_rect = panelp->getRect();
-
- S32 min_dim;
- if (orientation == HORIZONTAL)
+ // panels initialized as hidden should not start out partially visible
+ if (!getVisible())
{
- min_dim = mMinHeight;
+ mVisibleAmt = 0.f;
}
- else
- {
- min_dim = mMinWidth;
- }
- LLResizeBar::Params p;
- p.name("resize");
- p.resizing_view(mPanel);
- p.min_size(min_dim);
- p.side(side);
- p.snapping_enabled(false);
- mResizeBar = LLUICtrlFactory::create<LLResizeBar>(p);
- // panels initialized as hidden should not start out partially visible
- if (!mPanel->getVisible())
- {
- mVisibleAmt = 0.f;
}
+
+void LLLayoutPanel::initFromParams(const Params& p)
+ {
+ LLPanel::initFromParams(p);
+ setFollowsNone();
}
- ~LayoutPanel()
+
+LLLayoutPanel::~LLLayoutPanel()
{
// probably not necessary, but...
delete mResizeBar;
mResizeBar = NULL;
}
- F32 getCollapseFactor()
+F32 LLLayoutPanel::getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation)
{
- if (mOrientation == HORIZONTAL)
+ if (orientation == LLLayoutStack::HORIZONTAL)
{
F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth()));
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinDim / (F32)llmax(1, getRect().getWidth()));
return mVisibleAmt * collapse_amt;
}
else
{
F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinHeight / (F32)llmax(1, mPanel->getRect().getHeight())));
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinDim / (F32)llmax(1, getRect().getHeight())));
return mVisibleAmt * collapse_amt;
}
}
- 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;
- LLResizeBar* mResizeBar;
- ELayoutOrientation mOrientation;
- F32 mVisibleAmt;
- F32 mCollapseAmt;
-};
+//
+// LLLayoutStack
+//
LLLayoutStack::Params::Params()
-: orientation("orientation", std::string("vertical")),
+: orientation("orientation"),
animate("animate", true),
clip("clip", true),
border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))
@@ -157,18 +128,18 @@ void LLLayoutStack::draw()
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
// clip to layout rectangle, not bounding rectangle
- LLRect clip_rect = (*panel_it)->mPanel->getRect();
+ LLRect clip_rect = (*panel_it)->getRect();
// scale clipping rectangle by visible amount
if (mOrientation == HORIZONTAL)
{
- clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());
+ clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor(mOrientation));
}
else
{
- clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());
+ clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor(mOrientation));
}
- LLPanel* panelp = (*panel_it)->mPanel;
+ LLPanel* panelp = (*panel_it);
LLLocalClipRect clip(clip_rect, mClip);
// only force drawing invisible children if visible amount is non-zero
@@ -179,7 +150,7 @@ void LLLayoutStack::draw()
void LLLayoutStack::removeChild(LLView* view)
{
- LayoutPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast<LLPanel*>(view));
+ LLLayoutPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast<LLPanel*>(view));
if (embedded_panelp)
{
@@ -200,149 +171,16 @@ BOOL LLLayoutStack::postBuild()
return TRUE;
}
-static void get_attribute_s32_and_write(LLXMLNodePtr node,
- const char* name,
- S32 *value,
- S32 default_value,
- LLXMLNodePtr output_child)
-{
- BOOL has_attr = node->getAttributeS32(name, *value);
- if (has_attr && *value != default_value && output_child)
- {
- // create an attribute child node
- LLXMLNodePtr child_attr = output_child->createChild(name, TRUE);
- child_attr->setIntValue(*value);
- }
-}
-
-static void get_attribute_bool_and_write(LLXMLNodePtr node,
- const char* name,
- BOOL *value,
- BOOL default_value,
- LLXMLNodePtr output_child)
-{
- BOOL has_attr = node->getAttributeBOOL(name, *value);
- if (has_attr && *value != default_value && output_child)
- {
- LLXMLNodePtr child_attr = output_child->createChild(name, TRUE);
- child_attr->setBoolValue(*value);
- }
-}
-//static
-LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
-{
- 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
- // logic). JC
- if (output_node)
- {
- Params output_params(p);
- setupParamsForExport(output_params, parent);
- LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams<LLLayoutStack>());
- output_node->setName(node->getName()->mString);
- LLXUIParser::instance().writeXUI(
- output_node, output_params, &default_params);
- }
-
- p.from_xui = true;
- applyXUILayout(p, parent);
- LLLayoutStack* layout_stackp = LLUICtrlFactory::create<LLLayoutStack>(p);
-
- if (parent && layout_stackp)
- {
- S32 tab_group = p.tab_group.isProvided() ? p.tab_group() : parent->getLastTabGroup();
-
- parent->addChild(layout_stackp, tab_group);
- }
-
- for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling())
- {
- 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;
- if (output_node)
+bool LLLayoutStack::addChild(LLView* child, S32 tab_group)
{
- output_child = output_node->createChild("", FALSE);
- }
-
- // Layout stack allows child nodes to acquire additional attributes,
- // such as "min_width" in: <button label="Foo" min_width="100"/>
- // If these attributes exist and have non-default values, write them
- // to the output node.
- get_attribute_s32_and_write(child_node, "min_width", &min_width,
- 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);
-
- if (child_node->hasName("layout_panel"))
- {
- BOOL user_resize = TRUE;
- get_attribute_bool_and_write(child_node, "user_resize", &user_resize,
- TRUE, output_child);
- LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child_node, layout_stackp, output_child);
+ LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child);
if (panelp)
{
- panelp->setFollowsNone();
- layout_stackp->addPanel(panelp, min_width, min_height, max_width, max_height, auto_resize, user_resize);
+ mPanels.push_back(panelp);
}
+ return LLView::addChild(child, tab_group);
}
- else
- {
- BOOL user_resize = FALSE;
- get_attribute_bool_and_write(child_node, "user_resize", &user_resize,
- 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, LLPanel::child_registry_t::instance(), output_child);
- if (new_child)
- {
- // put child in new embedded panel
- 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);
- }
- else
- {
- panelp->die();
- }
- }
-
- if (output_child && !output_child->mChildren && output_child->mAttributes.empty() && output_child->getValue().empty())
- {
- output_node->deleteChild(output_child);
- }
- }
-
- if (!layout_stackp->postBuild())
- {
- delete layout_stackp;
- return NULL;
- }
- return layout_stackp;
-}
S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
{
@@ -370,8 +208,8 @@ S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
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);
+ LLLayoutPanel* embedded_panel_to_move = findEmbeddedPanel(panel_to_move);
+ LLLayoutPanel* 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)
{
@@ -384,34 +222,14 @@ void LLLayoutStack::movePanel(LLPanel* panel_to_move, LLPanel* target_panel, boo
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)
+void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate)
{
- // panel starts off invisible (collapsed)
- if (animate == ANIMATE)
- {
- panel->setVisible(FALSE);
- }
- 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);
-
- if (panel->getParent() != this)
- {
- addChild(panel);
- }
- addChild(embedded_panel->mResizeBar);
+ addChild(panel);
- // bring all resize bars to the front so that they are clickable even over the panels
- // with a bit of overlap
- for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
- {
- LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
- sendChildToFront(resize_barp);
- }
-
- // start expanding panel animation
+ // panel starts off invisible (collapsed)
if (animate == ANIMATE)
{
+ panel->mVisibleAmt = 0.f;
panel->setVisible(TRUE);
}
}
@@ -423,7 +241,7 @@ void LLLayoutStack::removePanel(LLPanel* panel)
void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
{
- LayoutPanel* panel_container = findEmbeddedPanel(panel);
+ LLLayoutPanel* panel_container = findEmbeddedPanel(panel);
if (!panel_container) return;
panel_container->mCollapsed = collapsed;
@@ -431,7 +249,7 @@ void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize)
{
- LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+ LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
if (panel)
{
@@ -441,7 +259,7 @@ void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL au
void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize)
{
- LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+ LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
if (panel)
{
@@ -449,27 +267,25 @@ void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_
}
}
-bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp)
+bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_dimp)
{
- LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+ LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
if (panel)
{
- if (min_widthp) *min_widthp = panel->mMinWidth;
- if (min_heightp) *min_heightp = panel->mMinHeight;
+ if (min_dimp) *min_dimp = panel->mMinDim;
}
return NULL != panel;
}
-bool LLLayoutStack::getPanelMaxSize(const std::string& panel_name, S32* max_widthp, S32* max_heightp)
+bool LLLayoutStack::getPanelMaxSize(const std::string& panel_name, S32* max_dimp)
{
- LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+ LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
if (panel)
{
- if (max_widthp) *max_widthp = panel->mMaxWidth;
- if (max_heightp) *max_heightp = panel->mMaxHeight;
+ if (max_dimp) *max_dimp = panel->mMaxDim;
}
return NULL != panel;
@@ -481,6 +297,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
LLFastTimer ft(FTM_UPDATE_LAYOUT);
static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0);
calcMinExtents();
+ createResizeBars();
// calculate current extents
S32 total_width = 0;
@@ -492,7 +309,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it)->mPanel;
+ LLPanel* panelp = (*panel_it);
if (panelp->getVisible())
{
if (mAnimate)
@@ -542,11 +359,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
if (mOrientation == HORIZONTAL)
{
// enforce minimize size constraint by default
- if (panelp->getRect().getWidth() < (*panel_it)->mMinWidth)
+ if (panelp->getRect().getWidth() < (*panel_it)->mMinDim)
{
- panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight());
+ panelp->reshape((*panel_it)->mMinDim, panelp->getRect().getHeight());
}
- total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor());
+ total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor(mOrientation));
// want n-1 panel gaps for n panels
if (panel_it != mPanels.begin())
{
@@ -556,11 +373,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
else //VERTICAL
{
// enforce minimize size constraint by default
- if (panelp->getRect().getHeight() < (*panel_it)->mMinHeight)
+ if (panelp->getRect().getHeight() < (*panel_it)->mMinDim)
{
- panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight);
+ panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinDim);
}
- total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor());
+ total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor(mOrientation));
if (panel_it != mPanels.begin())
{
total_height += mPanelSpacing;
@@ -574,7 +391,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
// panels that are not fully visible do not count towards shrink headroom
- if ((*panel_it)->getCollapseFactor() < 1.f)
+ if ((*panel_it)->getCollapseFactor(mOrientation) < 1.f)
{
continue;
}
@@ -587,11 +404,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
if (mOrientation == HORIZONTAL)
{
- shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ shrink_headroom_total += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
}
else //VERTICAL
{
- shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ shrink_headroom_total += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
}
}
else
@@ -599,13 +416,13 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
num_resizable_panels++;
if (mOrientation == HORIZONTAL)
{
- shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
- shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ shrink_headroom_available += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
+ shrink_headroom_total += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
}
else //VERTICAL
{
- shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
- shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ shrink_headroom_available += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
+ shrink_headroom_total += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
}
}
}
@@ -628,17 +445,25 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it)->mPanel;
+ LLPanel* panelp = (*panel_it);
S32 cur_width = panelp->getRect().getWidth();
S32 cur_height = panelp->getRect().getHeight();
- S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
- S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
+ S32 new_width = cur_width;
+ S32 new_height = cur_height;
+ if (mOrientation == HORIZONTAL)
+ {
+ new_width = llmax((*panel_it)->mMinDim, new_width);
+ }
+ else
+ {
+ new_height = llmax((*panel_it)->mMinDim, new_height);
+ }
S32 delta_size = 0;
// if panel can automatically resize (not animating, and resize flag set)...
- if ((*panel_it)->getCollapseFactor() == 1.f
+ if ((*panel_it)->getCollapseFactor(mOrientation) == 1.f
&& (force_resize || (*panel_it)->mAutoResize)
&& !(*panel_it)->mResizeBar->hasMouseCapture())
{
@@ -649,8 +474,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
- delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available)) : 0;
- shrink_headroom_available -= (cur_width - (*panel_it)->mMinWidth);
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinDim) / (F32)shrink_headroom_available)) : 0;
+ shrink_headroom_available -= (cur_width - (*panel_it)->mMinDim);
}
else
{
@@ -659,7 +484,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
- new_width = llmax((*panel_it)->mMinWidth, cur_width + delta_size);
+ new_width = llmax((*panel_it)->mMinDim, cur_width + delta_size);
}
else
{
@@ -672,8 +497,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
- delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available)) : 0;
- shrink_headroom_available -= (cur_height - (*panel_it)->mMinHeight);
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinDim) / (F32)shrink_headroom_available)) : 0;
+ shrink_headroom_available -= (cur_height - (*panel_it)->mMinDim);
}
else
{
@@ -681,7 +506,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
- new_height = llmax((*panel_it)->mMinHeight, cur_height + delta_size);
+ new_height = llmax((*panel_it)->mMinDim, cur_height + delta_size);
}
else
{
@@ -722,11 +547,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
if (mOrientation == HORIZONTAL)
{
- cur_x += llround(new_width * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
+ cur_x += llround(new_width * (*panel_it)->getCollapseFactor(mOrientation)) + mPanelSpacing;
}
else //VERTICAL
{
- cur_y -= llround(new_height * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
+ cur_y -= llround(new_height * (*panel_it)->getCollapseFactor(mOrientation)) + mPanelSpacing;
}
}
@@ -734,19 +559,19 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
LLResizeBar* last_resize_bar = NULL;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it)->mPanel;
+ LLPanel* panelp = (*panel_it);
if (mOrientation == HORIZONTAL)
{
(*panel_it)->mResizeBar->setResizeLimits(
- (*panel_it)->mMinWidth,
- (*panel_it)->mMinWidth + shrink_headroom_total);
+ (*panel_it)->mMinDim,
+ (*panel_it)->mMinDim + shrink_headroom_total);
}
else //VERTICAL
{
(*panel_it)->mResizeBar->setResizeLimits(
- (*panel_it)->mMinHeight,
- (*panel_it)->mMinHeight + shrink_headroom_total);
+ (*panel_it)->mMinDim,
+ (*panel_it)->mMinDim + shrink_headroom_total);
}
// toggle resize bars based on panel visibility, resizability, etc
@@ -782,14 +607,14 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
} // end LLLayoutStack::updateLayout
-LLLayoutStack::LayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
+LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
{
if (!panelp) return NULL;
e_panel_list_t::const_iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- if ((*panel_it)->mPanel == panelp)
+ if ((*panel_it) == panelp)
{
return *panel_it;
}
@@ -797,15 +622,15 @@ LLLayoutStack::LayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) co
return NULL;
}
-LLLayoutStack::LayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const
+LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const
{
- LayoutPanel* result = NULL;
+ LLLayoutPanel* result = NULL;
for (e_panel_list_t::const_iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LayoutPanel* p = *panel_it;
+ LLLayoutPanel* p = *panel_it;
- if (p->mPanel->getName() == name)
+ if (p->getName() == name)
{
result = p;
break;
@@ -826,9 +651,7 @@ void LLLayoutStack::calcMinExtents()
{
if (mOrientation == HORIZONTAL)
{
- mMinHeight = llmax( mMinHeight,
- (*panel_it)->mMinHeight);
- mMinWidth += (*panel_it)->mMinWidth;
+ mMinWidth += (*panel_it)->mMinDim;
if (panel_it != mPanels.begin())
{
mMinWidth += mPanelSpacing;
@@ -836,9 +659,7 @@ void LLLayoutStack::calcMinExtents()
}
else //VERTICAL
{
- mMinWidth = llmax( mMinWidth,
- (*panel_it)->mMinWidth);
- mMinHeight += (*panel_it)->mMinHeight;
+ mMinHeight += (*panel_it)->mMinDim;
if (panel_it != mPanels.begin())
{
mMinHeight += mPanelSpacing;
@@ -847,6 +668,37 @@ void LLLayoutStack::calcMinExtents()
}
}
+void LLLayoutStack::createResizeBars()
+{
+ for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLLayoutPanel* lp = (*panel_it);
+ if (lp->mResizeBar == NULL)
+ {
+ LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
+ LLRect resize_bar_rect = getRect();
+
+ LLResizeBar::Params resize_params;
+ resize_params.name("resize");
+ resize_params.resizing_view(lp);
+ resize_params.min_size(lp->mMinDim);
+ resize_params.side(side);
+ resize_params.snapping_enabled(false);
+ LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
+ lp->mResizeBar = resize_bar;
+ LLView::addChild(resize_bar, 0);
+
+ // bring all resize bars to the front so that they are clickable even over the panels
+ // with a bit of overlap
+ for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
+ sendChildToFront(resize_barp);
+ }
+ }
+ }
+}
+
// 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
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 6fcc8e2ac3..e19ef403ef 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -28,16 +28,21 @@
#ifndef LL_LLLAYOUTSTACK_H
#define LL_LLLAYOUTSTACK_H
-#include "llview.h"
+#include "llpanel.h"
class LLPanel;
+class LLLayoutPanel;
+
class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
{
public:
+ struct LayoutStackRegistry : public LLChildRegistry<LayoutStackRegistry>
+ {};
+
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
- Optional<std::string> orientation;
+ Mandatory<std::string> orientation;
Optional<S32> border_size;
Optional<bool> animate,
clip;
@@ -45,6 +50,8 @@ public:
Params();
};
+ typedef LayoutStackRegistry child_registry_t;
+
typedef enum e_layout_orientation
{
HORIZONTAL,
@@ -56,6 +63,7 @@ public:
/*virtual*/ void draw();
/*virtual*/ void removeChild(LLView*);
/*virtual*/ BOOL postBuild();
+ /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0);
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
@@ -68,7 +76,7 @@ public:
ANIMATE
} EAnimate;
- void addPanel(LLPanel* panel, S32 min_width, S32 min_height, S32 max_width, S32 max_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
+ void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE);
void removePanel(LLPanel* panel);
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
S32 getNumPanels() { return mPanels.size(); }
@@ -82,20 +90,18 @@ public:
void setPanelUserResize(const std::string& panel_name, BOOL user_resize);
/**
- * Gets minimal width and/or height of the specified by name panel.
+ * Gets minimal dimension along layout_stack axis of the specified by name panel.
*
- * If it is necessary to get only the one dimension pass NULL for another one.
* @returns true if specified by panel_name internal panel exists, false otherwise.
*/
- bool getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp);
+ bool getPanelMinSize(const std::string& panel_name, S32* min_dimp);
/**
- * Gets maximal width and/or height of the specified by name panel.
+ * Gets maximal dimension along layout_stack axis of the specified by name panel.
*
- * If it is necessary to get only the one dimension pass NULL for another one.
* @returns true if specified by panel_name internal panel exists, false otherwise.
*/
- bool getPanelMaxSize(const std::string& panel_name, S32* max_width, S32* max_height);
+ bool getPanelMaxSize(const std::string& panel_name, S32* max_dim);
void updateLayout(BOOL force_resize = FALSE);
@@ -110,19 +116,18 @@ protected:
friend class LLUICtrlFactory;
private:
- struct LayoutPanel;
-
+ void createResizeBars();
void calcMinExtents();
S32 getDefaultHeight(S32 cur_height);
S32 getDefaultWidth(S32 cur_width);
const ELayoutOrientation mOrientation;
- typedef std::vector<LayoutPanel*> e_panel_list_t;
+ typedef std::vector<LLLayoutPanel*> e_panel_list_t;
e_panel_list_t mPanels;
- LayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
- LayoutPanel* findEmbeddedPanelByName(const std::string& name) const;
+ LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
+ LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const;
S32 mMinWidth; // calculated by calcMinExtents
S32 mMinHeight; // calculated by calcMinExtents
@@ -134,4 +139,49 @@ private:
bool mClip;
}; // end class LLLayoutStack
+class LLLayoutPanel : public LLPanel
+{
+friend class LLLayoutStack;
+friend class LLUICtrlFactory;
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<S32> min_dim,
+ max_dim;
+ Optional<bool> user_resize,
+ auto_resize;
+
+ Params()
+ : min_dim("min_dim", 0),
+ max_dim("max_dim", 0),
+ user_resize("user_resize", true),
+ auto_resize("auto_resize", true)
+ {
+ addSynonym(min_dim, "min_width");
+ addSynonym(min_dim, "min_height");
+ addSynonym(max_dim, "max_width");
+ addSynonym(max_dim, "max_height");
+ }
+ };
+
+ ~LLLayoutPanel();
+
+ void initFromParams(const Params& p);
+protected:
+ LLLayoutPanel(const Params& p) ;
+
+
+ F32 getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation);
+
+ S32 mMinDim;
+ S32 mMaxDim;
+ BOOL mAutoResize;
+ BOOL mUserResize;
+ BOOL mCollapsed;
+ class LLResizeBar* mResizeBar;
+ F32 mVisibleAmt;
+ F32 mCollapseAmt;
+};
+
+
#endif
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 2759167d04..5f5fe851bb 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -78,7 +78,7 @@ template class LLLineEditor* LLView::getChild<class LLLineEditor>(
//
LLLineEditor::Params::Params()
-: max_length_bytes("max_length", 254),
+: max_length(""),
keystroke_callback("keystroke_callback"),
prevalidate_callback("prevalidate_callback"),
background_image("background_image"),
@@ -108,7 +108,8 @@ LLLineEditor::Params::Params()
LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
: LLUICtrl(p),
- mMaxLengthBytes(p.max_length_bytes),
+ mMaxLengthBytes(p.max_length.bytes),
+ mMaxLengthChars(p.max_length.chars),
mCursorPos( 0 ),
mScrollHPos( 0 ),
mTextPadLeft(p.text_pad_left),
@@ -313,6 +314,12 @@ void LLLineEditor::setMaxTextLength(S32 max_text_length)
mMaxLengthBytes = max_len;
}
+void LLLineEditor::setMaxTextChars(S32 max_text_chars)
+{
+ S32 max_chars = llmax(0, max_text_chars);
+ mMaxLengthChars = max_chars;
+}
+
void LLLineEditor::getTextPadding(S32 *left, S32 *right)
{
*left = mTextPadLeft;
@@ -358,6 +365,16 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
}
mText.assign(truncated_utf8);
+ if (mMaxLengthChars)
+ {
+ LLWString truncated_wstring = utf8str_to_wstring(truncated_utf8);
+ if (truncated_wstring.size() > (U32)mMaxLengthChars)
+ {
+ truncated_wstring = truncated_wstring.substr(0, mMaxLengthChars);
+ }
+ mText.assign(wstring_to_utf8str(truncated_wstring));
+ }
+
if (all_selected)
{
// ...keep whole thing selected
@@ -798,6 +815,7 @@ void LLLineEditor::addChar(const llwchar uni_char)
}
S32 cur_bytes = mText.getString().size();
+
S32 new_bytes = wchar_utf8_length(new_c);
BOOL allow_char = TRUE;
@@ -807,6 +825,14 @@ void LLLineEditor::addChar(const llwchar uni_char)
{
allow_char = FALSE;
}
+ else if (mMaxLengthChars)
+ {
+ S32 wide_chars = mText.getWString().size();
+ if ((wide_chars + 1) > mMaxLengthChars)
+ {
+ allow_char = FALSE;
+ }
+ }
if (allow_char)
{
@@ -1107,7 +1133,19 @@ void LLLineEditor::pasteHelper(bool is_primary)
clean_string = clean_string.substr(0, wchars_that_fit);
LLUI::reportBadKeystroke();
}
-
+
+ if (mMaxLengthChars)
+ {
+ U32 available_chars = mMaxLengthChars - mText.getWString().size();
+
+ if (available_chars < clean_string.size())
+ {
+ clean_string = clean_string.substr(0, available_chars);
+ }
+
+ LLUI::reportBadKeystroke();
+ }
+
mText.insert(getCursor(), clean_string);
setCursor( getCursor() + (S32)clean_string.length() );
deselect();
@@ -1271,7 +1309,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
if( mCurrentHistoryLine > mLineHistory.begin() )
{
mText.assign( *(--mCurrentHistoryLine) );
- setCursor(llmin((S32)mText.length(), getCursor()));
+ setCursorToEnd();
}
else
{
@@ -1288,7 +1326,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 )
{
mText.assign( *(++mCurrentHistoryLine) );
- setCursor(llmin((S32)mText.length(), getCursor()));
+ setCursorToEnd();
}
else
{
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 76d0187712..a1aa6b71c6 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -59,11 +59,19 @@ public:
typedef boost::function<void (LLLineEditor* caller)> keystroke_callback_t;
+ struct MaxLength : public LLInitParam::Choice<MaxLength>
+ {
+ Alternative<S32> bytes, chars;
+
+ MaxLength() : bytes("max_length_bytes", 254),
+ chars("max_length_chars", 0)
+ {}
+ };
+
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<std::string> default_text;
- Optional<S32> max_length_bytes;
-
+ Optional<MaxLength> max_length;
Optional<keystroke_callback_t> keystroke_callback;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
@@ -214,6 +222,7 @@ public:
void setKeystrokeCallback(callback_t callback, void* user_data);
void setMaxTextLength(S32 max_text_length);
+ void setMaxTextChars(S32 max_text_chars);
// Manipulate left and right padding for text
void getTextPadding(S32 *left, S32 *right);
void setTextPadding(S32 left, S32 right);
@@ -277,6 +286,7 @@ protected:
LLViewBorder* mBorder;
const LLFontGL* mGLFont;
S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes
+ S32 mMaxLengthChars; // Maximum number of characters in the string
S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
S32 mScrollHPos; // Horizontal offset from the start of mText. Used for scrolling.
LLFrameTimer mScrollTimer;
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index 1f6fa12969..d4e6091ee0 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -101,8 +101,8 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
setMouseUpCallback(initCommitCallback(p.mouse_up_callback));
}
- for (LLInitParam::ParamIterator<SliderParams>::const_iterator it = p.sliders().begin();
- it != p.sliders().end();
+ for (LLInitParam::ParamIterator<SliderParams>::const_iterator it = p.sliders.begin();
+ it != p.sliders.end();
++it)
{
if (it->name.isProvided())
diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp
index bd65625f53..91e5b6b9de 100644
--- a/indra/llui/llmultisliderctrl.cpp
+++ b/indra/llui/llmultisliderctrl.cpp
@@ -130,7 +130,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
params.name("MultiSliderCtrl Editor");
params.rect(text_rect);
params.font(p.font);
- params.max_length_bytes(MAX_STRING_LENGTH);
+ params.max_length.bytes(MAX_STRING_LENGTH);
params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
params.prevalidate_callback(&LLTextValidate::validateFloat);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 99d540a9de..dd6c632d10 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -27,8 +27,11 @@
#include "linden_common.h"
#include "llnotifications.h"
+#include "llnotificationtemplate.h"
+#include "llavatarnamecache.h"
#include "llinstantmessage.h"
+#include "llcachename.h"
#include "llxmlnode.h"
#include "lluictrl.h"
#include "lluictrlfactory.h"
@@ -37,6 +40,8 @@
#include "lltrans.h"
#include "llnotificationslistener.h"
#include "llstring.h"
+#include "llsdparam.h"
+#include "llsdutil.h"
#include <algorithm>
#include <boost/regex.hpp>
@@ -44,6 +49,58 @@
const std::string NOTIFICATION_PERSIST_VERSION = "0.93";
+void NotificationPriorityValues::declareValues()
+{
+ declare("low", NOTIFICATION_PRIORITY_LOW);
+ declare("normal", NOTIFICATION_PRIORITY_NORMAL);
+ declare("high", NOTIFICATION_PRIORITY_HIGH);
+ declare("critical", NOTIFICATION_PRIORITY_CRITICAL);
+}
+
+LLNotificationForm::FormElementBase::FormElementBase()
+: name("name")
+{}
+
+LLNotificationForm::FormIgnore::FormIgnore()
+: text("text"),
+ control("control"),
+ invert_control("invert_control", true),
+ save_option("save_option", false)
+{}
+
+LLNotificationForm::FormButton::FormButton()
+: index("index"),
+ text("text"),
+ ignore("ignore"),
+ is_default("default"),
+ type("type")
+{
+ // set type here so it gets serialized
+ type = "button";
+}
+
+LLNotificationForm::FormInput::FormInput()
+: type("type"),
+ max_length_chars("max_length_chars"),
+ width("width", 0),
+ value("value")
+{}
+
+LLNotificationForm::FormElement::FormElement()
+: button("button"),
+ input("input")
+{}
+
+LLNotificationForm::FormElements::FormElements()
+: elements("")
+{}
+
+LLNotificationForm::Params::Params()
+: name("name"),
+ ignore("ignore"),
+ form_elements("")
+{}
+
// Local channel for persistent notifications
// Stores only persistent notifications.
// Class users can use connectChanged() to process persistent notifications
@@ -88,12 +145,7 @@ bool filterIgnoredNotifications(LLNotificationPtr notification)
LLNotificationFormPtr form = notification->getForm();
// Check to see if the user wants to ignore this alert
- if (form->getIgnoreType() != LLNotificationForm::IGNORE_NO)
- {
- return LLUI::sSettingGroups["ignores"]->getBOOL(notification->getName());
- }
-
- return true;
+ return !notification->getForm()->getIgnored();
}
bool handleIgnoredNotification(const LLSD& payload)
@@ -135,63 +187,68 @@ namespace LLNotificationFilters
};
LLNotificationForm::LLNotificationForm()
-: mFormData(LLSD::emptyArray()),
- mIgnore(IGNORE_NO)
+: mIgnore(IGNORE_NO)
{
}
-LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node)
-: mFormData(LLSD::emptyArray()),
- mIgnore(IGNORE_NO)
+LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p)
+: mIgnore(IGNORE_NO),
+ mInvertSetting(true) // ignore settings by default mean true=show, false=ignore
{
- if (!xml_node->hasName("form"))
- {
- llwarns << "Bad xml node for form: " << xml_node->getName() << llendl;
- }
- LLXMLNodePtr child = xml_node->getFirstChild();
- while(child)
+ if (p.ignore.isProvided())
{
- child = LLNotifications::instance().checkForXMLTemplate(child);
+ mIgnoreMsg = p.ignore.text;
- LLSD item_entry;
- std::string element_name = child->getName()->mString;
+ if (!p.ignore.save_option)
+ {
+ mIgnore = IGNORE_WITH_DEFAULT_RESPONSE;
+ }
+ else
+ {
+ // remember last option chosen by user and automatically respond with that in the future
+ mIgnore = IGNORE_WITH_LAST_RESPONSE;
+ LLUI::sSettingGroups["ignores"]->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name));
+ }
- if (element_name == "ignore" )
+ BOOL show_notification = TRUE;
+ if (p.ignore.control.isProvided())
{
- bool save_option = false;
- child->getAttribute_bool("save_option", save_option);
- if (!save_option)
- {
- mIgnore = IGNORE_WITH_DEFAULT_RESPONSE;
- }
- else
- {
- // remember last option chosen by user and automatically respond with that in the future
- mIgnore = IGNORE_WITH_LAST_RESPONSE;
- LLUI::sSettingGroups["ignores"]->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name));
- }
- child->getAttributeString("text", mIgnoreMsg);
- BOOL show_notification = TRUE;
- LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Ignore notification with this name", TRUE);
+ mIgnoreSetting = LLUI::sSettingGroups["config"]->getControl(p.ignore.control);
+ mInvertSetting = p.ignore.invert_control;
}
else
{
- // flatten xml form entry into single LLSD map with type==name
- item_entry["type"] = element_name;
- const LLXMLAttribList::iterator attrib_end = child->mAttributes.end();
- for(LLXMLAttribList::iterator attrib_it = child->mAttributes.begin();
- attrib_it != attrib_end;
- ++attrib_it)
- {
- item_entry[std::string(attrib_it->second->getName()->mString)] = attrib_it->second->getValue();
- }
- item_entry["value"] = child->getTextContents();
- mFormData.append(item_entry);
+ LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Ignore notification with this name", TRUE);
+ mIgnoreSetting = LLUI::sSettingGroups["ignores"]->getControl(name);
}
+ }
+
+ LLParamSDParser parser;
+ parser.writeSD(mFormData, p.form_elements);
- child = child->getNextSibling();
+ mFormData = mFormData[""];
+ if (!mFormData.isArray())
+ {
+ // change existing contents to a one element array
+ LLSD new_llsd_array = LLSD::emptyArray();
+ new_llsd_array.append(mFormData);
+ mFormData = new_llsd_array;
}
+
+ for (LLSD::array_iterator it = mFormData.beginArray(), end_it = mFormData.endArray();
+ it != end_it;
+ ++it)
+ {
+ // lift contents of form element up a level, since element type is already encoded in "type" param
+ if (it->isMap() && it->beginMap() != it->endMap())
+ {
+ *it = it->beginMap()->second;
+ }
+ }
+
+ LL_DEBUGS("Notifications") << name << LL_ENDL;
+ LL_DEBUGS("Notifications") << ll_pretty_print_sd(mFormData) << LL_ENDL;
}
LLNotificationForm::LLNotificationForm(const LLSD& sd)
@@ -293,16 +350,64 @@ std::string LLNotificationForm::getDefaultOption()
return "";
}
-LLNotificationTemplate::LLNotificationTemplate() :
- mExpireSeconds(0),
- mExpireOption(-1),
- mURLOption(-1),
- mURLOpenExternally(-1),
- mPersist(false),
- mUnique(false),
- mPriority(NOTIFICATION_PRIORITY_NORMAL)
+LLControlVariablePtr LLNotificationForm::getIgnoreSetting()
+{
+ return mIgnoreSetting;
+}
+
+bool LLNotificationForm::getIgnored()
{
- mForm = LLNotificationFormPtr(new LLNotificationForm());
+ bool ignored = false;
+ if (mIgnore != LLNotificationForm::IGNORE_NO
+ && mIgnoreSetting)
+ {
+ ignored = mIgnoreSetting->getValue().asBoolean();
+ if (mInvertSetting) ignored = !ignored;
+ }
+
+ return ignored;
+}
+
+void LLNotificationForm::setIgnored(bool ignored)
+{
+ if (mIgnoreSetting)
+ {
+ if (mInvertSetting) ignored = !ignored;
+ mIgnoreSetting->setValue(ignored);
+ }
+}
+
+LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Params& p)
+: mName(p.name),
+ mType(p.type),
+ mMessage(p.value),
+ mLabel(p.label),
+ mIcon(p.icon),
+ mURL(p.url.value),
+ mExpireSeconds(p.duration),
+ mExpireOption(p.expire_option),
+ mURLOption(p.url.option),
+ mURLTarget(p.url.target),
+ mUnique(p.unique.isProvided()),
+ mPriority(p.priority),
+ mPersist(p.persist),
+ mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name())
+{
+ if (p.sound.isProvided()
+ && LLUI::sSettingGroups["config"]->controlExists(p.sound))
+ {
+ mSoundEffect = LLUUID(LLUI::sSettingGroups["config"]->getString(p.sound));
+ }
+
+ for(LLInitParam::ParamIterator<LLNotificationTemplate::UniquenessContext>::const_iterator it = p.unique.contexts.begin(),
+ end_it = p.unique.contexts.end();
+ it != end_it;
+ ++it)
+ {
+ mUniqueContext.push_back(it->key);
+ }
+
+ mForm = LLNotificationFormPtr(new LLNotificationForm(p.name, p.form_ref.form));
}
LLNotification::LLNotification(const LLNotification::Params& p) :
@@ -499,7 +604,7 @@ void LLNotification::respond(const LLSD& response)
{
mResponder->handleRespond(asLLSD(), response);
}
- else
+ else if (!mResponseFunctorName.empty())
{
// look up the functor
LLNotificationFunctorRegistry::ResponseFunctor functor =
@@ -507,6 +612,11 @@ void LLNotification::respond(const LLSD& response)
// and then call it
functor(asLLSD(), response);
}
+ else
+ {
+ // no registered responder
+ return;
+ }
if (mTemporaryResponder && !isReusable())
{
@@ -517,8 +627,7 @@ void LLNotification::respond(const LLSD& response)
if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
{
- BOOL show_notification = mIgnored ? FALSE : TRUE;
- LLUI::sSettingGroups["ignores"]->setBOOL(getName(), show_notification);
+ mForm->setIgnored(mIgnored);
if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
{
LLUI::sSettingGroups["ignores"]->setLLSD("Default" + getName(), response);
@@ -528,6 +637,49 @@ void LLNotification::respond(const LLSD& response)
update();
}
+void LLNotification::respondWithDefault()
+{
+ respond(getResponseTemplate(WITH_DEFAULT_BUTTON));
+}
+
+
+const std::string& LLNotification::getName() const
+{
+ return mTemplatep->mName;
+}
+
+const std::string& LLNotification::getIcon() const
+{
+ return mTemplatep->mIcon;
+}
+
+
+bool LLNotification::isPersistent() const
+{
+ return mTemplatep->mPersist;
+}
+
+std::string LLNotification::getType() const
+{
+ return (mTemplatep ? mTemplatep->mType : "");
+}
+
+S32 LLNotification::getURLOption() const
+{
+ return (mTemplatep ? mTemplatep->mURLOption : -1);
+}
+
+S32 LLNotification::getURLOpenExternally() const
+{
+ return(mTemplatep? mTemplatep->mURLTarget == "_external": -1);
+}
+
+bool LLNotification::hasUniquenessConstraints() const
+{
+ return (mTemplatep ? mTemplatep->mUnique : false);
+}
+
+
void LLNotification::setIgnored(bool ignore)
{
mIgnored = ignore;
@@ -607,6 +759,8 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele
// apply substitution to form labels
mForm->formatElements(mSubstitutions);
+ mIgnored = mForm->getIgnored();
+
LLDate rightnow = LLDate::now();
if (mTemplatep->mExpireSeconds)
{
@@ -910,12 +1064,12 @@ std::string LLNotificationChannel::summarize()
// LLNotifications implementation
// ---
LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything,
- LLNotificationComparators::orderByUUID()),
- mIgnoreAllNotifications(false)
+ LLNotificationComparators::orderByUUID()),
+ mIgnoreAllNotifications(false)
{
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
-
- mListener.reset(new LLNotificationsListener(*this));
+
+ mListener.reset(new LLNotificationsListener(*this));
}
@@ -1095,11 +1249,6 @@ bool LLNotifications::templateExists(const std::string& name)
return (mTemplates.count(name) != 0);
}
-void LLNotifications::clearTemplates()
-{
- mTemplates.clear();
-}
-
void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option)
{
LLNotificationPtr temp_notify(new LLNotification(params));
@@ -1162,190 +1311,88 @@ void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements)
}
}
-// private to this file
-// returns true if the template request was invalid and there's nothing else we
-// can do with this node, false if you should keep processing (it may have
-// replaced the contents of the node referred to)
-LLXMLNodePtr LLNotifications::checkForXMLTemplate(LLXMLNodePtr item)
+void replaceFormText(LLNotificationForm::Params& form, const std::string& pattern, const std::string& replace)
{
- if (item->hasName("usetemplate"))
+ if (form.ignore.isProvided() && form.ignore.text() == pattern)
+ {
+ form.ignore.text = replace;
+ }
+ for (LLInitParam::ParamIterator<LLNotificationForm::FormElement>::iterator it = form.form_elements.elements.begin(),
+ end_it = form.form_elements.elements.end();
+ it != end_it;
+ ++it)
{
- std::string replacementName;
- if (item->getAttributeString("name", replacementName))
+ if (it->button.isChosen() && it->button.text() == pattern)
{
- StringMap replacements;
- for (LLXMLAttribList::const_iterator it=item->mAttributes.begin();
- it != item->mAttributes.end(); ++it)
- {
- replacements[it->second->getName()->mString] = it->second->getValue();
- }
- if (mXmlTemplates.count(replacementName))
- {
- item=LLXMLNode::replaceNode(item, mXmlTemplates[replacementName]);
-
- // walk the nodes looking for $(substitution) here and replace
- replaceSubstitutionStrings(item, replacements);
- }
- else
- {
- llwarns << "XML template lookup failure on '" << replacementName << "' " << llendl;
- }
+ it->button.text = replace;
}
}
- return item;
}
bool LLNotifications::loadTemplates()
{
const std::string xml_filename = "notifications.xml";
+ std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), xml_filename);
+
LLXMLNodePtr root;
-
BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
if (!success || root.isNull() || !root->hasName( "notifications" ))
{
- llerrs << "Problem reading UI Notifications file: " << xml_filename << llendl;
+ llerrs << "Problem reading UI Notifications file: " << full_filename << llendl;
return false;
}
-
- clearTemplates();
-
- for (LLXMLNodePtr item = root->getFirstChild();
- item.notNull(); item = item->getNextSibling())
- {
- // we do this FIRST so that item can be changed if we
- // encounter a usetemplate -- we just replace the
- // current xml node and keep processing
- item = checkForXMLTemplate(item);
-
- if (item->hasName("global"))
- {
- std::string global_name;
- if (item->getAttributeString("name", global_name))
- {
- mGlobalStrings[global_name] = item->getTextContents();
- }
- continue;
- }
-
- if (item->hasName("template"))
- {
- // store an xml template; templates must have a single node (can contain
- // other nodes)
- std::string name;
- item->getAttributeString("name", name);
- LLXMLNodePtr ptr = item->getFirstChild();
- mXmlTemplates[name] = ptr;
- continue;
- }
-
- if (!item->hasName("notification"))
- {
- llwarns << "Unexpected entity " << item->getName()->mString <<
- " found in " << xml_filename << llendl;
- continue;
- }
-
- // now we know we have a notification entry, so let's build it
- LLNotificationTemplatePtr pTemplate(new LLNotificationTemplate());
- if (!item->getAttributeString("name", pTemplate->mName))
- {
- llwarns << "Unable to parse notification with no name" << llendl;
- continue;
- }
-
- //llinfos << "Parsing " << pTemplate->mName << llendl;
-
- pTemplate->mMessage = item->getTextContents();
- pTemplate->mDefaultFunctor = pTemplate->mName;
- item->getAttributeString("type", pTemplate->mType);
- item->getAttributeString("icon", pTemplate->mIcon);
- item->getAttributeString("label", pTemplate->mLabel);
- item->getAttributeU32("duration", pTemplate->mExpireSeconds);
- item->getAttributeU32("expireOption", pTemplate->mExpireOption);
-
- std::string priority;
- item->getAttributeString("priority", priority);
- pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL;
- if (!priority.empty())
- {
- if (priority == "low") pTemplate->mPriority = NOTIFICATION_PRIORITY_LOW;
- if (priority == "normal") pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL;
- if (priority == "high") pTemplate->mPriority = NOTIFICATION_PRIORITY_HIGH;
- if (priority == "critical") pTemplate->mPriority = NOTIFICATION_PRIORITY_CRITICAL;
- }
-
- item->getAttributeString("functor", pTemplate->mDefaultFunctor);
-
- BOOL persist = false;
- item->getAttributeBOOL("persist", persist);
- pTemplate->mPersist = persist;
-
- std::string sound;
- item->getAttributeString("sound", sound);
- if (!sound.empty())
+ LLNotificationTemplate::Notifications params;
+ LLXUIParser parser;
+ parser.readXUI(root, params, full_filename);
+
+ mTemplates.clear();
+
+ for(LLInitParam::ParamIterator<LLNotificationTemplate::GlobalString>::const_iterator it = params.strings.begin(), end_it = params.strings.end();
+ it != end_it;
+ ++it)
+ {
+ mGlobalStrings[it->name] = it->value;
+ }
+
+ std::map<std::string, LLNotificationForm::Params> form_templates;
+
+ for(LLInitParam::ParamIterator<LLNotificationTemplate::Template>::const_iterator it = params.templates.begin(), end_it = params.templates.end();
+ it != end_it;
+ ++it)
+ {
+ form_templates[it->name] = it->form;
+ }
+
+ for(LLInitParam::ParamIterator<LLNotificationTemplate::Params>::iterator it = params.notifications.begin(), end_it = params.notifications.end();
+ it != end_it;
+ ++it)
+ {
+ if (it->form_ref.form_template.isChosen())
{
- // test for bad sound effect name / missing effect
- if (LLUI::sSettingGroups["config"]->controlExists(sound))
+ // replace form contents from template
+ it->form_ref.form = form_templates[it->form_ref.form_template.name];
+ if(it->form_ref.form_template.yes_text.isProvided())
{
- pTemplate->mSoundEffect =
- LLUUID(LLUI::sSettingGroups["config"]->getString(sound));
+ replaceFormText(it->form_ref.form, "$yestext", it->form_ref.form_template.yes_text);
}
- else
+ if(it->form_ref.form_template.no_text.isProvided())
{
- llwarns << "Unknown sound effect control name " << sound
- << llendl;
+ replaceFormText(it->form_ref.form, "$notext", it->form_ref.form_template.no_text);
}
- }
-
- for (LLXMLNodePtr child = item->getFirstChild();
- !child.isNull(); child = child->getNextSibling())
- {
- child = checkForXMLTemplate(child);
-
- // <url>
- if (child->hasName("url"))
+ if(it->form_ref.form_template.cancel_text.isProvided())
{
- pTemplate->mURL = child->getTextContents();
- child->getAttributeU32("option", pTemplate->mURLOption);
- child->getAttributeU32("openexternally", pTemplate->mURLOpenExternally);
+ replaceFormText(it->form_ref.form, "$canceltext", it->form_ref.form_template.cancel_text);
}
-
- if (child->hasName("unique"))
- {
- pTemplate->mUnique = true;
- for (LLXMLNodePtr formitem = child->getFirstChild();
- !formitem.isNull(); formitem = formitem->getNextSibling())
- {
- if (formitem->hasName("context"))
- {
- std::string key;
- formitem->getAttributeString("key", key);
- pTemplate->mUniqueContext.push_back(key);
- //llwarns << "adding " << key << " to unique context" << llendl;
- }
- else
- {
- llwarns << "'unique' has unrecognized subelement "
- << formitem->getName()->mString << llendl;
- }
- }
- }
-
- // <form>
- if (child->hasName("form"))
+ if(it->form_ref.form_template.ignore_text.isProvided())
{
- pTemplate->mForm = LLNotificationFormPtr(new LLNotificationForm(pTemplate->mName, child));
+ replaceFormText(it->form_ref.form, "$ignoretext", it->form_ref.form_template.ignore_text);
}
}
- addTemplate(pTemplate->mName, pTemplate);
+ addTemplate(it->name, LLNotificationTemplatePtr(new LLNotificationTemplate(*it)));
}
-
- //std::ostringstream ostream;
- //root->writeToOstream(ostream, "\n ");
- //llwarns << ostream.str() << llendl;
-
+
return true;
}
@@ -1396,6 +1443,8 @@ LLNotificationPtr LLNotifications::add(const LLNotification::Params& p)
void LLNotifications::add(const LLNotificationPtr pNotif)
{
+ if (pNotif == NULL) return;
+
// first see if we already have it -- if so, that's a problem
LLNotificationSet::iterator it=mItems.find(pNotif);
if (it != mItems.end())
@@ -1408,6 +1457,8 @@ void LLNotifications::add(const LLNotificationPtr pNotif)
void LLNotifications::cancel(LLNotificationPtr pNotif)
{
+ if (pNotif == NULL) return;
+
LLNotificationSet::iterator it=mItems.find(pNotif);
if (it == mItems.end())
{
@@ -1417,6 +1468,30 @@ void LLNotifications::cancel(LLNotificationPtr pNotif)
updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);
}
+void LLNotifications::cancelByName(const std::string& name)
+{
+ std::vector<LLNotificationPtr> notifs_to_cancel;
+ for (LLNotificationSet::iterator it=mItems.begin(), end_it = mItems.end();
+ it != end_it;
+ ++it)
+ {
+ LLNotificationPtr pNotif = *it;
+ if (pNotif->getName() == name)
+ {
+ notifs_to_cancel.push_back(pNotif);
+ }
+ }
+
+ for (std::vector<LLNotificationPtr>::iterator it = notifs_to_cancel.begin(), end_it = notifs_to_cancel.end();
+ it != end_it;
+ ++it)
+ {
+ LLNotificationPtr pNotif = *it;
+ pNotif->cancel();
+ updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);
+ }
+}
+
void LLNotifications::update(const LLNotificationPtr pNotif)
{
LLNotificationSet::iterator it=mItems.find(pNotif);
@@ -1481,17 +1556,50 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
return s;
}
-void LLPostponedNotification::onCachedNameReceived(const LLUUID& id, const std::string& first,
- const std::string& last, bool is_group)
+//static
+void LLPostponedNotification::lookupName(LLPostponedNotification* thiz,
+ const LLUUID& id,
+ bool is_group)
+{
+ if (is_group)
+ {
+ gCacheName->getGroup(id,
+ boost::bind(&LLPostponedNotification::onGroupNameCache,
+ thiz, _1, _2, _3));
+ }
+ else
+ {
+ LLAvatarNameCache::get(id,
+ boost::bind(&LLPostponedNotification::onAvatarNameCache,
+ thiz, _1, _2));
+ }
+}
+
+void LLPostponedNotification::onGroupNameCache(const LLUUID& id,
+ const std::string& full_name,
+ bool is_group)
{
- mName = first + " " + last;
+ finalizeName(full_name);
+}
- LLStringUtil::trim(mName);
- if (mName.empty())
+void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
+{
+ std::string name = av_name.getCompleteName();
+
+ // from PE merge - we should figure out if this is the right thing to do
+ if (name.empty())
{
- llwarns << "Empty name received for Id: " << id << llendl;
- mName = SYSTEM_FROM;
+ llwarns << "Empty name received for Id: " << agent_id << llendl;
+ name = SYSTEM_FROM;
}
+
+ finalizeName(name);
+}
+
+void LLPostponedNotification::finalizeName(const std::string& name)
+{
+ mName = name;
modifyNotificationParams();
LLNotifications::instance().add(mParams);
cleanup();
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 2cc8803f10..524cff70e8 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -98,9 +98,8 @@
#include "llinitparam.h"
#include "llnotificationslistener.h"
#include "llnotificationptr.h"
-#include "llcachename.h"
-
+class LLAvatarName;
typedef enum e_notification_priority
{
NOTIFICATION_PRIORITY_UNSPECIFIED,
@@ -110,6 +109,11 @@ typedef enum e_notification_priority
NOTIFICATION_PRIORITY_CRITICAL
} ENotificationPriority;
+struct NotificationPriorityValues : public LLInitParam::TypeValuesHelper<ENotificationPriority, NotificationPriorityValues>
+{
+ static void declareValues();
+};
+
class LLNotificationResponderInterface
{
public:
@@ -157,6 +161,68 @@ class LLNotificationForm
LOG_CLASS(LLNotificationForm);
public:
+ struct FormElementBase : public LLInitParam::Block<FormElementBase>
+ {
+ Optional<std::string> name;
+
+ FormElementBase();
+ };
+
+ struct FormIgnore : public LLInitParam::Block<FormIgnore, FormElementBase>
+ {
+ Optional<std::string> text;
+ Optional<bool> save_option;
+ Optional<std::string> control;
+ Optional<bool> invert_control;
+
+ FormIgnore();
+ };
+
+ struct FormButton : public LLInitParam::Block<FormButton, FormElementBase>
+ {
+ Mandatory<S32> index;
+ Mandatory<std::string> text;
+ Optional<std::string> ignore;
+ Optional<bool> is_default;
+
+ Mandatory<std::string> type;
+
+ FormButton();
+ };
+
+ struct FormInput : public LLInitParam::Block<FormInput, FormElementBase>
+ {
+ Mandatory<std::string> type;
+ Optional<S32> width;
+ Optional<S32> max_length_chars;
+
+ Optional<std::string> value;
+ FormInput();
+ };
+
+ struct FormElement : public LLInitParam::Choice<FormElement>
+ {
+ Alternative<FormButton> button;
+ Alternative<FormInput> input;
+
+ FormElement();
+ };
+
+ struct FormElements : public LLInitParam::Block<FormElements>
+ {
+ Multiple<FormElement> elements;
+ FormElements();
+ };
+
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Optional<std::string> name;
+ Optional<FormIgnore> ignore;
+ Optional<FormElements> form_elements;
+
+ Params();
+ };
+
typedef enum e_ignore_type
{
IGNORE_NO,
@@ -167,8 +233,7 @@ public:
LLNotificationForm();
LLNotificationForm(const LLSD& sd);
- LLNotificationForm(const std::string& name,
- const LLPointer<class LLXMLNode> xml_node);
+ LLNotificationForm(const std::string& name, const Params& p);
LLSD asLLSD() const;
@@ -181,92 +246,25 @@ public:
// appends form elements from another form serialized as LLSD
void append(const LLSD& sub_form);
std::string getDefaultOption();
+ LLPointer<class LLControlVariable> getIgnoreSetting();
+ bool getIgnored();
+ void setIgnored(bool ignored);
EIgnoreType getIgnoreType() { return mIgnore; }
std::string getIgnoreMessage() { return mIgnoreMsg; }
private:
- LLSD mFormData;
- EIgnoreType mIgnore;
- std::string mIgnoreMsg;
+ LLSD mFormData;
+ EIgnoreType mIgnore;
+ std::string mIgnoreMsg;
+ LLPointer<class LLControlVariable> mIgnoreSetting;
+ bool mInvertSetting;
};
typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
-// This is the class of object read from the XML file (notifications.xml,
-// from the appropriate local language directory).
-struct LLNotificationTemplate
-{
- LLNotificationTemplate();
- // the name of the notification -- the key used to identify it
- // Ideally, the key should follow variable naming rules
- // (no spaces or punctuation).
- std::string mName;
- // The type of the notification
- // used to control which queue it's stored in
- std::string mType;
- // The text used to display the notification. Replaceable parameters
- // are enclosed in square brackets like this [].
- std::string mMessage;
- // The label for the notification; used for
- // certain classes of notification (those with a window and a window title).
- // Also used when a notification pops up underneath the current one.
- // Replaceable parameters can be used in the label.
- std::string mLabel;
- // The name of the icon image. This should include an extension.
- std::string mIcon;
- // This is the Highlander bit -- "There Can Be Only One"
- // An outstanding notification with this bit set
- // is updated by an incoming notification with the same name,
- // rather than creating a new entry in the queue.
- // (used for things like progress indications, or repeating warnings
- // like "the grid is going down in N minutes")
- bool mUnique;
- // if we want to be unique only if a certain part of the payload is constant
- // specify the field names for the payload. The notification will only be
- // combined if all of the fields named in the context are identical in the
- // new and the old notification; otherwise, the notification will be
- // duplicated. This is to support suppressing duplicate offers from the same
- // sender but still differentiating different offers. Example: Invitation to
- // conference chat.
- std::vector<std::string> mUniqueContext;
- // If this notification expires automatically, this value will be
- // nonzero, and indicates the number of seconds for which the notification
- // will be valid (a teleport offer, for example, might be valid for
- // 300 seconds).
- U32 mExpireSeconds;
- // if the offer expires, one of the options is chosen automatically
- // based on its "value" parameter. This controls which one.
- // If expireSeconds is specified, expireOption should also be specified.
- U32 mExpireOption;
- // if the notification contains a url, it's stored here (and replaced
- // into the message where [_URL] is found)
- std::string mURL;
- // if there's a URL in the message, this controls which option visits
- // that URL. Obsolete this and eliminate the buttons for affected
- // messages when we allow clickable URLs in the UI
- U32 mURLOption;
-
- U32 mURLOpenExternally;
- //This is a flag that tells if the url needs to open externally dispite
- //what the user setting is.
-
- // does this notification persist across sessions? if so, it will be
- // serialized to disk on first receipt and read on startup
- bool mPersist;
- // This is the name of the default functor, if present, to be
- // used for the notification's callback. It is optional, and used only if
- // the notification is constructed without an identified functor.
- std::string mDefaultFunctor;
- // The form data associated with a given notification (buttons, text boxes, etc)
- LLNotificationFormPtr mForm;
- // default priority for notifications of this type
- ENotificationPriority mPriority;
- // UUID of the audio file to be played when this notification arrives
- // this is loaded as a name, but looked up to get the UUID upon template load.
- // If null, it wasn't specified.
- LLUUID mSoundEffect;
-};
+
+struct LLNotificationTemplate;
// we want to keep a map of these by name, and it's best to manage them
// with smart pointers
@@ -302,7 +300,7 @@ public:
// optional
Optional<LLSD> substitutions;
Optional<LLSD> payload;
- Optional<ENotificationPriority> priority;
+ Optional<ENotificationPriority, NotificationPriorityValues> priority;
Optional<LLSD> form_elements;
Optional<LLDate> time_stamp;
Optional<LLNotificationContext*> context;
@@ -445,6 +443,7 @@ public:
LLSD asLLSD();
void respond(const LLSD& sd);
+ void respondWithDefault();
void* getResponder() { return mResponderObj; }
@@ -462,6 +461,13 @@ public:
return mRespondedTo;
}
+ bool isActive() const
+ {
+ return !isRespondedTo()
+ && !isCancelled()
+ && !isExpired();
+ }
+
const LLSD& getResponse() { return mResponse; }
bool isIgnored() const
@@ -469,15 +475,11 @@ public:
return mIgnored;
}
- const std::string& getName() const
- {
- return mTemplatep->mName;
- }
+ const std::string& getName() const;
- bool isPersistent() const
- {
- return mTemplatep->mPersist;
- }
+ const std::string& getIcon() const;
+
+ bool isPersistent() const;
const LLUUID& id() const
{
@@ -499,28 +501,12 @@ public:
return mTimestamp;
}
- std::string getType() const
- {
- return (mTemplatep ? mTemplatep->mType : "");
- }
-
+ std::string getType() const;
std::string getMessage() const;
std::string getLabel() const;
-
std::string getURL() const;
-// {
-// return (mTemplatep ? mTemplatep->mURL : "");
-// }
-
- S32 getURLOption() const
- {
- return (mTemplatep ? mTemplatep->mURLOption : -1);
- }
-
- S32 getURLOpenExternally() const
- {
- return(mTemplatep? mTemplatep->mURLOpenExternally : -1);
- }
+ S32 getURLOption() const;
+ S32 getURLOpenExternally() const;
const LLNotificationFormPtr getForm();
@@ -590,7 +576,7 @@ public:
std::string summarize() const;
- bool hasUniquenessConstraints() const { return (mTemplatep ? mTemplatep->mUnique : false);}
+ bool hasUniquenessConstraints() const;
virtual ~LLNotification() {}
};
@@ -872,7 +858,6 @@ public:
// load notification descriptions from file;
// OK to call more than once because it will reload
bool loadTemplates();
- LLPointer<class LLXMLNode> checkForXMLTemplate(LLPointer<class LLXMLNode> item);
// Add a simple notification (from XUI)
void addFromCallback(const LLSD& name);
@@ -894,6 +879,7 @@ public:
void add(const LLNotificationPtr pNotif);
void cancel(LLNotificationPtr pNotif);
+ void cancelByName(const std::string& name);
void update(const LLNotificationPtr pNotif);
LLNotificationPtr find(LLUUID uuid);
@@ -917,8 +903,6 @@ public:
// test for existence
bool templateExists(const std::string& name);
- // useful if you're reloading the file
- void clearTemplates(); // erase all templates
void forceResponse(const LLNotification::Params& params, S32 option);
@@ -956,9 +940,6 @@ private:
std::string mFileName;
- typedef std::map<std::string, LLPointer<class LLXMLNode> > XMLTemplateMap;
- XMLTemplateMap mXmlTemplates;
-
LLNotificationMap mUniqueNotifications;
typedef std::map<std::string, std::string> GlobalStringMap;
@@ -994,17 +975,20 @@ public:
{
// upcast T to the base type to restrict T derivation from LLPostponedNotification
LLPostponedNotification* thiz = new T();
-
thiz->mParams = params;
- gCacheName->get(id, is_group, boost::bind(
- &LLPostponedNotification::onCachedNameReceived, thiz, _1, _2,
- _3, _4));
+ // Avoid header file dependency on llcachename.h
+ lookupName(thiz, id, is_group);
}
private:
- void onCachedNameReceived(const LLUUID& id, const std::string& first,
- const std::string& last, bool is_group);
+ static void lookupName(LLPostponedNotification* thiz, const LLUUID& id, bool is_group);
+ // only used for groups
+ void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
+ // only used for avatars
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
+ // used for both group and avatar names
+ void finalizeName(const std::string& name);
void cleanup()
{
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
index 44a90398fd..3bbeb3a778 100644
--- a/indra/llui/llnotificationslistener.cpp
+++ b/indra/llui/llnotificationslistener.cpp
@@ -29,6 +29,7 @@
#include "linden_common.h"
#include "llnotificationslistener.h"
#include "llnotifications.h"
+#include "llnotificationtemplate.h"
#include "llsd.h"
#include "llui.h"
@@ -182,7 +183,11 @@ void LLNotificationsListener::ignore(const LLSD& params) const
if (params["name"].isDefined())
{
// ["name"] was passed: ignore just that notification
- LLUI::sSettingGroups["ignores"]->setBOOL(params["name"], ignore);
+ LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]);
+ if (templatep)
+ {
+ templatep->mForm->setIgnored(ignore);
+ }
}
else
{
diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h
new file mode 100644
index 0000000000..6bc0d2aaff
--- /dev/null
+++ b/indra/llui/llnotificationtemplate.h
@@ -0,0 +1,282 @@
+/**
+* @file llnotificationtemplate.h
+* @brief Description of notification contents
+* @author Q (with assistance from Richard and Coco)
+*
+* $LicenseInfo:firstyear=2008&license=viewerlgpl$
+* Second Life Viewer Source Code
+* 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.
+*
+* 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.
+*
+* 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$
+*/
+
+#ifndef LL_LLNOTIFICATION_TEMPLATE_H
+#define LL_LLNOTIFICATION_TEMPLATE_H
+
+//#include <string>
+//#include <list>
+//#include <vector>
+//#include <map>
+//#include <set>
+//#include <iomanip>
+//#include <sstream>
+//
+//#include <boost/utility.hpp>
+//#include <boost/shared_ptr.hpp>
+//#include <boost/enable_shared_from_this.hpp>
+//#include <boost/type_traits.hpp>
+//
+//// we want to minimize external dependencies, but this one is important
+//#include "llsd.h"
+//
+//// and we need this to manage the notification callbacks
+//#include "llevents.h"
+//#include "llfunctorregistry.h"
+//#include "llpointer.h"
+#include "llinitparam.h"
+//#include "llnotificationslistener.h"
+//#include "llnotificationptr.h"
+//#include "llcachename.h"
+#include "llnotifications.h"
+
+
+typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
+
+// This is the class of object read from the XML file (notifications.xml,
+// from the appropriate local language directory).
+struct LLNotificationTemplate
+{
+ struct GlobalString : public LLInitParam::Block<GlobalString>
+ {
+ Mandatory<std::string> name,
+ value;
+
+ GlobalString()
+ : name("name"),
+ value("value")
+ {}
+ };
+
+ struct UniquenessContext : public LLInitParam::Block<UniquenessContext>
+ {
+ Mandatory<std::string> key;
+
+ UniquenessContext()
+ : key("key")
+ {}
+
+ };
+
+ struct UniquenessConstraint : public LLInitParam::Block<UniquenessConstraint>
+ {
+ private:
+ // this idiom allows
+ // <notification unique="true">
+ // as well as
+ // <notification> <unique> <context key=""/> </unique>...
+ Optional<bool> dummy_val;
+ public:
+ Multiple<UniquenessContext> contexts;
+
+ UniquenessConstraint()
+ : contexts("context"),
+ dummy_val("")
+ {}
+ };
+
+ // Templates are used to define common form types, such as OK/Cancel dialogs, etc.
+
+ struct Template : public LLInitParam::Block<Template>
+ {
+ Mandatory<std::string> name;
+ Mandatory<LLNotificationForm::Params> form;
+
+ Template()
+ : name("name"),
+ form("form")
+ {}
+ };
+
+ // Reference a template to use its form elements
+ struct TemplateRef : public LLInitParam::Block<TemplateRef>
+ {
+ Mandatory<std::string> name;
+ Optional<std::string> yes_text,
+ no_text,
+ cancel_text,
+ ignore_text;
+
+ TemplateRef()
+ : name("name"),
+ yes_text("yestext"),
+ no_text("notext"),
+ cancel_text("canceltext"),
+ ignore_text("ignoretext")
+ {}
+ };
+
+ struct URL : public LLInitParam::Block<URL>
+ {
+ Mandatory<S32> option;
+ Mandatory<std::string> value;
+ Optional<std::string> target;
+ Ignored name;
+
+ URL()
+ : option("option", -1),
+ value("value"),
+ target("target", "_blank"),
+ name("name")
+ {}
+ };
+
+ struct FormRef : public LLInitParam::Choice<FormRef>
+ {
+ Alternative<LLNotificationForm::Params> form;
+ Alternative<TemplateRef> form_template;
+
+ FormRef()
+ : form("form"),
+ form_template("usetemplate")
+ {}
+ };
+
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Mandatory<std::string> name;
+ Optional<bool> persist;
+ Optional<std::string> functor,
+ icon,
+ label,
+ sound,
+ type,
+ value;
+ Optional<U32> duration;
+ Optional<S32> expire_option;
+ Optional<URL> url;
+ Optional<UniquenessConstraint> unique;
+ Optional<FormRef> form_ref;
+ Optional<ENotificationPriority,
+ NotificationPriorityValues> priority;
+
+
+ Params()
+ : name("name"),
+ persist("persist", false),
+ functor("functor"),
+ icon("icon"),
+ label("label"),
+ priority("priority"),
+ sound("sound"),
+ type("type"),
+ value("value"),
+ duration("duration"),
+ expire_option("expireOption", -1),
+ url("url"),
+ unique("unique"),
+ form_ref("")
+ {}
+
+ };
+
+ struct Notifications : public LLInitParam::Block<Notifications>
+ {
+ Multiple<GlobalString> strings;
+ Multiple<Template> templates;
+ Multiple<Params> notifications;
+
+ Notifications()
+ : strings("global"),
+ notifications("notification"),
+ templates("template")
+ {}
+ };
+
+ LLNotificationTemplate(const Params& p);
+ // the name of the notification -- the key used to identify it
+ // Ideally, the key should follow variable naming rules
+ // (no spaces or punctuation).
+ std::string mName;
+ // The type of the notification
+ // used to control which queue it's stored in
+ std::string mType;
+ // The text used to display the notification. Replaceable parameters
+ // are enclosed in square brackets like this [].
+ std::string mMessage;
+ // The label for the notification; used for
+ // certain classes of notification (those with a window and a window title).
+ // Also used when a notification pops up underneath the current one.
+ // Replaceable parameters can be used in the label.
+ std::string mLabel;
+ // The name of the icon image. This should include an extension.
+ std::string mIcon;
+ // This is the Highlander bit -- "There Can Be Only One"
+ // An outstanding notification with this bit set
+ // is updated by an incoming notification with the same name,
+ // rather than creating a new entry in the queue.
+ // (used for things like progress indications, or repeating warnings
+ // like "the grid is going down in N minutes")
+ bool mUnique;
+ // if we want to be unique only if a certain part of the payload is constant
+ // specify the field names for the payload. The notification will only be
+ // combined if all of the fields named in the context are identical in the
+ // new and the old notification; otherwise, the notification will be
+ // duplicated. This is to support suppressing duplicate offers from the same
+ // sender but still differentiating different offers. Example: Invitation to
+ // conference chat.
+ std::vector<std::string> mUniqueContext;
+ // If this notification expires automatically, this value will be
+ // nonzero, and indicates the number of seconds for which the notification
+ // will be valid (a teleport offer, for example, might be valid for
+ // 300 seconds).
+ U32 mExpireSeconds;
+ // if the offer expires, one of the options is chosen automatically
+ // based on its "value" parameter. This controls which one.
+ // If expireSeconds is specified, expireOption should also be specified.
+ U32 mExpireOption;
+ // if the notification contains a url, it's stored here (and replaced
+ // into the message where [_URL] is found)
+ std::string mURL;
+ // if there's a URL in the message, this controls which option visits
+ // that URL. Obsolete this and eliminate the buttons for affected
+ // messages when we allow clickable URLs in the UI
+ U32 mURLOption;
+
+ std::string mURLTarget;
+ //This is a flag that tells if the url needs to open externally dispite
+ //what the user setting is.
+
+ // does this notification persist across sessions? if so, it will be
+ // serialized to disk on first receipt and read on startup
+ bool mPersist;
+ // This is the name of the default functor, if present, to be
+ // used for the notification's callback. It is optional, and used only if
+ // the notification is constructed without an identified functor.
+ std::string mDefaultFunctor;
+ // The form data associated with a given notification (buttons, text boxes, etc)
+ LLNotificationFormPtr mForm;
+ // default priority for notifications of this type
+ ENotificationPriority mPriority;
+ // UUID of the audio file to be played when this notification arrives
+ // this is loaded as a name, but looked up to get the UUID upon template load.
+ // If null, it wasn't specified.
+ LLUUID mSoundEffect;
+};
+
+#endif //LL_LLNOTIFICATION_TEMPLATE_H
+
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index b2e08c48c5..c8e56630f1 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -35,6 +35,7 @@
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
+#include "lldir.h"
#include "lltimer.h"
#include "llaccordionctrltab.h"
@@ -52,6 +53,8 @@
#include "lltabcontainer.h"
static LLDefaultChildRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML);
+LLPanel::factory_stack_t LLPanel::sFactoryStack;
+
// Compiler optimization, generate extern template
template class LLPanel* LLView::getChild<class LLPanel>(
@@ -380,8 +383,7 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_
LLPanel* panelp = NULL;
- {
- LLFastTimer timer(FTM_PANEL_CONSTRUCTION);
+ { LLFastTimer _(FTM_PANEL_CONSTRUCTION);
if(!class_attr.empty())
{
@@ -394,7 +396,7 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_
if (!panelp)
{
- panelp = LLUICtrlFactory::getInstance()->createFactoryPanel(name);
+ panelp = createFactoryPanel(name);
llassert(panelp);
if (!panelp)
@@ -407,20 +409,20 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_
// factory panels may have registered their own factory maps
if (!panelp->getFactoryMap().empty())
{
- LLUICtrlFactory::instance().pushFactoryFunctions(&panelp->getFactoryMap());
+ sFactoryStack.push_back(&panelp->getFactoryMap());
}
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
panelp->mCommitCallbackRegistrar.pushScope();
panelp->mEnableCallbackRegistrar.pushScope();
- panelp->initPanelXML(node, parent, output_node);
+ panelp->initPanelXML(node, parent, output_node, LLUICtrlFactory::getDefaultParams<LLPanel>());
panelp->mCommitCallbackRegistrar.popScope();
panelp->mEnableCallbackRegistrar.popScope();
if (!panelp->getFactoryMap().empty())
{
- LLUICtrlFactory::instance().popFactoryFunctions();
+ sFactoryStack.pop_back();
}
return panelp;
@@ -444,8 +446,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
setVisibleCallback(initCommitCallback(p.visible_callback));
}
- for (LLInitParam::ParamIterator<LocalizedString>::const_iterator it = p.strings().begin();
- it != p.strings().end();
+ for (LLInitParam::ParamIterator<LocalizedString>::const_iterator it = p.strings.begin();
+ it != p.strings.end();
++it)
{
mUIStrings[it->name] = it->value;
@@ -487,11 +489,9 @@ static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
static LLFastTimer::DeclareTimer FTM_EXTERNAL_PANEL_LOAD("Load Extern Panel Reference");
static LLFastTimer::DeclareTimer FTM_PANEL_POSTBUILD("Panel PostBuild");
-BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
+BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node, const LLPanel::Params& default_params)
{
- const LLPanel::Params& default_params(LLUICtrlFactory::getDefaultParams<LLPanel>());
Params params(default_params);
-
{
LLFastTimer timer(FTM_PANEL_SETUP);
@@ -505,6 +505,8 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
setXMLFilename(xml_filename);
}
+ LLXUIParser parser;
+
if (!xml_filename.empty())
{
LLUICtrlFactory::instance().pushFileName(xml_filename);
@@ -514,12 +516,11 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
{
//if we are exporting, we want to export the current xml
//not the referenced xml
- LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+ parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
Params output_params(params);
setupParamsForExport(output_params, parent);
output_node->setName(node->getName()->mString);
- LLXUIParser::instance().writeXUI(
- output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, &default_params);
return TRUE;
}
@@ -530,7 +531,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
return FALSE;
}
- LLXUIParser::instance().readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName());
+ parser.readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName());
// add children using dimensions from referenced xml for consistent layout
setShape(params.rect);
@@ -540,15 +541,14 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
}
// ask LLUICtrlFactory for filename, since xml_filename might be empty
- LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+ parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
if (output_node)
{
Params output_params(params);
setupParamsForExport(output_params, parent);
output_node->setName(node->getName()->mString);
- LLXUIParser::instance().writeXUI(
- output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, &default_params);
}
params.from_xui = true;
@@ -959,3 +959,89 @@ boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t::
return mVisibleSignal->connect(cb);
}
+
+static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels");
+
+//-----------------------------------------------------------------------------
+// buildPanel()
+//-----------------------------------------------------------------------------
+BOOL LLPanel::buildFromFile(const std::string& filename, LLXMLNodePtr output_node, const LLPanel::Params& default_params)
+{
+ LLFastTimer timer(FTM_BUILD_PANELS);
+ BOOL didPost = FALSE;
+ LLXMLNodePtr root;
+
+ //if exporting, only load the language being exported,
+ //instead of layering localized version on top of english
+ if (output_node)
+ {
+ if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
+ {
+ llwarns << "Couldn't parse panel from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
+ return didPost;
+ }
+ }
+ else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
+ {
+ llwarns << "Couldn't parse panel from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
+ return didPost;
+ }
+
+ // root must be called panel
+ if( !root->hasName("panel" ) )
+ {
+ llwarns << "Root node should be named panel in : " << filename << llendl;
+ return didPost;
+ }
+
+ lldebugs << "Building panel " << filename << llendl;
+
+ LLUICtrlFactory::instance().pushFileName(filename);
+ {
+ if (!getFactoryMap().empty())
+ {
+ sFactoryStack.push_back(&getFactoryMap());
+ }
+
+ // for local registry callbacks; define in constructor, referenced in XUI or postBuild
+ getCommitCallbackRegistrar().pushScope();
+ getEnableCallbackRegistrar().pushScope();
+
+ didPost = initPanelXML(root, NULL, output_node, default_params);
+
+ getCommitCallbackRegistrar().popScope();
+ getEnableCallbackRegistrar().popScope();
+
+ setXMLFilename(filename);
+
+ if (!getFactoryMap().empty())
+ {
+ sFactoryStack.pop_back();
+ }
+ }
+ LLUICtrlFactory::instance().popFileName();
+ return didPost;
+}
+
+//-----------------------------------------------------------------------------
+// createFactoryPanel()
+//-----------------------------------------------------------------------------
+LLPanel* LLPanel::createFactoryPanel(const std::string& name)
+{
+ std::deque<const LLCallbackMap::map_t*>::iterator itor;
+ for (itor = sFactoryStack.begin(); itor != sFactoryStack.end(); ++itor)
+ {
+ const LLCallbackMap::map_t* factory_map = *itor;
+
+ // Look up this panel's name in the map.
+ LLCallbackMap::map_const_iter_t iter = factory_map->find( name );
+ if (iter != factory_map->end())
+ {
+ // Use the factory to create the panel, instead of using a default LLPanel.
+ LLPanel *ret = (LLPanel*) iter->second.mCallback( iter->second.mData );
+ return ret;
+ }
+ }
+ LLPanel::Params panel_p;
+ return LLUICtrlFactory::create<LLPanel>(panel_p);
+}
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index a7224648c1..c1a1a06f39 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -104,7 +104,10 @@ protected:
LLPanel(const LLPanel::Params& params = getDefaultParams());
public:
-// LLPanel(const std::string& name, const LLRect& rect = LLRect(), BOOL bordered = TRUE);
+ BOOL buildFromFile(const std::string &filename, LLXMLNodePtr output_node = NULL, const LLPanel::Params&default_params = getDefaultParams());
+
+ static LLPanel* createFactoryPanel(const std::string& name);
+
/*virtual*/ ~LLPanel();
// LLView interface
@@ -157,7 +160,7 @@ public:
EnableCallbackRegistry::ScopedRegistrar& getEnableCallbackRegistrar() { return mEnableCallbackRegistrar; }
void initFromParams(const Params& p);
- BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
+ BOOL initPanelXML( LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node, const LLPanel::Params& default_params);
bool hasString(const std::string& name);
std::string getString(const std::string& name, const LLStringUtil::format_map_t& args) const;
@@ -256,6 +259,8 @@ protected:
commit_signal_t* mVisibleSignal; // Called when visibility changes, passes new visibility as LLSD()
std::string mHelpTopic; // the name of this panel's help topic to display in the Help Viewer
+ typedef std::deque<const LLCallbackMap::map_t*> factory_stack_t;
+ static factory_stack_t sFactoryStack;
private:
BOOL mBgVisible; // any background at all?
@@ -285,4 +290,57 @@ extern template class LLPanel* LLView::getChild<class LLPanel>(
const std::string& name, BOOL recurse) const;
#endif
+typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc;
+
+// local static instance for registering a particular panel class
+
+class LLRegisterPanelClass
+: public LLSingleton< LLRegisterPanelClass >
+{
+public:
+ // reigister with either the provided builder, or the generic templated builder
+ void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func)
+ {
+ mPanelClassesNames[tag] = func;
+ }
+
+ LLPanel* createPanelClass(const std::string& tag)
+ {
+ param_name_map_t::iterator iT = mPanelClassesNames.find(tag);
+ if(iT == mPanelClassesNames.end())
+ return 0;
+ return iT->second();
+ }
+ template<typename T>
+ static T* defaultPanelClassBuilder()
+ {
+ T* pT = new T();
+ return pT;
+ }
+
+private:
+ typedef std::map< std::string, LLPanelClassCreatorFunc> param_name_map_t;
+
+ param_name_map_t mPanelClassesNames;
+};
+
+
+// local static instance for registering a particular panel class
+template<typename T>
+class LLRegisterPanelClassWrapper
+: public LLRegisterPanelClass
+{
+public:
+ // reigister with either the provided builder, or the generic templated builder
+ LLRegisterPanelClassWrapper(const std::string& tag);
+};
+
+
+template<typename T>
+LLRegisterPanelClassWrapper<T>::LLRegisterPanelClassWrapper(const std::string& tag)
+{
+ LLRegisterPanelClass::instance().addPanelClass(tag,&LLRegisterPanelClass::defaultPanelClassBuilder<T>);
+}
+
+
#endif
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index 83c42a5ab8..cc348fdc63 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -100,8 +100,8 @@ LLRadioGroup::LLRadioGroup(const LLRadioGroup::Params& p)
void LLRadioGroup::initFromParams(const Params& p)
{
- for (LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items().begin();
- it != p.items().end();
+ for (LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items.begin();
+ it != p.items.end();
++it)
{
LLRadioGroup::ItemParams item_params(*it);
diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp
index 50b7bbab90..5e6840d7df 100644
--- a/indra/llui/llrngwriter.cpp
+++ b/indra/llui/llrngwriter.cpp
@@ -30,10 +30,15 @@
#include "lluicolor.h"
#include "lluictrlfactory.h"
+static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
+static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
+static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
+
//
// LLRNGWriter - writes Relax NG schema files based on a param block
//
LLRNGWriter::LLRNGWriter()
+: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
{
// register various callbacks for inspecting the contents of a param block
registerInspectFunc<bool>(boost::bind(&LLRNGWriter::writeAttribute, this, "boolean", _1, _2, _3, _4));
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 84e438cfb7..7df7c13dc0 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -259,15 +259,15 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
}
- for (LLInitParam::ParamIterator<LLScrollListColumn::Params>::const_iterator row_it = p.contents.columns().begin();
- row_it != p.contents.columns().end();
+ for (LLInitParam::ParamIterator<LLScrollListColumn::Params>::const_iterator row_it = p.contents.columns.begin();
+ row_it != p.contents.columns.end();
++row_it)
{
addColumn(*row_it);
}
- for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = p.contents.rows().begin();
- row_it != p.contents.rows().end();
+ for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = p.contents.rows.begin();
+ row_it != p.contents.rows.end();
++row_it)
{
addRow(*row_it);
@@ -537,23 +537,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
setNeedsSort();
break;
- case ADD_SORTED:
- {
- // sort by column 0, in ascending order
- std::vector<sort_column_t> single_sort_column;
- single_sort_column.push_back(std::make_pair(0, TRUE));
-
- mItemList.push_back(item);
- std::stable_sort(
- mItemList.begin(),
- mItemList.end(),
- SortScrollListItem(single_sort_column,mSortCallback));
-
- // ADD_SORTED just sorts by first column...
- // this might not match user sort criteria, so flag list as being in unsorted state
- setNeedsSort();
- break;
- }
+ case ADD_DEFAULT:
case ADD_BOTTOM:
mItemList.push_back(item);
setNeedsSort();
@@ -2578,7 +2562,8 @@ BOOL LLScrollListCtrl::canDeselect() const
void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
{
LLScrollListColumn::Params p;
- LLParamSDParser::instance().readSD(column, p);
+ LLParamSDParser parser;
+ parser.readSD(column, p);
addColumn(p, pos);
}
@@ -2764,31 +2749,35 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name)
return NULL;
}
-
+LLFastTimer::DeclareTimer FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item");
LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
{
+ LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
LLScrollListItem::Params item_params;
- LLParamSDParser::instance().readSD(element, item_params);
+ LLParamSDParser parser;
+ parser.readSD(element, item_params);
item_params.userdata = userdata;
return addRow(item_params, pos);
}
LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)
{
+ LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
LLScrollListItem *new_item = new LLScrollListItem(item_p);
return addRow(new_item, item_p, pos);
}
LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos)
{
+ LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
if (!item_p.validateBlock() || !new_item) return NULL;
new_item->setNumColumns(mColumns.size());
// Add any columns we don't already have
S32 col_index = 0;
- for(LLInitParam::ParamIterator<LLScrollListCell::Params>::const_iterator itor = item_p.columns().begin();
- itor != item_p.columns().end();
+ for(LLInitParam::ParamIterator<LLScrollListCell::Params>::const_iterator itor = item_p.columns.begin();
+ itor != item_p.columns.end();
++itor)
{
LLScrollListCell::Params cell_p = *itor;
@@ -2839,7 +2828,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS
col_index++;
}
- if (item_p.columns().empty())
+ if (item_p.columns.empty())
{
if (mColumns.empty())
{
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index 54c3060c4a..f97f80ab6c 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -29,49 +29,42 @@
// Project includes
#include "llsdparam.h"
+#include "llsdutil.h"
+
+static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
+static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
+static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
//
// LLParamSDParser
//
LLParamSDParser::LLParamSDParser()
+: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
{
using boost::bind;
- registerParserFuncs<S32>(bind(&LLParamSDParser::readTypedValue<S32>, this, _1, &LLSD::asInteger),
- bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2));
- registerParserFuncs<U32>(bind(&LLParamSDParser::readTypedValue<U32>, this, _1, &LLSD::asInteger),
- bind(&LLParamSDParser::writeU32Param, this, _1, _2));
- registerParserFuncs<F32>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asReal),
- bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
- registerParserFuncs<F64>(bind(&LLParamSDParser::readTypedValue<F64>, this, _1, &LLSD::asReal),
- bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2));
- registerParserFuncs<bool>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asBoolean),
- bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
- registerParserFuncs<std::string>(bind(&LLParamSDParser::readTypedValue<std::string>, this, _1, &LLSD::asString),
- bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2));
- registerParserFuncs<LLUUID>(bind(&LLParamSDParser::readTypedValue<LLUUID>, this, _1, &LLSD::asUUID),
- bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2));
- registerParserFuncs<LLDate>(bind(&LLParamSDParser::readTypedValue<LLDate>, this, _1, &LLSD::asDate),
- bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2));
- registerParserFuncs<LLURI>(bind(&LLParamSDParser::readTypedValue<LLURI>, this, _1, &LLSD::asURI),
- bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2));
- registerParserFuncs<LLSD>(bind(&LLParamSDParser::readSDParam, this, _1),
- bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));
-}
-
-bool LLParamSDParser::readSDParam(void* value_ptr)
-{
- if (!mCurReadSD) return false;
- *((LLSD*)value_ptr) = *mCurReadSD;
- return true;
+ if (sReadFuncs.empty())
+ {
+ registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
+ registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
+ registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
+ registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
+ registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
+ registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
+ registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
+ registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
+ registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
+ registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
+ }
}
// special case handling of U32 due to ambiguous LLSD::assign overload
-bool LLParamSDParser::writeU32Param(const void* val_ptr, const parser_t::name_stack_t& name_stack)
+bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)
{
- if (!mWriteSD) return false;
+ LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+ if (!sdparser.mWriteRootSD) return false;
- LLSD* sd_to_write = getSDWriteNode(name_stack);
+ LLSD* sd_to_write = sdparser.getSDWriteNode(name_stack);
if (!sd_to_write) return false;
sd_to_write->assign((S32)*((const U32*)val_ptr));
@@ -89,7 +82,8 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool
void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
{
- mWriteSD = &sd;
+ mNameStack.clear();
+ mWriteRootSD = &sd;
block.serializeBlock(*this);
}
@@ -139,6 +133,155 @@ void LLParamSDParser::readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block
LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)
{
//TODO: implement nested LLSD writing
- return mWriteSD;
+ LLSD* sd_to_write = mWriteRootSD;
+ bool new_traversal = false;
+ for (name_stack_t::const_iterator it = name_stack.begin(), prev_it = mNameStack.begin();
+ it != name_stack.end();
+ ++it)
+ {
+ bool new_array_entry = false;
+ if (prev_it == mNameStack.end())
+ {
+ new_traversal = true;
+ }
+ else
+ {
+ if (!new_traversal // have not diverged yet from previous trace
+ && prev_it->first == it->first // names match
+ && prev_it->second != it->second) // versions differ
+ {
+ // name stacks match, but version numbers differ in last place.
+ // create a different entry at this point using an LLSD array
+ new_array_entry = true;
+ }
+ if (prev_it->first != it->first // names differ
+ || prev_it->second != it->second) // versions differ
+ {
+ // at this point we have diverged from our last trace
+ // so any elements referenced here are new
+ new_traversal = true;
+ }
+ }
+
+ LLSD* child_sd = &(*sd_to_write)[it->first];
+
+ if (child_sd->isArray())
+ {
+ if (new_traversal)
+ {
+ // write to new element at end
+ sd_to_write = &(*child_sd)[child_sd->size()];
+ }
+ else
+ {
+ // write to last of existing elements, or first element if empty
+ sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
+ }
+ }
+ else
+ {
+ if (new_array_entry && !child_sd->isArray())
+ {
+ // copy child contents into first element of an array
+ LLSD new_array = LLSD::emptyArray();
+ new_array.append(*child_sd);
+ // assign array to slot that previously held the single value
+ *child_sd = new_array;
+ // return next element in that array
+ sd_to_write = &((*child_sd)[1]);
+ }
+ else
+ {
+ sd_to_write = child_sd;
+ }
+ }
+ if (prev_it != mNameStack.end())
+ {
+ ++prev_it;
+ }
+ }
+ mNameStack = name_stack;
+
+ //llinfos << ll_pretty_print_sd(*mWriteRootSD) << llendl;
+ return sd_to_write;
+}
+
+bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((S32*)val_ptr) = self.mCurReadSD->asInteger();
+ return true;
+}
+
+bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((U32*)val_ptr) = self.mCurReadSD->asInteger();
+ return true;
+}
+
+bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((F32*)val_ptr) = self.mCurReadSD->asReal();
+ return true;
+}
+
+bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((F64*)val_ptr) = self.mCurReadSD->asReal();
+ return true;
+}
+
+bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((bool*)val_ptr) = self.mCurReadSD->asBoolean();
+ return true;
+}
+
+bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((std::string*)val_ptr) = self.mCurReadSD->asString();
+ return true;
}
+bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
+ return true;
+}
+
+bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((LLDate*)val_ptr) = self.mCurReadSD->asDate();
+ return true;
+}
+
+bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((LLURI*)val_ptr) = self.mCurReadSD->asURI();
+ return true;
+}
+
+bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((LLSD*)val_ptr) = *self.mCurReadSD;
+ return true;
+}
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
index e028fc30c2..97e8b58e49 100644
--- a/indra/llui/llsdparam.h
+++ b/indra/llui/llsdparam.h
@@ -31,17 +31,14 @@
#include "llinitparam.h"
class LLParamSDParser
-: public LLInitParam::Parser,
- public LLSingleton<LLParamSDParser>
+: public LLInitParam::Parser
{
LOG_CLASS(LLParamSDParser);
typedef LLInitParam::Parser parser_t;
-protected:
- LLParamSDParser();
- friend class LLSingleton<LLParamSDParser>;
public:
+ LLParamSDParser();
void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
@@ -51,20 +48,12 @@ private:
void readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block);
template<typename T>
- bool readTypedValue(void* val_ptr, boost::function<T(const LLSD&)> parser_func)
- {
- if (!mCurReadSD) return false;
-
- *((T*)val_ptr) = parser_func(*mCurReadSD);
- return true;
- }
-
- template<typename T>
- bool writeTypedValue(const void* val_ptr, const parser_t::name_stack_t& name_stack)
+ static bool writeTypedValue(Parser& parser, const void* val_ptr, const parser_t::name_stack_t& name_stack)
{
- if (!mWriteSD) return false;
+ LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+ if (!sdparser.mWriteRootSD) return false;
- LLSD* sd_to_write = getSDWriteNode(name_stack);
+ LLSD* sd_to_write = sdparser.getSDWriteNode(name_stack);
if (!sd_to_write) return false;
sd_to_write->assign(*((const T*)val_ptr));
@@ -73,12 +62,23 @@ private:
LLSD* getSDWriteNode(const parser_t::name_stack_t& name_stack);
- bool readSDParam(void* value_ptr);
- bool writeU32Param(const void* value_ptr, const parser_t::name_stack_t& name_stack);
+ static bool writeU32Param(Parser& parser, const void* value_ptr, const parser_t::name_stack_t& name_stack);
+
+ static bool readS32(Parser& parser, void* val_ptr);
+ static bool readU32(Parser& parser, void* val_ptr);
+ static bool readF32(Parser& parser, void* val_ptr);
+ static bool readF64(Parser& parser, void* val_ptr);
+ static bool readBool(Parser& parser, void* val_ptr);
+ static bool readString(Parser& parser, void* val_ptr);
+ static bool readUUID(Parser& parser, void* val_ptr);
+ static bool readDate(Parser& parser, void* val_ptr);
+ static bool readURI(Parser& parser, void* val_ptr);
+ static bool readSD(Parser& parser, void* val_ptr);
Parser::name_stack_t mNameStack;
const LLSD* mCurReadSD;
- LLSD* mWriteSD;
+ LLSD* mWriteRootSD;
+ LLSD* mCurWriteSD;
};
template<typename T>
@@ -88,7 +88,8 @@ class LLSDParamAdapter : public T
LLSDParamAdapter() {}
LLSDParamAdapter(const LLSD& sd)
{
- LLParamSDParser::instance().readSD(sd, *this);
+ LLParamSDParser parser;
+ parser.readSD(sd, *this);
}
LLSDParamAdapter(const T& val)
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 9decfa0b25..6b4e9cf923 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -119,7 +119,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
{
params.font(p.font);
}
- params.max_length_bytes(MAX_STRING_LENGTH);
+ params.max_length.bytes(MAX_STRING_LENGTH);
params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2)));
if( mPrecision>0 )//should accept float numbers
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index 5e09cee78b..28a064e6b6 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -40,7 +40,8 @@ LLStyle::Params::Params()
selected_color("selected_color", LLColor4::black),
font("font", LLFontGL::getFontMonospace()),
image("image"),
- link_href("href")
+ link_href("href"),
+ is_link("is_link")
{}
@@ -51,6 +52,7 @@ LLStyle::LLStyle(const LLStyle::Params& p)
mSelectedColor(p.selected_color),
mFont(p.font()),
mLink(p.link_href),
+ mIsLink(p.is_link.isProvided() ? p.is_link : !p.link_href().empty()),
mDropShadow(p.drop_shadow),
mImagep(p.image())
{}
@@ -73,7 +75,7 @@ void LLStyle::setLinkHREF(const std::string& href)
BOOL LLStyle::isLink() const
{
- return mLink.size();
+ return mIsLink;
}
BOOL LLStyle::isVisible() const
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index 66cd639936..322edc343c 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -46,6 +46,7 @@ public:
Optional<const LLFontGL*> font;
Optional<LLUIImage*> image;
Optional<std::string> link_href;
+ Optional<bool> is_link;
Params();
};
LLStyle(const Params& p = Params());
@@ -106,6 +107,7 @@ private:
std::string mFontName;
const LLFontGL* mFont;
std::string mLink;
+ bool mIsLink;
LLUIImagePtr mImagep;
};
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 574b24cf13..9adeddca99 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2009-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
@@ -475,8 +475,8 @@ void LLTextBase::drawCursor()
{
LLColor4 text_color;
const LLFontGL* fontp;
- text_color = segmentp->getColor();
- fontp = segmentp->getStyle()->getFont();
+ text_color = segmentp->getColor();
+ fontp = segmentp->getStyle()->getFont();
fontp->render(text, mCursorPos, cursor_rect,
LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
LLFontGL::LEFT, mVAlign,
@@ -1602,6 +1602,20 @@ std::string LLTextBase::getText() const
return getViewModel()->getValue().asString();
}
+// IDEVO - icons can be UI image names or UUID sent from
+// server with avatar display name
+static LLUIImagePtr image_from_icon_name(const std::string& icon_name)
+{
+ if (LLUUID::validate(icon_name))
+ {
+ return LLUI::getUIImageByID( LLUUID(icon_name) );
+ }
+ else
+ {
+ return LLUI::getUIImage(icon_name);
+ }
+}
+
void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
{
LLStyle::Params style_params(input_params);
@@ -1614,16 +1628,13 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
LLUrlMatch match;
std::string text = new_text;
while ( LLUrlRegistry::instance().findUrl(text, match,
- boost::bind(&LLTextBase::replaceUrlLabel, this, _1, _2)) )
+ boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
{
start = match.getStart();
end = match.getEnd()+1;
- LLStyle::Params link_params = style_params;
- link_params.color = match.getColor();
- link_params.readonly_color = match.getColor();
- link_params.font.style("UNDERLINE");
- link_params.link_href = match.getUrl();
+ LLStyle::Params link_params(style_params);
+ link_params.overwriteFrom(match.getStyle());
// output the text before the Url
if (start > 0)
@@ -1644,26 +1655,20 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
// inserts an avatar icon preceding the Url if appropriate
LLTextUtil::processUrlMatch(&match,this);
- // output the styled Url (unless we've been asked to suppress hyperlinking)
- if (match.isLinkDisabled())
+ // output the styled Url
+ appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
+
+ // set the tooltip for the Url label
+ if (! match.getTooltip().empty())
{
- appendAndHighlightText(match.getLabel(), part, style_params);
+ segment_set_t::iterator it = getSegIterContaining(getLength()-1);
+ if (it != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *it;
+ segment->setToolTip(match.getTooltip());
+ }
}
- else
- {
- appendAndHighlightText(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
- // set the tooltip for the Url label
- if (! match.getTooltip().empty())
- {
- segment_set_t::iterator it = getSegIterContaining(getLength()-1);
- if (it != mSegments.end())
- {
- LLTextSegmentPtr segment = *it;
- segment->setToolTip(match.getTooltip());
- }
- }
- }
// move on to the rest of the text after the Url
if (end < (S32)text.length())
{
@@ -1848,8 +1853,9 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
}
-void LLTextBase::replaceUrlLabel(const std::string &url,
- const std::string &label)
+void LLTextBase::replaceUrl(const std::string &url,
+ const std::string &label,
+ const std::string &icon)
{
// get the full (wide) text for the editor so we can change it
LLWString text = getWText();
@@ -1870,7 +1876,7 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
seg->setEnd(seg_start + seg_length);
// if we find a link with our Url, then replace the label
- if (style->isLink() && style->getLinkHREF() == url)
+ if (style->getLinkHREF() == url)
{
S32 start = seg->getStart();
S32 end = seg->getEnd();
@@ -1879,6 +1885,21 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
modified = true;
}
+ // Icon might be updated when more avatar or group info
+ // becomes available
+ if (style->isImage() && style->getLinkHREF() == url)
+ {
+ LLUIImagePtr image = image_from_icon_name( icon );
+ if (image)
+ {
+ LLStyle::Params icon_params;
+ icon_params.image = image;
+ LLStyleConstSP new_style(new LLStyle(icon_params));
+ seg->setStyle(new_style);
+ modified = true;
+ }
+ }
+
// work out the character offset for the next segment
seg_start = seg->getEnd();
}
@@ -1976,8 +1997,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
else if (hit_past_end_of_line && segmentp->getEnd() > line_iter->mDocIndexEnd - 1)
{
// segment wraps to next line, so just set doc pos to the end of the line
- // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
- pos = llmin(getLength(), line_iter->mDocIndexEnd);
+ // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
+ pos = llmin(getLength(), line_iter->mDocIndexEnd);
break;
}
start_x += text_width;
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index e5dfecad54..aafcf8ceb0 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -235,6 +235,7 @@ class LLTextBase
public:
friend class LLTextSegment;
friend class LLNormalTextSegment;
+ friend class LLUICtrlFactory;
struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams>
{
@@ -492,7 +493,11 @@ protected:
// misc
void updateRects();
void needsScroll() { mScrollNeeded = TRUE; }
- void replaceUrlLabel(const std::string &url, const std::string &label);
+
+ struct URLLabelCallback;
+ // Replace a URL with a new icon and label, for example, when
+ // avatar names are looked up.
+ void replaceUrl(const std::string &url, const std::string &label, const std::string& icon);
void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index b02d3122fe..6390039794 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -78,9 +78,9 @@ BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
LLToolTipMgr& tooltip_mgr = LLToolTipMgr::instance();
- if (x != last_x && y != last_y)
+ if (x != last_x && y != last_y && !tooltip_mgr.getMouseNearRect().pointInRect(x, y))
{
- // allow new tooltips because mouse moved
+ // allow new tooltips because mouse moved outside of mouse near rect
tooltip_mgr.unblockToolTips();
}
@@ -276,8 +276,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
if (p.styled_message.isProvided())
{
- for (LLInitParam::ParamIterator<LLToolTip::StyledText>::const_iterator text_it = p.styled_message().begin();
- text_it != p.styled_message().end();
+ for (LLInitParam::ParamIterator<LLToolTip::StyledText>::const_iterator text_it = p.styled_message.begin();
+ text_it != p.styled_message.end();
++text_it)
{
mTextBox->appendText(text_it->text(), false, text_it->style);
@@ -580,6 +580,7 @@ void LLToolTipMgr::updateToolTipVisibility()
if (mToolTip->getVisibleTime() > tooltip_timeout)
{
hideToolTips();
+ unblockToolTips();
}
}
}
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index d33d8e3178..ff9af21e54 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1796,7 +1796,8 @@ void LLUI::setupPaths()
LLXMLNodePtr root;
BOOL success = LLXMLNode::parseFile(filename, root, NULL);
Paths paths;
- LLXUIParser::instance().readXUI(root, paths, filename);
+ LLXUIParser parser;
+ parser.readXUI(root, paths, filename);
sXUIPaths.clear();
@@ -1805,14 +1806,14 @@ void LLUI::setupPaths()
LLStringUtil::format_map_t path_args;
path_args["[LANGUAGE]"] = LLUI::getLanguage();
- for (LLInitParam::ParamIterator<Directory>::const_iterator it = paths.directories().begin(),
- end_it = paths.directories().end();
+ for (LLInitParam::ParamIterator<Directory>::const_iterator it = paths.directories.begin(),
+ end_it = paths.directories.end();
it != end_it;
++it)
{
std::string path_val_ui;
- for (LLInitParam::ParamIterator<SubDir>::const_iterator subdir_it = it->subdirs().begin(),
- subdir_end_it = it->subdirs().end();
+ for (LLInitParam::ParamIterator<SubDir>::const_iterator subdir_it = it->subdirs.begin(),
+ subdir_end_it = it->subdirs.end();
subdir_it != subdir_end_it;)
{
path_val_ui += subdir_it->value();
diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp
index 9891e38f7b..0641f6d175 100644
--- a/indra/llui/lluicolortable.cpp
+++ b/indra/llui/lluicolortable.cpp
@@ -56,8 +56,8 @@ void LLUIColorTable::insertFromParams(const Params& p, string_color_map_t& table
typedef std::map<std::string, std::string> string_string_map_t;
string_string_map_t unresolved_refs;
- for(LLInitParam::ParamIterator<ColorEntryParams>::const_iterator it = p.color_entries().begin();
- it != p.color_entries().end();
+ for(LLInitParam::ParamIterator<ColorEntryParams>::const_iterator it = p.color_entries.begin();
+ it != p.color_entries.end();
++it)
{
ColorEntryParams color_entry = *it;
@@ -237,7 +237,8 @@ void LLUIColorTable::saveUserSettings() const
}
LLXMLNodePtr output_node = new LLXMLNode("colors", false);
- LLXUIParser::instance().writeXUI(output_node, params);
+ LLXUIParser parser;
+ parser.writeXUI(output_node, params);
if(!output_node->isNull())
{
@@ -303,7 +304,8 @@ bool LLUIColorTable::loadFromFilename(const std::string& filename, string_color_
}
Params params;
- LLXUIParser::instance().readXUI(root, params, filename);
+ LLXUIParser parser;
+ parser.readXUI(root, params, filename);
if(params.validateBlock())
{
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 15a382660e..5de96f9d48 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -42,7 +42,7 @@
#include "llquaternion.h"
// this library includes
-#include "llfloater.h"
+#include "llpanel.h"
LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION("Widget Construction");
LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS("Widget InitFromParams");
@@ -93,10 +93,12 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa
std::string filename = std::string("widgets") + gDirUtilp->getDirDelimiter() + widget_tag + ".xml";
LLXMLNodePtr root_node;
- if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
+ std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), filename);
+ if (!full_filename.empty())
{
- LLUICtrlFactory::instance().pushFileName(filename);
- LLXUIParser::instance().readXUI(root_node, block, filename);
+ LLUICtrlFactory::instance().pushFileName(full_filename);
+ LLSimpleXUIParser parser;
+ parser.readXUI(full_filename, block);
LLUICtrlFactory::instance().popFileName();
}
}
@@ -171,70 +173,6 @@ bool LLUICtrlFactory::getLocalizedXMLNode(const std::string &xui_filename, LLXML
}
}
-static LLFastTimer::DeclareTimer FTM_BUILD_FLOATERS("Build Floaters");
-
-//-----------------------------------------------------------------------------
-// buildFloater()
-//-----------------------------------------------------------------------------
-bool LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filename, LLXMLNodePtr output_node)
-{
- LLFastTimer timer(FTM_BUILD_FLOATERS);
- LLXMLNodePtr root;
-
- //if exporting, only load the language being exported,
- //instead of layering localized version on top of english
- if (output_node)
- {
- if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
- {
- llwarns << "Couldn't parse floater from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
- return false;
- }
- }
- else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
- {
- llwarns << "Couldn't parse floater from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
- return false;
- }
-
- // root must be called floater
- if( !(root->hasName("floater") || root->hasName("multi_floater")) )
- {
- llwarns << "Root node should be named floater in: " << filename << llendl;
- return false;
- }
-
- bool res = true;
-
- lldebugs << "Building floater " << filename << llendl;
- pushFileName(filename);
- {
- if (!floaterp->getFactoryMap().empty())
- {
- mFactoryStack.push_front(&floaterp->getFactoryMap());
- }
-
- // for local registry callbacks; define in constructor, referenced in XUI or postBuild
- floaterp->getCommitCallbackRegistrar().pushScope();
- floaterp->getEnableCallbackRegistrar().pushScope();
-
- res = floaterp->initFloaterXML(root, floaterp->getParent(), filename, output_node);
-
- floaterp->setXMLFilename(filename);
-
- floaterp->getCommitCallbackRegistrar().popScope();
- floaterp->getEnableCallbackRegistrar().popScope();
-
- if (!floaterp->getFactoryMap().empty())
- {
- mFactoryStack.pop_front();
- }
- }
- popFileName();
-
- return res;
-}
-
//-----------------------------------------------------------------------------
// saveToXML()
//-----------------------------------------------------------------------------
@@ -243,69 +181,6 @@ S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename)
return 0;
}
-static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels");
-
-//-----------------------------------------------------------------------------
-// buildPanel()
-//-----------------------------------------------------------------------------
-BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, LLXMLNodePtr output_node)
-{
- LLFastTimer timer(FTM_BUILD_PANELS);
- BOOL didPost = FALSE;
- LLXMLNodePtr root;
-
- //if exporting, only load the language being exported,
- //instead of layering localized version on top of english
- if (output_node)
- {
- if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
- {
- llwarns << "Couldn't parse panel from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
- return didPost;
- }
- }
- else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
- {
- llwarns << "Couldn't parse panel from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
- return didPost;
- }
-
- // root must be called panel
- if( !root->hasName("panel" ) )
- {
- llwarns << "Root node should be named panel in : " << filename << llendl;
- return didPost;
- }
-
- lldebugs << "Building panel " << filename << llendl;
-
- pushFileName(filename);
- {
- if (!panelp->getFactoryMap().empty())
- {
- mFactoryStack.push_front(&panelp->getFactoryMap());
- }
-
- // for local registry callbacks; define in constructor, referenced in XUI or postBuild
- panelp->getCommitCallbackRegistrar().pushScope();
- panelp->getEnableCallbackRegistrar().pushScope();
-
- didPost = panelp->initPanelXML(root, NULL, output_node);
-
- panelp->getCommitCallbackRegistrar().popScope();
- panelp->getEnableCallbackRegistrar().popScope();
-
- panelp->setXMLFilename(filename);
-
- if (!panelp->getFactoryMap().empty())
- {
- mFactoryStack.pop_front();
- }
- }
- popFileName();
- return didPost;
-}
-
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@@ -337,29 +212,6 @@ LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const
return view;
}
-//-----------------------------------------------------------------------------
-// createFactoryPanel()
-//-----------------------------------------------------------------------------
-LLPanel* LLUICtrlFactory::createFactoryPanel(const std::string& name)
-{
- std::deque<const LLCallbackMap::map_t*>::iterator itor;
- for (itor = mFactoryStack.begin(); itor != mFactoryStack.end(); ++itor)
- {
- const LLCallbackMap::map_t* factory_map = *itor;
-
- // Look up this panel's name in the map.
- LLCallbackMap::map_const_iter_t iter = factory_map->find( name );
- if (iter != factory_map->end())
- {
- // Use the factory to create the panel, instead of using a default LLPanel.
- LLPanel *ret = (LLPanel*) iter->second.mCallback( iter->second.mData );
- return ret;
- }
- }
- LLPanel::Params panel_p;
- return create<LLPanel>(panel_p);
-}
-
std::string LLUICtrlFactory::getCurFileName()
{
return mFileNames.empty() ? "" : gDirUtilp->getWorkingDir() + gDirUtilp->getDirDelimiter() + mFileNames.back();
@@ -376,36 +228,6 @@ void LLUICtrlFactory::popFileName()
mFileNames.pop_back();
}
-
-//-----------------------------------------------------------------------------
-
-//static
-BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color)
-{
- std::string colorstring;
- BOOL res = node->getAttributeString(name.c_str(), colorstring);
- if (res)
- {
- if (LLUIColorTable::instance().colorExists(colorstring))
- {
- color.setVec(LLUIColorTable::instance().getColor(colorstring));
- }
- else
- {
- res = FALSE;
- }
- }
- if (!res)
- {
- res = LLColor4::parseColor(colorstring, &color);
- }
- if (!res)
- {
- res = node->getAttributeColor(name.c_str(), color);
- }
- return res;
-}
-
//static
void LLUICtrlFactory::setCtrlParent(LLView* view, LLView* parent, S32 tab_group)
{
@@ -421,28 +243,22 @@ std::string LLUICtrlFactory::findSkinnedFilename(const std::string& filename)
return gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename);
}
-void LLUICtrlFactory::pushFactoryFunctions(const LLCallbackMap::map_t* map)
-{
- mFactoryStack.push_back(map);
-}
-
-void LLUICtrlFactory::popFactoryFunctions()
-{
- if (!mFactoryStack.empty())
- {
- mFactoryStack.pop_back();
- }
-}
-
//static
void LLUICtrlFactory::copyName(LLXMLNodePtr src, LLXMLNodePtr dest)
{
dest->setName(src->getName()->mString);
}
+template<typename T>
+const LLInitParam::BaseBlock& get_empty_param_block()
+{
+ static typename T::Params params;
+ return params;
+}
+
// adds a widget and its param block to various registries
//static
-void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, dummy_widget_creator_func_t creator_func, const std::string& tag)
+void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag)
{
// associate parameter block type with template .xml file
std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type);
@@ -462,17 +278,9 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st
}
}
LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag);
- // associate widget type with factory function
- LLDefaultWidgetRegistry::instance().defaultRegistrar().add(widget_type, creator_func);
//FIXME: comment this in when working on schema generation
//LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);
- //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &getEmptyParamBlock<T>);
-}
-
-//static
-dummy_widget_creator_func_t* LLUICtrlFactory::getDefaultWidgetFunc(const std::type_info* widget_type)
-{
- return LLDefaultWidgetRegistry::instance().getValue(widget_type);
+ //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block<T>);
}
//static
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 58ec5d8387..499b97f52d 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -27,24 +27,13 @@
#ifndef LLUICTRLFACTORY_H
#define LLUICTRLFACTORY_H
-#include "llcallbackmap.h"
+#include "llfasttimer.h"
#include "llinitparam.h"
#include "llregistry.h"
-#include "v4color.h"
-#include "llfasttimer.h"
-
#include "llxuiparser.h"
-#include <boost/function.hpp>
-#include <iosfwd>
-#include <stack>
-#include <set>
-
-class LLPanel;
-class LLFloater;
class LLView;
-
// sort functor for typeid maps
struct LLCompareTypeID
{
@@ -85,12 +74,6 @@ class LLWidgetNameRegistry
: public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry , LLCompareTypeID>
{};
-// lookup factory functions for default widget instances by widget type
-typedef LLView* (*dummy_widget_creator_func_t)(const std::string&);
-class LLDefaultWidgetRegistry
-: public LLRegistrySingleton<const std::type_info*, dummy_widget_creator_func_t, LLDefaultWidgetRegistry, LLCompareTypeID>
-{};
-
// lookup function for generating empty param block by widget type
// this is used for schema generation
//typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
@@ -157,58 +140,21 @@ public:
return ParamDefaults<typename T::Params, 0>::instance().get();
}
- bool buildFloater(LLFloater* floaterp, const std::string &filename, LLXMLNodePtr output_node);
- BOOL buildPanel(LLPanel* panelp, const std::string &filename, LLXMLNodePtr output_node = NULL);
-
// Does what you want for LLFloaters and LLPanels
// Returns 0 on success
S32 saveToXML(LLView* viewp, const std::string& filename);
+ // filename tracking for debugging info
std::string getCurFileName();
void pushFileName(const std::string& name);
void popFileName();
- static BOOL getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color);
-
- LLPanel* createFactoryPanel(const std::string& name);
-
- void pushFactoryFunctions(const LLCallbackMap::map_t* map);
- void popFactoryFunctions();
-
- template<typename T>
- static T* createWidget(const typename T::Params& params, LLView* parent = NULL)
- {
- T* widget = NULL;
-
- if (!params.validateBlock())
- {
- llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl;
- //return NULL;
- }
-
- {
- LLFastTimer timer(FTM_WIDGET_CONSTRUCTION);
- widget = new T(params);
- }
- {
- LLFastTimer timer(FTM_INIT_FROM_PARAMS);
- widget->initFromParams(params);
- }
-
- if (parent)
- {
- S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : S32_MAX;
- setCtrlParent(widget, parent, tab_group);
- }
- return widget;
- }
-
template<typename T>
static T* create(typename T::Params& params, LLView* parent = NULL)
{
params.fillFrom(ParamDefaults<typename T::Params, 0>::instance().get());
- T* widget = createWidget<T>(params, parent);
+ T* widget = createWidgetImpl<T>(params, parent);
if (widget)
{
widget->postBuild();
@@ -266,21 +212,54 @@ fail:
template<class T>
static T* getDefaultWidget(const std::string& name)
{
- dummy_widget_creator_func_t* dummy_func = getDefaultWidgetFunc(&typeid(T));
- return dummy_func ? dynamic_cast<T*>((*dummy_func)(name)) : NULL;
+ typename T::Params widget_params;
+ widget_params.name = name;
+ return create<T>(widget_params);
}
- template <class T>
- static LLView* createDefaultWidget(const std::string& name)
- {
- typename T::Params params;
- params.name(name);
-
- return create<T>(params);
- }
+ static void createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t&, LLXMLNodePtr output_node = NULL);
+
+ static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root);
+ static bool getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root);
+
+private:
+ //NOTE: both friend declarations are necessary to keep both gcc and msvc happy
+ template <typename T> friend class LLChildRegistry;
+ template <typename T> template <typename U> friend class LLChildRegistry<T>::Register;
static void copyName(LLXMLNodePtr src, LLXMLNodePtr dest);
+ // helper function for adding widget type info to various registries
+ static void registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag);
+
+ static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block);
+
+ template<typename T>
+ static T* createWidgetImpl(const typename T::Params& params, LLView* parent = NULL)
+ {
+ T* widget = NULL;
+
+ if (!params.validateBlock())
+ {
+ llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl;
+ //return NULL;
+ }
+
+ { LLFastTimer _(FTM_WIDGET_CONSTRUCTION);
+ widget = new T(params);
+ }
+ { LLFastTimer _(FTM_INIT_FROM_PARAMS);
+ widget->initFromParams(params);
+ }
+
+ if (parent)
+ {
+ S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : S32_MAX;
+ setCtrlParent(widget, parent, tab_group);
+ }
+ return widget;
+ }
+
template<typename T>
static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
@@ -288,7 +267,8 @@ fail:
typename T::Params params(getDefaultParams<T>());
- LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+ LLXUIParser parser;
+ parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
if (output_node)
{
@@ -298,14 +278,13 @@ fail:
// Export only the differences between this any default params
typename T::Params default_params(getDefaultParams<T>());
copyName(node, output_node);
- LLXUIParser::instance().writeXUI(
- output_node, output_params, &default_params);
+ parser.writeXUI(output_node, output_params, &default_params);
}
// Apply layout transformations, usually munging rect
params.from_xui = true;
T::applyXUILayout(params, parent);
- T* widget = createWidget<T>(params, parent);
+ T* widget = createWidgetImpl<T>(params, parent);
typedef typename T::child_registry_t registry_t;
@@ -320,20 +299,6 @@ fail:
return widget;
}
- static void createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t&, LLXMLNodePtr output_node = NULL);
-
- static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root);
-
- static bool getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root);
-
- static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block);
-
- // helper function for adding widget type info to various registries
- static void registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, dummy_widget_creator_func_t creator_func, const std::string& tag);
-
-private:
- // return default widget instance factory func for a given type
- static dummy_widget_creator_func_t* getDefaultWidgetFunc(const std::type_info* widget_type);
static const std::string* getWidgetTag(const std::type_info* widget_type);
@@ -343,20 +308,10 @@ private:
// Avoid directly using LLUI and LLDir in the template code
static std::string findSkinnedFilename(const std::string& filename);
- typedef std::deque<const LLCallbackMap::map_t*> factory_stack_t;
- factory_stack_t mFactoryStack;
-
- LLPanel* mDummyPanel;
+ class LLPanel* mDummyPanel;
std::vector<std::string> mFileNames;
};
-template<typename T>
-const LLInitParam::BaseBlock& getEmptyParamBlock()
-{
- static typename T::Params params;
- return params;
-}
-
// this is here to make gcc happy with reference to LLUICtrlFactory
template<typename DERIVED>
template<typename T>
@@ -364,7 +319,7 @@ LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreator
: LLChildRegistry<DERIVED>::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func)
{
// add this widget to various registries
- LLUICtrlFactory::instance().registerWidget(&typeid(T), &typeid(typename T::Params), &LLUICtrlFactory::createDefaultWidget<T>, tag);
+ LLUICtrlFactory::instance().registerWidget(&typeid(T), &typeid(typename T::Params), tag);
// since registry_t depends on T, do this in line here
// TODO: uncomment this for schema generation
@@ -372,58 +327,4 @@ LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreator
//LLChildRegistryRegistry::instance().defaultRegistrar().add(&typeid(T), registry_t::instance());
}
-
-typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc;
-
-// local static instance for registering a particular panel class
-
-class LLRegisterPanelClass
-: public LLSingleton< LLRegisterPanelClass >
-{
-public:
- // reigister with either the provided builder, or the generic templated builder
- void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func)
- {
- mPanelClassesNames[tag] = func;
- }
-
- LLPanel* createPanelClass(const std::string& tag)
- {
- param_name_map_t::iterator iT = mPanelClassesNames.find(tag);
- if(iT == mPanelClassesNames.end())
- return 0;
- return iT->second();
- }
- template<typename T>
- static T* defaultPanelClassBuilder()
- {
- T* pT = new T();
- return pT;
- }
-
-private:
- typedef std::map< std::string, LLPanelClassCreatorFunc> param_name_map_t;
-
- param_name_map_t mPanelClassesNames;
-};
-
-
-// local static instance for registering a particular panel class
-template<typename T>
-class LLRegisterPanelClassWrapper
-: public LLRegisterPanelClass
-{
-public:
- // reigister with either the provided builder, or the generic templated builder
- LLRegisterPanelClassWrapper(const std::string& tag);
-};
-
-
-template<typename T>
-LLRegisterPanelClassWrapper<T>::LLRegisterPanelClassWrapper(const std::string& tag)
-{
- LLRegisterPanelClass::instance().addPanelClass(tag,&LLRegisterPanelClass::defaultPanelClassBuilder<T>);
-}
-
-
#endif //LLUICTRLFACTORY_H
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index 3e9b956ee6..ac69d3bf85 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -34,7 +34,7 @@ LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");
LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args)
: mOrig(instring),
- mArgs(args)
+ mArgs(new LLStringUtil::format_map_t(args))
{
dirty();
}
@@ -48,7 +48,7 @@ void LLUIString::assign(const std::string& s)
void LLUIString::setArgList(const LLStringUtil::format_map_t& args)
{
- mArgs = args;
+ getArgs() = args;
dirty();
}
@@ -68,7 +68,7 @@ void LLUIString::setArgs(const LLSD& sd)
void LLUIString::setArg(const std::string& key, const std::string& replacement)
{
- mArgs[key] = replacement;
+ getArgs()[key] = replacement;
dirty();
}
@@ -129,14 +129,14 @@ void LLUIString::updateResult() const
mResult = mOrig;
// get the defailt args + local args
- if (mArgs.empty())
+ if (!mArgs || mArgs->empty())
{
LLStringUtil::format(mResult, LLTrans::getDefaultArgs());
}
else
{
LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs();
- combined_args.insert(mArgs.begin(), mArgs.end());
+ combined_args.insert(mArgs->begin(), mArgs->end());
LLStringUtil::format(mResult, combined_args);
}
}
@@ -147,3 +147,12 @@ void LLUIString::updateWResult() const
mWResult = utf8str_to_wstring(getUpdatedResult());
}
+
+LLStringUtil::format_map_t& LLUIString::getArgs()
+{
+ if (!mArgs)
+ {
+ mArgs = new LLStringUtil::format_map_t;
+ }
+ return *mArgs;
+}
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index fc7ac37d99..eff2467bf0 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -58,9 +58,9 @@ class LLUIString
public:
// These methods all perform appropriate argument substitution
// and modify mOrig where appropriate
- LLUIString() : mNeedsResult(false), mNeedsWResult(false) {}
+ LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {}
LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args);
- LLUIString(const std::string& instring) { assign(instring); }
+ LLUIString(const std::string& instring) : mArgs(NULL) { assign(instring); }
void assign(const std::string& instring);
LLUIString& operator=(const std::string& s) { assign(s); return *this; }
@@ -80,7 +80,7 @@ public:
S32 length() const { return getUpdatedWResult().size(); }
void clear();
- void clearArgs() { mArgs.clear(); }
+ void clearArgs() { if (mArgs) mArgs->clear(); }
// These utility functions are included for text editing.
// They do not affect mOrig and do not perform argument substitution
@@ -99,11 +99,12 @@ private:
// do actual work of updating strings (non-inlined)
void updateResult() const;
void updateWResult() const;
+ LLStringUtil::format_map_t& getArgs();
std::string mOrig;
mutable std::string mResult;
mutable LLWString mWResult; // for displaying
- LLStringUtil::format_map_t mArgs;
+ LLStringUtil::format_map_t* mArgs;
// controls lazy evaluation
mutable bool mNeedsResult;
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 5680ab8bd4..efb3f1a8be 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -31,18 +31,19 @@
#include "llurlmatch.h"
#include "llurlregistry.h"
+#include "llavatarnamecache.h"
#include "llcachename.h"
#include "lltrans.h"
#include "lluicolortable.h"
#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
+// Utility functions
+std::string localize_slapp_label(const std::string& url, const std::string& full_name);
-LLUrlEntryBase::LLUrlEntryBase() :
- mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")),
- mDisabledLink(false)
-{
-}
+
+LLUrlEntryBase::LLUrlEntryBase()
+{}
LLUrlEntryBase::~LLUrlEntryBase()
{
@@ -53,6 +54,22 @@ std::string LLUrlEntryBase::getUrl(const std::string &string) const
return escapeUrl(string);
}
+//virtual
+std::string LLUrlEntryBase::getIcon(const std::string &url)
+{
+ return mIcon;
+}
+
+LLStyle::Params LLUrlEntryBase::getStyle() const
+{
+ LLStyle::Params style_params;
+ style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ style_params.font.style = "UNDERLINE";
+ return style_params;
+}
+
+
std::string LLUrlEntryBase::getIDStringFromUrl(const std::string &url) const
{
// return the id from a SLURL in the format /app/{cmd}/{id}/about
@@ -130,16 +147,20 @@ void LLUrlEntryBase::addObserver(const std::string &id,
mObservers.insert(std::pair<std::string, LLUrlEntryObserver>(id, observer));
}
}
-
-void LLUrlEntryBase::callObservers(const std::string &id, const std::string &label)
+
+// *NOTE: See also LLUrlEntryAgent::callObservers()
+void LLUrlEntryBase::callObservers(const std::string &id,
+ const std::string &label,
+ const std::string &icon)
{
// notify all callbacks waiting on the given uuid
- std::multimap<std::string, LLUrlEntryObserver>::iterator it;
- for (it = mObservers.find(id); it != mObservers.end();)
+ typedef std::multimap<std::string, LLUrlEntryObserver>::iterator observer_it;
+ std::pair<observer_it, observer_it> matching_range = mObservers.equal_range(id);
+ for (observer_it it = matching_range.first; it != matching_range.second;)
{
// call the callback - give it the new label
LLUrlEntryObserver &observer = it->second;
- (*observer.signal)(it->second.url, label);
+ (*observer.signal)(it->second.url, label, icon);
// then remove the signal - we only need to call it once
delete observer.signal;
mObservers.erase(it++);
@@ -188,7 +209,13 @@ LLUrlEntryHTTPLabel::LLUrlEntryHTTPLabel()
std::string LLUrlEntryHTTPLabel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
- return getLabelFromWikiLink(url);
+ std::string label = getLabelFromWikiLink(url);
+ return (!LLUrlRegistry::instance().hasUrl(label)) ? label : getUrl(url);
+}
+
+std::string LLUrlEntryHTTPLabel::getTooltip(const std::string &string) const
+{
+ return getUrl(string);
}
std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) const
@@ -308,16 +335,35 @@ LLUrlEntryAgent::LLUrlEntryAgent()
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_agent.xml";
mIcon = "Generic_Person";
- mColor = LLUIColorTable::instance().getColor("AgentLinkColor");
}
-void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group)
+// virtual
+void LLUrlEntryAgent::callObservers(const std::string &id,
+ const std::string &label,
+ const std::string &icon)
+{
+ // notify all callbacks waiting on the given uuid
+ typedef std::multimap<std::string, LLUrlEntryObserver>::iterator observer_it;
+ std::pair<observer_it, observer_it> matching_range = mObservers.equal_range(id);
+ for (observer_it it = matching_range.first; it != matching_range.second;)
+ {
+ // call the callback - give it the new label
+ LLUrlEntryObserver &observer = it->second;
+ std::string final_label = localize_slapp_label(observer.url, label);
+ (*observer.signal)(observer.url, final_label, icon);
+ // then remove the signal - we only need to call it once
+ delete observer.signal;
+ mObservers.erase(it++);
+ }
+}
+
+void LLUrlEntryAgent::onAvatarNameCache(const LLUUID& id,
+ const LLAvatarName& av_name)
{
+ std::string label = av_name.getCompleteName();
+
// received the agent name from the server - tell our observers
- callObservers(id.asString(), first + " " + last);
+ callObservers(id.asString(), label, mIcon);
}
LLUUID LLUrlEntryAgent::getID(const std::string &string) const
@@ -330,6 +376,10 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
// return a tooltip corresponding to the URL type instead of the generic one
std::string url = getUrl(string);
+ if (LLStringUtil::endsWith(url, "/inspect"))
+ {
+ return LLTrans::getString("TooltipAgentInspect");
+ }
if (LLStringUtil::endsWith(url, "/mute"))
{
return LLTrans::getString("TooltipAgentMute");
@@ -379,50 +429,182 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
}
LLUUID agent_id(agent_id_string);
- std::string full_name;
if (agent_id.isNull())
{
return LLTrans::getString("AvatarNameNobody");
}
- else if (gCacheName->getFullName(agent_id, full_name))
- {
- // customize label string based on agent SLapp suffix
- if (LLStringUtil::endsWith(url, "/mute"))
- {
- return LLTrans::getString("SLappAgentMute") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/unmute"))
- {
- return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/im"))
- {
- return LLTrans::getString("SLappAgentIM") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/pay"))
- {
- return LLTrans::getString("SLappAgentPay") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/offerteleport"))
- {
- return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/requestfriend"))
- {
- return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
- }
- return full_name;
+
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(agent_id, &av_name))
+ {
+ std::string label = av_name.getCompleteName();
+
+ // handle suffixes like /mute or /offerteleport
+ label = localize_slapp_label(url, label);
+ return label;
}
else
{
- gCacheName->get(agent_id, FALSE,
- boost::bind(&LLUrlEntryAgent::onAgentNameReceived,
- this, _1, _2, _3, _4));
+ LLAvatarNameCache::get(agent_id,
+ boost::bind(&LLUrlEntryAgent::onAvatarNameCache,
+ this, _1, _2));
addObserver(agent_id_string, url, cb);
return LLTrans::getString("LoadingData");
}
}
+LLStyle::Params LLUrlEntryAgent::getStyle() const
+{
+ LLStyle::Params style_params = LLUrlEntryBase::getStyle();
+ style_params.color = LLUIColorTable::instance().getColor("AgentLinkColor");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("AgentLinkColor");
+ return style_params;
+}
+
+std::string localize_slapp_label(const std::string& url, const std::string& full_name)
+{
+ // customize label string based on agent SLapp suffix
+ if (LLStringUtil::endsWith(url, "/mute"))
+ {
+ return LLTrans::getString("SLappAgentMute") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/unmute"))
+ {
+ return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/im"))
+ {
+ return LLTrans::getString("SLappAgentIM") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/pay"))
+ {
+ return LLTrans::getString("SLappAgentPay") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/offerteleport"))
+ {
+ return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/requestfriend"))
+ {
+ return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
+ }
+ return full_name;
+}
+
+
+std::string LLUrlEntryAgent::getIcon(const std::string &url)
+{
+ // *NOTE: Could look up a badge here by calling getIDStringFromUrl()
+ // and looking up the badge for the agent.
+ return mIcon;
+}
+
+//
+// LLUrlEntryAgentName describes a Second Life agent name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+//
+LLUrlEntryAgentName::LLUrlEntryAgentName()
+{}
+
+void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id,
+ const LLAvatarName& av_name)
+{
+ std::string label = getName(av_name);
+ // received the agent name from the server - tell our observers
+ callObservers(id.asString(), label, mIcon);
+}
+
+std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ if (!gCacheName)
+ {
+ // probably at the login screen, use short string for layout
+ return LLTrans::getString("LoadingData");
+ }
+
+ std::string agent_id_string = getIDStringFromUrl(url);
+ if (agent_id_string.empty())
+ {
+ // something went wrong, just give raw url
+ return unescapeUrl(url);
+ }
+
+ LLUUID agent_id(agent_id_string);
+ if (agent_id.isNull())
+ {
+ return LLTrans::getString("AvatarNameNobody");
+ }
+
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(agent_id, &av_name))
+ {
+ return getName(av_name);
+ }
+ else
+ {
+ LLAvatarNameCache::get(agent_id,
+ boost::bind(&LLUrlEntryAgentCompleteName::onAvatarNameCache,
+ this, _1, _2));
+ addObserver(agent_id_string, url, cb);
+ return LLTrans::getString("LoadingData");
+ }
+}
+
+LLStyle::Params LLUrlEntryAgentName::getStyle() const
+{
+ // don't override default colors
+ return LLStyle::Params().is_link(false);
+}
+
+//
+// LLUrlEntryAgentCompleteName describes a Second Life agent complete name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+//
+LLUrlEntryAgentCompleteName::LLUrlEntryAgentCompleteName()
+{
+ mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/completename",
+ boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentCompleteName::getName(const LLAvatarName& avatar_name)
+{
+ return avatar_name.getCompleteName();
+}
+
+//
+// LLUrlEntryAgentDisplayName describes a Second Life agent display name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+//
+LLUrlEntryAgentDisplayName::LLUrlEntryAgentDisplayName()
+{
+ mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/displayname",
+ boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentDisplayName::getName(const LLAvatarName& avatar_name)
+{
+ return avatar_name.mDisplayName;
+}
+
+//
+// LLUrlEntryAgentUserName describes a Second Life agent user name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+//
+LLUrlEntryAgentUserName::LLUrlEntryAgentUserName()
+{
+ mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/username",
+ boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentUserName::getName(const LLAvatarName& avatar_name)
+{
+ return avatar_name.mUsername.empty() ? avatar_name.getLegacyName() : avatar_name.mUsername;
+}
+
//
// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
@@ -436,18 +618,16 @@ LLUrlEntryGroup::LLUrlEntryGroup()
mMenuName = "menu_url_group.xml";
mIcon = "Generic_Group";
mTooltip = LLTrans::getString("TooltipGroupUrl");
- mColor = LLUIColorTable::instance().getColor("GroupLinkColor");
}
void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group)
+ const std::string& name,
+ bool is_group)
{
// received the group name from the server - tell our observers
- callObservers(id.asString(), first);
+ callObservers(id.asString(), name, mIcon);
}
LLUUID LLUrlEntryGroup::getID(const std::string &string) const
@@ -483,14 +663,23 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa
}
else
{
- gCacheName->get(group_id, TRUE,
+ gCacheName->getGroup(group_id,
boost::bind(&LLUrlEntryGroup::onGroupNameReceived,
- this, _1, _2, _3, _4));
+ this, _1, _2, _3));
addObserver(group_id_string, url, cb);
return LLTrans::getString("LoadingData");
}
}
+LLStyle::Params LLUrlEntryGroup::getStyle() const
+{
+ LLStyle::Params style_params = LLUrlEntryBase::getStyle();
+ style_params.color = LLUIColorTable::instance().getColor("GroupLinkColor");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("GroupLinkColor");
+ return style_params;
+}
+
+
//
// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
@@ -791,7 +980,6 @@ LLUrlEntryNoLink::LLUrlEntryNoLink()
{
mPattern = boost::regex("<nolink>[^<]*</nolink>",
boost::regex::perl|boost::regex::icase);
- mDisabledLink = true;
}
std::string LLUrlEntryNoLink::getUrl(const std::string &url) const
@@ -805,6 +993,12 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC
return getUrl(url);
}
+LLStyle::Params LLUrlEntryNoLink::getStyle() const
+{
+ return LLStyle::Params();
+}
+
+
//
// LLUrlEntryIcon describes an icon with <icon>...</icon> tags
//
@@ -812,7 +1006,6 @@ LLUrlEntryIcon::LLUrlEntryIcon()
{
mPattern = boost::regex("<icon\\s*>\\s*([^<]*)?\\s*</icon\\s*>",
boost::regex::perl|boost::regex::icase);
- mDisabledLink = true;
}
std::string LLUrlEntryIcon::getUrl(const std::string &url) const
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index e25eaa7555..9b91c103ef 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -30,13 +30,17 @@
#include "lluuid.h"
#include "lluicolor.h"
+#include "llstyle.h"
#include <boost/signals2.hpp>
#include <boost/regex.hpp>
#include <string>
#include <map>
+class LLAvatarName;
+
typedef boost::signals2::signal<void (const std::string& url,
- const std::string& label)> LLUrlLabelSignal;
+ const std::string& label,
+ const std::string& icon)> LLUrlLabelSignal;
typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback;
///
@@ -71,10 +75,10 @@ public:
virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
/// Return an icon that can be displayed next to Urls of this type
- virtual std::string getIcon(const std::string &url) { return mIcon; }
+ virtual std::string getIcon(const std::string &url);
- /// Return the color to render the displayed text
- LLUIColor getColor() const { return mColor; }
+ /// Return the style to render the displayed text
+ virtual LLStyle::Params getStyle() const;
/// Given a matched Url, return a tooltip string for the hyperlink
virtual std::string getTooltip(const std::string &string) const { return mTooltip; }
@@ -85,9 +89,6 @@ public:
/// Return the name of a SL location described by this Url, if any
virtual std::string getLocation(const std::string &url) const { return ""; }
- /// is this a match for a URL that should not be hyperlinked?
- bool isLinkDisabled() const { return mDisabledLink; }
-
/// Should this link text be underlined only when mouse is hovered over it?
virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
@@ -100,7 +101,7 @@ protected:
std::string getLabelFromWikiLink(const std::string &url) const;
std::string getUrlFromWikiLink(const std::string &string) const;
void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb);
- void callObservers(const std::string &id, const std::string &label);
+ virtual void callObservers(const std::string &id, const std::string &label, const std::string& icon);
typedef struct {
std::string url;
@@ -111,9 +112,7 @@ protected:
std::string mIcon;
std::string mMenuName;
std::string mTooltip;
- LLUIColor mColor;
std::multimap<std::string, LLUrlEntryObserver> mObservers;
- bool mDisabledLink;
};
///
@@ -134,6 +133,7 @@ class LLUrlEntryHTTPLabel : public LLUrlEntryBase
public:
LLUrlEntryHTTPLabel();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getTooltip(const std::string &string) const;
/*virtual*/ std::string getUrl(const std::string &string) const;
};
@@ -162,18 +162,78 @@ public:
///
/// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
-///
class LLUrlEntryAgent : public LLUrlEntryBase
{
public:
LLUrlEntryAgent();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getIcon(const std::string &url);
/*virtual*/ std::string getTooltip(const std::string &string) const;
+ /*virtual*/ LLStyle::Params getStyle() const;
/*virtual*/ LLUUID getID(const std::string &string) const;
/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
+protected:
+ /*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon);
+private:
+ void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
+};
+
+///
+/// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+/// that displays various forms of user name
+/// This is a base class for the various implementations of name display
+class LLUrlEntryAgentName : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryAgentName();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ LLStyle::Params getStyle() const;
+protected:
+ // override this to pull out relevant name fields
+ virtual std::string getName(const LLAvatarName& avatar_name) = 0;
+private:
+ void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
+};
+
+
+///
+/// LLUrlEntryAgentCompleteName Describes a Second Life agent name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+/// that displays the full display name + user name for an avatar
+/// such as "James Linden (james.linden)"
+class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName
+{
+public:
+ LLUrlEntryAgentCompleteName();
+private:
+ /*virtual*/ std::string getName(const LLAvatarName& avatar_name);
+};
+
+///
+/// LLUrlEntryAgentDisplayName Describes a Second Life agent display name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+/// that displays the just the display name for an avatar
+/// such as "James Linden"
+class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName
+{
+public:
+ LLUrlEntryAgentDisplayName();
+private:
+ /*virtual*/ std::string getName(const LLAvatarName& avatar_name);
+};
+
+///
+/// LLUrlEntryAgentUserName Describes a Second Life agent username Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+/// that displays the just the display name for an avatar
+/// such as "james.linden"
+class LLUrlEntryAgentUserName : public LLUrlEntryAgentName
+{
+public:
+ LLUrlEntryAgentUserName();
private:
- void onAgentNameReceived(const LLUUID& id, const std::string& first,
- const std::string& last, BOOL is_group);
+ /*virtual*/ std::string getName(const LLAvatarName& avatar_name);
};
///
@@ -185,10 +245,10 @@ class LLUrlEntryGroup : public LLUrlEntryBase
public:
LLUrlEntryGroup();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ LLStyle::Params getStyle() const;
/*virtual*/ LLUUID getID(const std::string &string) const;
private:
- void onGroupNameReceived(const LLUUID& id, const std::string& first,
- const std::string& last, BOOL is_group);
+ void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group);
};
///
@@ -297,6 +357,7 @@ public:
LLUrlEntryNoLink();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
+ /*virtual*/ LLStyle::Params getStyle() const;
};
///
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index e53b0c4370..c1f1382a9f 100644
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -37,16 +37,15 @@ LLUrlMatch::LLUrlMatch() :
mIcon(""),
mMenuName(""),
mLocation(""),
- mDisabledLink(false),
mUnderlineOnHoverOnly(false)
{
}
void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
- const std::string &icon, const LLUIColor& color,
+ const std::string &icon, const LLStyle::Params& style,
const std::string &menu, const std::string &location,
- bool disabled_link, const LLUUID& id, bool underline_on_hover_only)
+ const LLUUID& id, bool underline_on_hover_only)
{
mStart = start;
mEnd = end;
@@ -54,10 +53,10 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mLabel = label;
mTooltip = tooltip;
mIcon = icon;
- mColor = color;
+ mStyle = style;
+ mStyle.link_href = url;
mMenuName = menu;
mLocation = location;
- mDisabledLink = disabled_link;
mID = id;
mUnderlineOnHoverOnly = underline_on_hover_only;
}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index d1b2112ee7..2818f45207 100644
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -28,11 +28,11 @@
#ifndef LL_LLURLMATCH_H
#define LL_LLURLMATCH_H
-#include "linden_common.h"
+//#include "linden_common.h"
#include <string>
#include <vector>
-#include "lluicolor.h"
+#include "llstyle.h"
///
/// LLUrlMatch describes a single Url that was matched within a string by
@@ -69,7 +69,7 @@ public:
std::string getIcon() const { return mIcon; }
/// Return the color to render the displayed text
- LLUIColor getColor() const { return mColor; }
+ LLStyle::Params getStyle() const { return mStyle; }
/// Return the name of a XUI file containing the context menu items
std::string getMenuName() const { return mMenuName; }
@@ -77,21 +77,17 @@ public:
/// return the SL location that this Url describes, or "" if none.
std::string getLocation() const { return mLocation; }
- /// is this a match for a URL that should not be hyperlinked?
- bool isLinkDisabled() const { return mDisabledLink; }
-
/// Should this link text be underlined only when mouse is hovered over it?
bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
- const LLUIColor& color, const std::string &menu,
- const std::string &location, bool disabled_link
- , const LLUUID& id, bool underline_on_hover_only = false );
-
- const LLUUID& getID() const { return mID;}
+ const LLStyle::Params& style, const std::string &menu,
+ const std::string &location, const LLUUID& id,
+ bool underline_on_hover_only = false );
+ const LLUUID& getID() const { return mID; }
private:
U32 mStart;
U32 mEnd;
@@ -101,10 +97,8 @@ private:
std::string mIcon;
std::string mMenuName;
std::string mLocation;
-
LLUUID mID;
- LLUIColor mColor;
- bool mDisabledLink;
+ LLStyle::Params mStyle;
bool mUnderlineOnHoverOnly;
};
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 9d215cf7ef..478b412d5e 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -31,18 +31,25 @@
#include <boost/regex.hpp>
// default dummy callback that ignores any label updates from the server
-void LLUrlRegistryNullCallback(const std::string &url, const std::string &label)
+void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon)
{
}
LLUrlRegistry::LLUrlRegistry()
{
+ mUrlEntry.reserve(20);
+
// Urls are matched in the order that they were registered
registerUrl(new LLUrlEntryNoLink());
registerUrl(new LLUrlEntryIcon());
registerUrl(new LLUrlEntrySLURL());
registerUrl(new LLUrlEntryHTTP());
registerUrl(new LLUrlEntryHTTPLabel());
+ registerUrl(new LLUrlEntryAgentCompleteName());
+ registerUrl(new LLUrlEntryAgentDisplayName());
+ registerUrl(new LLUrlEntryAgentUserName());
+ // LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since
+ // LLUrlEntryAgent is a less specific (catchall for agent urls)
registerUrl(new LLUrlEntryAgent());
registerUrl(new LLUrlEntryGroup());
registerUrl(new LLUrlEntryParcel());
@@ -71,10 +78,13 @@ LLUrlRegistry::~LLUrlRegistry()
}
}
-void LLUrlRegistry::registerUrl(LLUrlEntryBase *url)
+void LLUrlRegistry::registerUrl(LLUrlEntryBase *url, bool force_front)
{
if (url)
{
+ if (force_front) // IDEVO
+ mUrlEntry.insert(mUrlEntry.begin(), url);
+ else
mUrlEntry.push_back(url);
}
}
@@ -174,10 +184,9 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getLabel(url, cb),
match_entry->getTooltip(url),
match_entry->getIcon(url),
- match_entry->getColor(),
+ match_entry->getStyle(),
match_entry->getMenuName(),
match_entry->getLocation(url),
- match_entry->isLinkDisabled(),
match_entry->getID(url),
match_entry->underlineOnHoverOnly(url));
return true;
@@ -210,10 +219,9 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
match.getLabel(),
match.getTooltip(),
match.getIcon(),
- match.getColor(),
+ match.getStyle(),
match.getMenuName(),
match.getLocation(),
- match.isLinkDisabled(),
match.getID(),
match.underlineOnHoverOnly());
return true;
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index 24ce516c43..da16171a97 100644
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -37,7 +37,9 @@
#include <vector>
/// This default callback for findUrl() simply ignores any label updates
-void LLUrlRegistryNullCallback(const std::string &url, const std::string &label);
+void LLUrlRegistryNullCallback(const std::string &url,
+ const std::string &label,
+ const std::string &icon);
///
/// LLUrlRegistry is a singleton that contains a set of Url types that
@@ -64,7 +66,9 @@ public:
~LLUrlRegistry();
/// add a new Url handler to the registry (will be freed on destruction)
- void registerUrl(LLUrlEntryBase *url);
+ /// optionally force it to the front of the list, making it take
+ /// priority over other regular expression matches for URLs
+ void registerUrl(LLUrlEntryBase *url, bool force_front = false);
/// get the next Url in an input string, starting at a given character offset
/// your callback is invoked if the matched Url's label changes in the future
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index fe5ef269a9..3fa86bf0ca 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -102,11 +102,7 @@ LLView::Params::Params()
left_pad("left_pad"),
left_delta("left_delta", S32_MAX),
from_xui("from_xui", false),
- user_resize("user_resize"),
- auto_resize("auto_resize"),
needs_translate("translate"),
- min_width("min_width"),
- max_width("max_width"),
xmlns("xmlns"),
xmlns_xsi("xmlns:xsi"),
xsi_schemaLocation("xsi:schemaLocation"),
@@ -218,7 +214,7 @@ void LLView::setUseBoundingRect( BOOL use_bounding_rect )
}
}
-BOOL LLView::getUseBoundingRect()
+BOOL LLView::getUseBoundingRect() const
{
return mUseBoundingRect;
}
@@ -1370,12 +1366,12 @@ void LLView::drawDebugRect()
// drawing solids requires texturing be disabled
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- if (mUseBoundingRect)
+ if (getUseBoundingRect())
{
LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom, 0.f);
}
- LLRect debug_rect = mUseBoundingRect ? mBoundingRect : mRect;
+ LLRect debug_rect = getUseBoundingRect() ? mBoundingRect : mRect;
// draw red rectangle for the border
LLColor4 border_color(0.25f, 0.25f, 0.25f, 1.f);
@@ -1573,7 +1569,7 @@ void LLView::updateBoundingRect()
LLRect cur_rect = mBoundingRect;
- if (mUseBoundingRect)
+ if (getUseBoundingRect())
{
mBoundingRect = calcBoundingRect();
}
@@ -1583,7 +1579,7 @@ void LLView::updateBoundingRect()
}
// give parent view a chance to resize, in case we just moved, for example
- if (getParent() && getParent()->mUseBoundingRect)
+ if (getParent() && getParent()->getUseBoundingRect())
{
getParent()->updateBoundingRect();
}
@@ -1607,7 +1603,7 @@ LLRect LLView::calcScreenBoundingRect() const
{
LLRect screen_rect;
// get bounding rect, if used
- LLRect bounding_rect = mUseBoundingRect ? mBoundingRect : mRect;
+ LLRect bounding_rect = getUseBoundingRect() ? mBoundingRect : mRect;
// convert to local coordinates, as defined by mRect
bounding_rect.translate(-mRect.mLeft, -mRect.mBottom);
@@ -1692,7 +1688,9 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse) const
child = getDefaultWidget<LLView>(name);
if (!child)
{
- child = LLUICtrlFactory::createDefaultWidget<LLView>(name);
+ LLView::Params view_params;
+ view_params.name = name;
+ child = LLUICtrlFactory::create<LLView>(view_params);
}
}
return child;
@@ -1736,14 +1734,14 @@ LLView* LLView::findChildView(const std::string& name, BOOL recurse) const
BOOL LLView::parentPointInView(S32 x, S32 y, EHitTestType type) const
{
- return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT)
+ return (getUseBoundingRect() && type == HIT_TEST_USE_BOUNDING_RECT)
? mBoundingRect.pointInRect( x, y )
: mRect.pointInRect( x, y );
}
BOOL LLView::pointInView(S32 x, S32 y, EHitTestType type) const
{
- return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT)
+ return (getUseBoundingRect() && type == HIT_TEST_USE_BOUNDING_RECT)
? mBoundingRect.pointInRect( x + mRect.mLeft, y + mRect.mBottom )
: mRect.localPointInRect( x, y );
}
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 6d79415c26..33d345beff 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -128,26 +128,22 @@ public:
Optional<std::string> layout;
Optional<LLRect> rect;
+
// Historical bottom-left layout used bottom_delta and left_delta
// for relative positioning. New layout "topleft" prefers specifying
// based on top edge.
- Optional<S32> bottom_delta, // deprecated
- top_pad, // from last bottom to my top
- top_delta, // from last top to my top
- left_pad, // from last right to my left
- left_delta; // from last left to my left
-
- // these are nested attributes for LLLayoutPanel
+ Optional<S32> bottom_delta, // from last bottom to my bottom
+ top_pad, // from last bottom to my top
+ top_delta, // from last top to my top
+ left_pad, // from last right to my left
+ left_delta; // from last left to my left
+
//FIXME: get parent context involved in parsing traversal
- Ignored user_resize,
- auto_resize,
- needs_translate,
- min_width,
- max_width,
- xmlns,
- xmlns_xsi,
- xsi_schemaLocation,
- xsi_type;
+ Ignored needs_translate, // cue for translation tools
+ xmlns, // xml namespace
+ xmlns_xsi, // xml namespace
+ xsi_schemaLocation, // xml schema
+ xsi_type; // xml schema type
Params();
};
@@ -238,7 +234,7 @@ public:
void setSoundFlags(U8 flags) { mSoundFlags = flags; }
void setName(std::string name) { mName = name; }
void setUseBoundingRect( BOOL use_bounding_rect );
- BOOL getUseBoundingRect();
+ BOOL getUseBoundingRect() const;
ECursorType getHoverCursor() { return mHoverCursor; }
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index ff53ae5624..f30704cb22 100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -27,11 +27,28 @@
#include "llstring.h"
#include "llfile.h"
+#include "llavatarnamecache.h"
#include "llcachename.h"
#include "lluuid.h"
#include <string>
+// Stub for LLAvatarNameCache
+bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
+{
+ return false;
+}
+
+void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
+{
+ return;
+}
+
+bool LLAvatarNameCache::useDisplayNames()
+{
+ return false;
+}
+
//
// Stub implementation for LLCacheName
//
@@ -47,7 +64,12 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
return TRUE;
}
-boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
+{
+ return boost::signals2::connection();
+}
+
+boost::signals2::connection LLCacheName::getGroup(const LLUUID& id, const LLCacheNameCallback& callback)
{
return boost::signals2::connection();
}
@@ -67,3 +89,105 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::
{
return std::string();
}
+
+//
+// Stub implementation for LLStyle::Params::Params
+//
+
+LLStyle::Params::Params()
+{
+}
+
+//
+// Stub implementations for various LLInitParam classes
+//
+
+namespace LLInitParam
+{
+ BaseBlock::BaseBlock() {}
+ BaseBlock::~BaseBlock() {}
+ Param::Param(BaseBlock* enclosing_block)
+ : mIsProvided(false)
+ {
+ const U8* my_addr = reinterpret_cast<const U8*>(this);
+ const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+ mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ }
+ void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {}
+
+ void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){}
+ param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
+
+ void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+ {
+ descriptor.mCurrentBlockPtr = this;
+ }
+ bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; }
+ bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; }
+ bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; }
+ bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
+ bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
+
+ TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count)
+ {}
+
+ void TypedParam<LLUIColor>::setValueFromBlock() const
+ {}
+
+ void TypedParam<LLUIColor>::setBlockFromValue()
+ {}
+
+ void TypeValues<LLUIColor>::declareValues()
+ {}
+
+ bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
+ {
+ return false;
+ }
+
+ TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, _name, value, func, min_count, max_count)
+ {}
+
+ void TypedParam<const LLFontGL*>::setValueFromBlock() const
+ {}
+
+ void TypedParam<const LLFontGL*>::setBlockFromValue()
+ {}
+
+ void TypeValues<LLFontGL::HAlign>::declareValues()
+ {}
+
+ void TypeValues<LLFontGL::VAlign>::declareValues()
+ {}
+
+ void TypeValues<LLFontGL::ShadowType>::declareValues()
+ {}
+
+ void TypedParam<LLUIImage*>::setValueFromBlock() const
+ {}
+
+ void TypedParam<LLUIImage*>::setBlockFromValue()
+ {}
+
+
+ bool ParamCompare<LLUIImage*, false>::equals(
+ LLUIImage* const &a,
+ LLUIImage* const &b)
+ {
+ return false;
+ }
+
+ bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
+ {
+ return false;
+ }
+
+}
+
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+ return NULL;
+}
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 95affe4460..5c6623da61 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -30,6 +30,7 @@
#include "llurlentry_stub.cpp"
#include "lltut.h"
#include "../lluicolortable.h"
+#include "../lluiimage.h"
#include <boost/regex.hpp>
@@ -40,6 +41,26 @@ LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& defa
LLUIColor::LLUIColor() : mColorPtr(NULL) {}
+LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
+{
+}
+
+LLUIImage::~LLUIImage()
+{
+}
+
+//virtual
+S32 LLUIImage::getWidth() const
+{
+ return 0;
+}
+
+//virtual
+S32 LLUIImage::getHeight() const
+{
+ return 0;
+}
+
namespace tut
{
struct LLUrlEntryData
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index 4e38bea1bd..fdaab00f18 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -25,14 +25,135 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "../llurlmatch.h"
+#include "../lluiimage.h"
#include "lltut.h"
-// link seam
+// link seams
+
LLUIColor::LLUIColor()
: mColorPtr(NULL)
{}
+LLStyle::Params::Params()
+{
+}
+
+LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
+{
+}
+
+LLUIImage::~LLUIImage()
+{
+}
+
+//virtual
+S32 LLUIImage::getWidth() const
+{
+ return 0;
+}
+
+//virtual
+S32 LLUIImage::getHeight() const
+{
+ return 0;
+}
+
+namespace LLInitParam
+{
+ BaseBlock::BaseBlock() {}
+ BaseBlock::~BaseBlock() {}
+
+ void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {}
+
+ void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){}
+ param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
+
+ void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+ {
+ descriptor.mCurrentBlockPtr = this;
+ }
+
+ Param::Param(BaseBlock* enclosing_block)
+ : mIsProvided(false)
+ {
+ const U8* my_addr = reinterpret_cast<const U8*>(this);
+ const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+ mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ }
+
+ bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; }
+ bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; }
+ bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; }
+ bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
+ bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
+
+ TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count)
+ {}
+
+ void TypedParam<LLUIColor>::setValueFromBlock() const
+ {}
+
+ void TypedParam<LLUIColor>::setBlockFromValue()
+ {}
+
+ void TypeValues<LLUIColor>::declareValues()
+ {}
+
+ bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
+ {
+ return false;
+ }
+
+ TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, _name, value, func, min_count, max_count)
+ {}
+
+ void TypedParam<const LLFontGL*>::setValueFromBlock() const
+ {}
+
+ void TypedParam<const LLFontGL*>::setBlockFromValue()
+ {}
+
+ void TypeValues<LLFontGL::HAlign>::declareValues()
+ {}
+
+ void TypeValues<LLFontGL::VAlign>::declareValues()
+ {}
+
+ void TypeValues<LLFontGL::ShadowType>::declareValues()
+ {}
+
+ void TypedParam<LLUIImage*>::setValueFromBlock() const
+ {}
+
+ void TypedParam<LLUIImage*>::setBlockFromValue()
+ {}
+
+ bool ParamCompare<LLUIImage*, false>::equals(
+ LLUIImage* const &a,
+ LLUIImage* const &b)
+ {
+ return false;
+ }
+
+ bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
+ {
+ return false;
+ }
+
+}
+
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+ return NULL;
+}
+
+
namespace tut
{
struct LLUrlMatchData
@@ -59,7 +180,7 @@ namespace tut
LLUrlMatch match;
ensure("empty()", match.empty());
- match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("! empty()", ! match.empty());
}
@@ -72,7 +193,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getStart() == 0", match.getStart(), 0);
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getStart() == 10", match.getStart(), 10);
}
@@ -85,7 +206,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getEnd() == 0", match.getEnd(), 0);
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getEnd() == 20", match.getEnd(), 20);
}
@@ -98,10 +219,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getUrl() == ''", match.getUrl(), "");
- match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "http://slurl.com/", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
}
@@ -114,10 +235,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getLabel() == ''", match.getLabel(), "");
- match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "Label", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
}
@@ -130,10 +251,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getTooltip() == ''", match.getTooltip(), "");
- match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "Info", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
}
@@ -146,10 +267,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getIcon() == ''", match.getIcon(), "");
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
}
@@ -162,10 +283,10 @@ namespace tut
LLUrlMatch match;
ensure("getMenuName() empty", match.getMenuName().empty());
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "xui_file.xml", "", LLUUID::null);
ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("getMenuName() empty (2)", match.getMenuName().empty());
}
@@ -178,10 +299,10 @@ namespace tut
LLUrlMatch match;
ensure("getLocation() empty", match.getLocation().empty());
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "xui_file.xml", "Paris", LLUUID::null);
ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("getLocation() empty (2)", match.getLocation().empty());
}
}