diff options
Diffstat (limited to 'indra/llui')
27 files changed, 721 insertions, 804 deletions
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index c3ef734823..5ce52185e3 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -89,7 +89,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.h b/indra/llui/llaccordionctrltab.h index 00fb276f19..f87534fa76 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -91,10 +91,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(); }; @@ -176,7 +176,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/llfloater.cpp b/indra/llui/llfloater.cpp index 838f93d3f9..e7d0950846 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -42,6 +42,7 @@ #include "lluictrlfactory.h" #include "llbutton.h" #include "llcheckboxctrl.h" +#include "lldir.h" #include "lldraghandle.h" #include "llfloaterreg.h" #include "llfocusmgr.h" @@ -2779,7 +2780,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) { @@ -2787,8 +2789,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 @@ -2883,3 +2884,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 e7d365238b..750cf23c7d 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -147,6 +147,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); void initFromParams(const LLFloater::Params& p); bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 85f9af126c..39a67ee57b 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -127,7 +127,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 4512091371..309f710cbb 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -41,95 +41,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 +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) { - 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), - mCollapsed(FALSE), - mCollapseAmt(0.f), - mVisibleAmt(1.f), // default to fully visible - mResizeBar(NULL) + // panels initialized as hidden should not start out partially visible + if (!getVisible()) { - LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; - LLRect resize_bar_rect = panelp->getRect(); - - S32 min_dim; - if (orientation == HORIZONTAL) - { - min_dim = mMinHeight; - } - 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; - } + mVisibleAmt = 0.f; } +} - ~LayoutPanel() - { - // probably not necessary, but... - delete mResizeBar; - mResizeBar = NULL; - } +void LLLayoutPanel::initFromParams(const Params& p) +{ + LLPanel::initFromParams(p); + setFollowsNone(); +} + + +LLLayoutPanel::~LLLayoutPanel() +{ + // probably not necessary, but... + delete mResizeBar; + mResizeBar = NULL; +} - F32 getCollapseFactor() +F32 LLLayoutPanel::getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation) +{ + if (orientation == LLLayoutStack::HORIZONTAL) { - if (mOrientation == HORIZONTAL) - { - F32 collapse_amt = - clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth())); - return mVisibleAmt * collapse_amt; - } - else + F32 collapse_amt = + 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()))); - return mVisibleAmt * collapse_amt; - } + F32 collapse_amt = + 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)) @@ -163,18 +134,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 @@ -185,7 +156,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) { @@ -206,149 +177,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 LLLayoutStack::addChild(LLView* child, S32 tab_group) { - BOOL has_attr = node->getAttributeBOOL(name, *value); - if (has_attr && *value != default_value && output_child) + LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child); + if (panelp) { - LLXMLNodePtr child_attr = output_child->createChild(name, TRUE); - child_attr->setBoolValue(*value); + mPanels.push_back(panelp); } + return LLView::addChild(child, tab_group); } -//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) - { - 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); - if (panelp) - { - panelp->setFollowsNone(); - layout_stackp->addPanel(panelp, min_width, min_height, max_width, max_height, auto_resize, user_resize); - } - } - 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) { @@ -374,34 +212,14 @@ S32 LLLayoutStack::getDefaultWidth(S32 cur_width) return cur_width; } -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); - - // 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); - } + addChild(panel); - // start expanding panel animation + // panel starts off invisible (collapsed) if (animate == ANIMATE) { + panel->mVisibleAmt = 0.f; panel->setVisible(TRUE); } } @@ -413,7 +231,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; @@ -421,7 +239,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) { @@ -431,7 +249,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) { @@ -439,27 +257,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; @@ -471,6 +287,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; @@ -482,7 +299,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) @@ -532,11 +349,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()) { @@ -546,11 +363,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; @@ -564,7 +381,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; } @@ -577,11 +394,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 @@ -589,13 +406,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; } } } @@ -618,17 +435,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()) { @@ -639,8 +464,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 { @@ -649,7 +474,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 { @@ -662,8 +487,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 { @@ -671,7 +496,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 { @@ -712,11 +537,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; } } @@ -724,19 +549,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 @@ -772,14 +597,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; } @@ -787,15 +612,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; @@ -816,9 +641,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; @@ -826,9 +649,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; @@ -837,6 +658,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 e454454fe2..4316d9bc46 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -34,16 +34,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; @@ -51,6 +56,8 @@ public: Params(); }; + typedef LayoutStackRegistry child_registry_t; + typedef enum e_layout_orientation { HORIZONTAL, @@ -62,6 +69,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); @@ -74,7 +82,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(); } @@ -83,20 +91,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); @@ -111,19 +117,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 @@ -135,4 +140,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 c93ca1af88..e6a07b02cc 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1277,7 +1277,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) if( mCurrentHistoryLine > mLineHistory.begin() ) { mText.assign( *(--mCurrentHistoryLine) ); - setCursor(llmin((S32)mText.length(), getCursor())); + setCursorToEnd(); } else { @@ -1294,7 +1294,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/llmenugl.cpp b/indra/llui/llmenugl.cpp index 46a7215707..b4d1a5726f 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -9,7 +9,7 @@ * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement + * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 7fa3c2cf65..7cc6e8e8f6 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1423,6 +1423,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); diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 1cdd744a68..fcf988222d 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -900,6 +900,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); diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 0f769bd6dc..4471f315c0 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -41,6 +41,7 @@ #include "llfontgl.h" #include "llrect.h" #include "llerror.h" +#include "lldir.h" #include "lltimer.h" #include "llaccordionctrltab.h" @@ -58,6 +59,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>( @@ -386,8 +389,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()) { @@ -400,7 +402,7 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_ if (!panelp) { - panelp = LLUICtrlFactory::getInstance()->createFactoryPanel(name); + panelp = createFactoryPanel(name); llassert(panelp); if (!panelp) @@ -413,20 +415,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; @@ -493,11 +495,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); @@ -511,6 +511,8 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu setXMLFilename(xml_filename); } + LLXUIParser parser; + if (!xml_filename.empty()) { LLUICtrlFactory::instance().pushFileName(xml_filename); @@ -520,12 +522,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; } @@ -536,7 +537,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); @@ -546,15 +547,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; @@ -965,3 +965,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 784054cd86..cacd1fdcf0 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -110,7 +110,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 @@ -163,7 +166,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; @@ -262,6 +265,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? @@ -291,4 +296,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/llrngwriter.cpp b/indra/llui/llrngwriter.cpp index 7e3d4b92d3..718c10d2f8 100644 --- a/indra/llui/llrngwriter.cpp +++ b/indra/llui/llrngwriter.cpp @@ -36,10 +36,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 bb43c19c2c..844278e41c 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -543,23 +543,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(); @@ -2584,7 +2568,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); } @@ -2770,23 +2755,27 @@ 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()); diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 4bb45a3065..69976004e6 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -36,48 +36,40 @@ // Project includes #include "llsdparam.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<F32>); + 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.mWriteSD) 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)); @@ -148,3 +140,82 @@ LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack) return mWriteSD; } +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 12f28f876f..c42358178a 100644 --- a/indra/llui/llsdparam.h +++ b/indra/llui/llsdparam.h @@ -37,17 +37,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); @@ -57,20 +54,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.mWriteSD) 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)); @@ -79,8 +68,18 @@ 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; @@ -94,7 +93,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/lltextbase.h b/indra/llui/lltextbase.h index db010d1cf6..2314ece6df 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -241,6 +241,7 @@ class LLTextBase public: friend class LLTextSegment; friend class LLNormalTextSegment; + friend class LLUICtrlFactory; struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams> { diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 025725476e..b3699c738e 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -84,9 +84,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(); } @@ -586,6 +586,7 @@ void LLToolTipMgr::updateToolTipVisibility() if (mToolTip->getVisibleTime() > tooltip_timeout) { hideToolTips(); + unblockToolTips(); } } } diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 5d8b628776..85fdfbb312 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1802,7 +1802,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(); diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index 1b64ef3abe..88140f1a49 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -243,7 +243,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()) { @@ -309,7 +310,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 a46d961709..2a2fa21ec0 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -48,7 +48,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"); @@ -99,10 +99,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(); } } @@ -177,70 +179,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() //----------------------------------------------------------------------------- @@ -249,69 +187,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; -} - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -343,29 +218,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(); @@ -382,36 +234,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) { @@ -427,28 +249,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); @@ -468,17 +284,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 dc43b311a7..6b5d055b78 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -33,24 +33,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 { @@ -91,12 +80,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)(); @@ -163,58 +146,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(); @@ -272,21 +218,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) { @@ -294,7 +273,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) { @@ -304,14 +284,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; @@ -326,20 +305,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); @@ -349,20 +314,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> @@ -370,7 +325,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 @@ -378,58 +333,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 ac9e71665f..e343df0063 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -40,7 +40,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(); } @@ -54,7 +54,7 @@ void LLUIString::assign(const std::string& s) void LLUIString::setArgList(const LLStringUtil::format_map_t& args) { - mArgs = args; + getArgs() = args; dirty(); } @@ -74,7 +74,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(); } @@ -135,14 +135,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); } } @@ -153,3 +153,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 32cfc0d9cd..3f91856e26 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -64,9 +64,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; } @@ -86,7 +86,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 @@ -105,11 +105,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/llview.cpp b/indra/llui/llview.cpp index 4d3708302b..878def07ae 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -108,11 +108,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"), @@ -1698,7 +1694,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; diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 37f5232f91..fa4f4c8ae2 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -134,26 +134,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(); }; |