From eeefec394c932b79a22c5ea2b8aa03690bb6061e Mon Sep 17 00:00:00 2001 From: Ima Mechanique Date: Wed, 23 Nov 2011 01:30:15 +0000 Subject: Changes to filter out tabs from file load and to test if loading/saving should be allowed. --- indra/llui/lltexteditor.cpp | 26 ++++++++++++++++++++++++++ indra/llui/lltexteditor.h | 5 +++++ 2 files changed, 31 insertions(+) (limited to 'indra/llui') diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 9bd445988d..3a23ce1cac 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2250,6 +2250,22 @@ void LLTextEditor::insertText(const std::string &new_text) setEnabled( enabled ); } +void LLTextEditor::insertText(LLWString &new_text) +{ + BOOL enabled = getEnabled(); + setEnabled( TRUE ); + + // Delete any selected characters (the insertion replaces them) + if( hasSelection() ) + { + deleteSelection(TRUE); + } + + setCursorPos(mCursorPos + insert( mCursorPos, new_text, FALSE, LLTextSegmentPtr() )); + + setEnabled( enabled ); +} + void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo) { // Save old state @@ -2838,3 +2854,13 @@ void LLTextEditor::clear() getViewModel()->setDisplay(LLWStringUtil::null); clearSegments(); } + +bool LLTextEditor::canLoadOrSaveToFile() +{ + return !mReadOnly; +} + +S32 LLTextEditor::spacesPerTab() +{ + return SPACES_PER_TAB; +} diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 9e4b95003b..40821ae9fb 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -92,6 +92,8 @@ public: void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;} + static S32 spacesPerTab(); + // mousehandler overrides virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -140,6 +142,8 @@ public: virtual void selectAll(); virtual BOOL canSelectAll() const; + virtual bool canLoadOrSaveToFile(); + void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE); BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE); void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive); @@ -158,6 +162,7 @@ public: // inserts text at cursor void insertText(const std::string &text); + void insertText(LLWString &text); void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo); // Non-undoable -- cgit v1.3 From e860925818fe9376fa9abb0520680dba986ab42e Mon Sep 17 00:00:00 2001 From: Leslie Linden Date: Wed, 7 Dec 2011 15:03:45 -0800 Subject: Crash workaround when opening toats windows after a long session. --- indra/llui/llview.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/llui') diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 486babb0ab..d2966fbe98 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1090,6 +1090,11 @@ void LLView::drawChildren() { child_list_reverse_iter_t child = child_iter++; LLView *viewp = *child; + + if (viewp == NULL) + { + continue; + } if (viewp->getVisible() && viewp->getRect().isValid()) { -- cgit v1.3 From 0aa2c7343ac2af195e80c8f52b9ef67da785fa00 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 8 Dec 2011 20:36:47 -0800 Subject: EXP-1512 FIX changing UI size changes cursor position in notecards --- indra/llui/lltextbase.cpp | 31 ++++++++++++++++++++++++++++++- indra/llui/lltextbase.h | 2 ++ 2 files changed, 32 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3b768166f1..1f890b625f 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -598,7 +598,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s pos = getEditableIndex(pos, true); - segment_set_t::iterator seg_iter = getSegIterContaining(pos); + segment_set_t::iterator seg_iter = getEditableSegIterContaining(pos); LLTextSegmentPtr default_segment; @@ -1510,8 +1510,37 @@ void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg } } +LLTextBase::segment_set_t::iterator LLTextBase::getEditableSegIterContaining(S32 index) +{ + segment_set_t::iterator it = getSegIterContaining(index); + if (it == mSegments.end()) return it; + + if (!(*it)->canEdit() + && index == (*it)->getStart() + && it != mSegments.begin()) + { + it--; + } + return it; +} + +LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaining(S32 index) const +{ + segment_set_t::const_iterator it = getSegIterContaining(index); + if (it == mSegments.end()) return it; + + if (!(*it)->canEdit() + && index == (*it)->getStart() + && it != mSegments.begin()) + { + it--; + } + return it; +} + LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index) { + static LLPointer index_segment = new LLIndexSegment(); if (index > getLength()) { return mSegments.end(); } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index b699601908..0549141b72 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -461,6 +461,8 @@ protected: void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const; void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp ); LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true); + segment_set_t::iterator getEditableSegIterContaining(S32 index); + segment_set_t::const_iterator getEditableSegIterContaining(S32 index) const; segment_set_t::iterator getSegIterContaining(S32 index); segment_set_t::const_iterator getSegIterContaining(S32 index) const; void clearSegments(); -- cgit v1.3 From cc92db1f353de96f6d27863b92671b2d847536f4 Mon Sep 17 00:00:00 2001 From: Leslie Linden Date: Fri, 9 Dec 2011 16:19:03 -0800 Subject: Moved outbox import confirmations to window shades on the merchant outbox floater, rather than modal dialogs. --- indra/llui/llwindowshade.cpp | 5 ++ indra/llui/llwindowshade.h | 2 + indra/newview/llfloateroutbox.cpp | 61 +++++++++++++++++++++- indra/newview/llfloateroutbox.h | 8 +++ indra/newview/llnotificationhandler.h | 10 +++- indra/newview/llnotificationmanager.cpp | 2 + indra/newview/skins/default/textures/textures.xml | 19 ++----- .../newview/skins/default/xui/en/notifications.xml | 35 ++++++++----- 8 files changed, 112 insertions(+), 30 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index cf76202215..b21c088a1f 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -297,6 +297,11 @@ void LLWindowShade::hide() setMouseOpaque(false); } +bool LLWindowShade::isShown() const +{ + return getChildRef("notification_area").getVisible(); +} + void LLWindowShade::onCloseNotification() { LLNotifications::instance().cancel(mNotification); diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h index 09ffc2cd54..cb8f223a84 100644 --- a/indra/llui/llwindowshade.h +++ b/indra/llui/llwindowshade.h @@ -48,6 +48,8 @@ public: void show(); /*virtual*/ void draw(); void hide(); + + bool isShown() const; private: friend class LLUICtrlFactory; diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 619be87187..8d64214e8c 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -33,11 +33,32 @@ #include "llinventoryobserver.h" #include "llinventorypanel.h" #include "llmarketplacefunctions.h" +#include "llnotificationhandler.h" #include "llnotificationsutil.h" #include "lltextbox.h" #include "lltransientfloatermgr.h" #include "lltrans.h" #include "llviewernetwork.h" +#include "llwindowshade.h" + + +///---------------------------------------------------------------------------- +/// LLOutboxNotification class +///---------------------------------------------------------------------------- + +bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify) +{ + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); + + if (notification) + { + LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance("outbox"); + + outbox_floater->showNotification(notification); + } + + return false; +} ///---------------------------------------------------------------------------- @@ -89,6 +110,7 @@ LLFloaterOutbox::LLFloaterOutbox(const LLSD& key) , mInventoryText(NULL) , mInventoryTitle(NULL) , mImportButton(NULL) + , mWindowShade(NULL) { } @@ -121,6 +143,16 @@ BOOL LLFloaterOutbox::postBuild() return TRUE; } +void LLFloaterOutbox::onClose(bool app_quitting) +{ + if (mWindowShade) + { + delete mWindowShade; + + mWindowShade = NULL; + } +} + void LLFloaterOutbox::onOpen(const LLSD& key) { // @@ -275,7 +307,8 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, { // Pass drag and drop to this floater to the outbox inventory control - if (LLMarketplaceInventoryImporter::getInstance()->isImportInProgress()) + if (LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() || + (mWindowShade && mWindowShade->isShown())) { return FALSE; } @@ -369,3 +402,29 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress) } } +void LLFloaterOutbox::showNotification(LLNotificationPtr notify) +{ + if (mWindowShade) + { + delete mWindowShade; + } + + LLRect floater_rect = getLocalRect(); + floater_rect.mTop -= getHeaderHeight(); + floater_rect.stretch(-5, 0); + + LLWindowShade::Params params; + params.name = "notification_shade"; + params.rect = floater_rect; + params.follows.flags = FOLLOWS_ALL; + params.notification = notify; + params.modal = true; + params.can_close = false; + params.text_color = LLColor4::white; + + mWindowShade = LLUICtrlFactory::create(params); + + addChild(mWindowShade); + mWindowShade->show(); +} + diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 3d2ce86144..8023434675 100644 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -30,6 +30,7 @@ #include "llfloater.h" #include "llfoldertype.h" +#include "llnotificationptr.h" class LLButton; @@ -37,8 +38,10 @@ class LLInventoryCategoriesObserver; class LLInventoryCategoryAddedObserver; class LLInventoryPanel; class LLLoadingIndicator; +class LLNotification; class LLTextBox; class LLView; +class LLWindowShade; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -55,12 +58,15 @@ public: // virtuals BOOL postBuild(); + void onClose(bool app_quitting); void onOpen(const LLSD& key); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); + + void showNotification(LLNotificationPtr notify); protected: void importReportResults(U32 status, const LLSD& content); @@ -86,6 +92,8 @@ private: LLTextBox * mInventoryTitle; LLButton * mImportButton; + + LLWindowShade * mWindowShade; }; #endif // LL_LLFLOATEROUTBOX_H diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 28a69f2373..23dbb6b047 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -283,9 +283,17 @@ class LLBrowserNotification : public LLSingleton { public: virtual bool processNotification(const LLSD& notify); +}; +/** + * Handler for outbox notifications + */ +class LLOutboxNotification : public LLSingleton +{ +public: + virtual bool processNotification(const LLSD& notify); }; - + class LLHandlerUtil { public: diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 6988227128..6105eff8ea 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -62,6 +62,7 @@ void LLNotificationManager::init() LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "offer")); LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "hint")); LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "browser")); + LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy(&LLNotification::getType, "outbox")); LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); @@ -72,6 +73,7 @@ void LLNotificationManager::init() LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); + LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); mNotifyHandlers["notify"] = boost::shared_ptr(new LLScriptHandler(NT_NOTIFY, LLSD())); mNotifyHandlers["notifytip"] = boost::shared_ptr(new LLTipHandler(NT_NOTIFY, LLSD())); diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 5da1276881..e4a8622a4b 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -387,22 +387,9 @@ with the same filename but different name - - - - - - - - - - - - - - - - + + + diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 8d0d76b58e..b174d51421 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -212,33 +212,44 @@ Save changes to current clothing/body part? -Marketplace import complete. + type="outbox"> +Success + +All folders were successfully sent to the Marketplace. + + yestext="OK"/> -Marketplace import completed with errors! Please correct the problems in your outbox and retry. Thanks. + type="outbox"> +Some folders did not transfer + +Errors occurred when some folders were sent to the Marketplace. Those folders are still in your Merchant Outbox. See the error log for more information. + + yestext="OK"/> -Marketplace import failed with error [ERROR_CODE]! Please try again later. Thanks. + type="outbox"> +Transfer failed + +No folders were sent to the Marketplace because of a system or network error. Try again later. + +Error [ERROR_CODE] + + yestext="OK"/> -- cgit v1.3 From 40a74eb5b77493e66587a01b6655d405c75e3a59 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 12 Dec 2011 12:32:22 -0800 Subject: EXP-1711 FIX LLWindowShade doesn't stack multiple notifications --- indra/llui/lllayoutstack.h | 3 +- indra/llui/llpanel.h | 2 + indra/llui/llwindowshade.cpp | 207 ++++++++++++++++++----------- indra/llui/llwindowshade.h | 10 +- indra/newview/llmediactrl.cpp | 46 +++---- indra/newview/llpanelprimmediacontrols.cpp | 3 +- 6 files changed, 163 insertions(+), 108 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index ede6149a80..3b308a359d 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -191,13 +191,12 @@ public: return min_dim; } + F32 getCollapseFactor(); void setOrientation(LLLayoutStack::ELayoutOrientation orientation) { mOrientation = orientation; } protected: LLLayoutPanel(const Params& p); - F32 getCollapseFactor(); - bool mExpandedMinDimSpecified; S32 mExpandedMinDim; diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index cd33938226..f620201020 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -135,6 +135,8 @@ public: const LLColor4& getBackgroundColor() const { return mBgOpaqueColor; } void setTransparentColor(const LLColor4& color) { mBgAlphaColor = color; } const LLColor4& getTransparentColor() const { return mBgAlphaColor; } + void setBackgroundImage(LLUIImage* image) { mBgOpaqueImage = image; } + void setTransparentImage(LLUIImage* image) { mBgAlphaImage = image; } LLPointer getBackgroundImage() const { return mBgOpaqueImage; } LLPointer getTransparentImage() const { return mBgAlphaImage; } LLColor4 getBackgroundImageOverlay() { return mBgOpaqueImageOverlay; } diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index cf76202215..0b4cfe68a6 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -37,6 +37,8 @@ const S32 MIN_NOTIFICATION_AREA_HEIGHT = 30; const S32 MAX_NOTIFICATION_AREA_HEIGHT = 100; +static LLDefaultChildRegistry::Register r("window_shade"); + LLWindowShade::Params::Params() : bg_image("bg_image"), modal("modal", false), @@ -48,7 +50,6 @@ LLWindowShade::Params::Params() LLWindowShade::LLWindowShade(const LLWindowShade::Params& params) : LLUICtrl(params), - mNotification(params.notification), mModal(params.modal), mFormHeight(0), mTextColor(params.text_color) @@ -72,7 +73,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) addChild(stackp); LLLayoutPanel::Params panel_p; - panel_p.rect = LLRect(0, 30, 800, 0); + panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 800, 0); panel_p.name = "notification_area"; panel_p.visible = false; panel_p.user_resize = false; @@ -107,11 +108,11 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) LLIconCtrl::Params icon_p; icon_p.name = "notification_icon"; - icon_p.rect = LLRect(5, 23, 21, 8); + icon_p.rect = LLRect(5, 25, 21, 10); panel->addChild(LLUICtrlFactory::create(icon_p)); LLTextBox::Params text_p; - text_p.rect = LLRect(31, 20, panel->getRect().getWidth() - 5, 0); + text_p.rect = LLRect(31, 23, panel->getRect().getWidth() - 5, 3); text_p.follows.flags = FOLLOWS_ALL; text_p.text_color = mTextColor; text_p.font = LLFontGL::getFontSansSerifSmall(); @@ -125,41 +126,132 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) panel_p.auto_resize = false; panel_p.user_resize = false; panel_p.name="form_elements"; - panel_p.rect = LLRect(0, 30, 130, 0); + panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 130, 0); LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create(panel_p); stackp->addChild(form_elements_panel); - if (params.can_close) + panel_p = LLUICtrlFactory::getDefaultParams(); + panel_p.auto_resize = false; + panel_p.user_resize = false; + panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 25, 0); + panel_p.name = "close_panel"; + LLLayoutPanel* close_panel = LLUICtrlFactory::create(panel_p); + stackp->addChild(close_panel); + + LLButton::Params button_p; + button_p.name = "close_notification"; + button_p.rect = LLRect(5, 23, 21, 7); + button_p.image_color.control="DkGray_66"; + button_p.image_unselected.name="Icon_Close_Foreground"; + button_p.image_selected.name="Icon_Close_Press"; + button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this); + + close_panel->addChild(LLUICtrlFactory::create(button_p)); + + close_panel->setVisible(params.can_close); +} + +void LLWindowShade::draw() +{ + LLRect message_rect = getChild("notification_text")->getTextBoundingRect(); + + LLLayoutPanel* notification_area = getChild("notification_area"); + + notification_area->reshape(notification_area->getRect().getWidth(), + llclamp(message_rect.getHeight() + 15, + llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT), + MAX_NOTIFICATION_AREA_HEIGHT)); + + LLUICtrl::draw(); + + while(!mNotifications.empty() && !mNotifications.back()->isActive()) + { + mNotifications.pop_back(); + // go ahead and hide + hide(); + } + + if (mNotifications.empty()) + { + hide(); + } + else if (notification_area->getCollapseFactor() < 0.01f) + { + displayLatestNotification(); + } + + if (!notification_area->getVisible() && (notification_area->getCollapseFactor() < 0.001f)) + { + getChildRef("background_area").setBackgroundVisible(false); + setMouseOpaque(false); + } +} + +void LLWindowShade::hide() +{ + getChildRef("notification_area").setVisible(false); +} + +void LLWindowShade::onCloseNotification() +{ + if (!mNotifications.empty()) + LLNotifications::instance().cancel(mNotifications.back()); +} + +void LLWindowShade::onClickIgnore(LLUICtrl* ctrl) +{ + LLNotificationPtr notify = getCurrentNotification(); + if (!notify) return; + + bool check = ctrl->getValue().asBoolean(); + if (notify->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN) { - panel_p = LLUICtrlFactory::getDefaultParams(); - panel_p.auto_resize = false; - panel_p.user_resize = false; - panel_p.rect = LLRect(0, 30, 25, 0); - LLLayoutPanel* close_panel = LLUICtrlFactory::create(panel_p); - stackp->addChild(close_panel); - - LLButton::Params button_p; - button_p.name = "close_notification"; - button_p.rect = LLRect(5, 23, 21, 7); - button_p.image_color.control="DkGray_66"; - button_p.image_unselected.name="Icon_Close_Foreground"; - button_p.image_selected.name="Icon_Close_Press"; - button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this); - - close_panel->addChild(LLUICtrlFactory::create(button_p)); + // question was "show again" so invert value to get "ignore" + check = !check; } + notify->setIgnored(check); +} + +void LLWindowShade::onClickNotificationButton(const std::string& name) +{ + LLNotificationPtr notify = getCurrentNotification(); + if (!notify) return; - LLSD payload = mNotification->getPayload(); + mNotificationResponse[name] = true; - LLNotificationFormPtr formp = mNotification->getForm(); + notify->respond(mNotificationResponse); +} + +void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name) +{ + mNotificationResponse[name] = ctrl->getValue().asString(); +} + +void LLWindowShade::show(LLNotificationPtr notification) +{ + mNotifications.push_back(notification); + + displayLatestNotification(); +} + +void LLWindowShade::displayLatestNotification() +{ + if (mNotifications.empty()) return; + + LLNotificationPtr notification = mNotifications.back(); + + LLSD payload = notification->getPayload(); + + LLNotificationFormPtr formp = notification->getForm(); LLLayoutPanel& notification_area = getChildRef("notification_area"); - notification_area.getChild("notification_icon")->setValue(mNotification->getIcon()); - notification_area.getChild("notification_text")->setValue(mNotification->getMessage()); - notification_area.getChild("notification_text")->setToolTip(mNotification->getMessage()); + notification_area.getChild("notification_icon")->setValue(notification->getIcon()); + notification_area.getChild("notification_text")->setValue(notification->getMessage()); + notification_area.getChild("notification_text")->setToolTip(notification->getMessage()); LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType(); LLLayoutPanel& form_elements = notification_area.getChildRef("form_elements"); form_elements.deleteAllChildren(); + form_elements.reshape(form_elements.getRect().getWidth(), MIN_NOTIFICATION_AREA_HEIGHT); const S32 FORM_PADDING_HORIZONTAL = 10; const S32 FORM_PADDING_VERTICAL = 3; @@ -229,7 +321,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) label_p.v_pad = 5; LLTextBox* textbox = LLUICtrlFactory::create(label_p); textbox->reshapeToFitText(); - textbox->reshape(textbox->getRect().getWidth(), form_elements.getRect().getHeight() - 2 * FORM_PADDING_VERTICAL); + textbox->reshape(textbox->getRect().getWidth(), MIN_NOTIFICATION_AREA_HEIGHT - 2 * FORM_PADDING_VERTICAL); form_elements.addChild(textbox); cur_x = textbox->getRect().mRight + FORM_PADDING_HORIZONTAL; @@ -249,7 +341,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) } } - mFormHeight = form_elements.getRect().getHeight() - (cur_y - FORM_PADDING_VERTICAL) + WIDGET_HEIGHT; + mFormHeight = form_elements.getRect().getHeight() - (cur_y - WIDGET_HEIGHT - FORM_PADDING_VERTICAL); form_elements.reshape(form_width, mFormHeight); form_elements.setMinDim(form_width); @@ -261,68 +353,33 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) { (*it)->translate(0, delta_y); } -} -void LLWindowShade::show() -{ getChildRef("notification_area").setVisible(true); getChildRef("background_area").setBackgroundVisible(mModal); setMouseOpaque(mModal); } -void LLWindowShade::draw() +void LLWindowShade::setBackgroundImage(LLUIImage* image) { - LLRect message_rect = getChild("notification_text")->getTextBoundingRect(); - - LLLayoutPanel* notification_area = getChild("notification_area"); - - notification_area->reshape(notification_area->getRect().getWidth(), - llclamp(message_rect.getHeight() + 10, - llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT), - MAX_NOTIFICATION_AREA_HEIGHT)); - - LLUICtrl::draw(); - if (mNotification && !mNotification->isActive()) - { - hide(); - } + getChild("notification_area")->setTransparentImage(image); } -void LLWindowShade::hide() +void LLWindowShade::setTextColor(LLColor4 color) { - getChildRef("notification_area").setVisible(false); - getChildRef("background_area").setBackgroundVisible(false); - - setMouseOpaque(false); + getChild("notification_text")->setColor(color); } -void LLWindowShade::onCloseNotification() +void LLWindowShade::setCanClose(bool can_close) { - LLNotifications::instance().cancel(mNotification); + getChildView("close_panel")->setVisible(can_close); } -void LLWindowShade::onClickIgnore(LLUICtrl* ctrl) +LLNotificationPtr LLWindowShade::getCurrentNotification() { - bool check = ctrl->getValue().asBoolean(); - if (mNotification && mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN) + if (mNotifications.empty()) { - // question was "show again" so invert value to get "ignore" - check = !check; + return LLNotificationPtr(); } - mNotification->setIgnored(check); -} - -void LLWindowShade::onClickNotificationButton(const std::string& name) -{ - if (!mNotification) return; - - mNotificationResponse[name] = true; - - mNotification->respond(mNotificationResponse); -} - -void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name) -{ - mNotificationResponse[name] = ctrl->getValue().asString(); -} + return mNotifications.back(); +} \ No newline at end of file diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h index 09ffc2cd54..1dcab4e32f 100644 --- a/indra/llui/llwindowshade.h +++ b/indra/llui/llwindowshade.h @@ -36,7 +36,6 @@ class LLWindowShade : public LLUICtrl public: struct Params : public LLInitParam::Block { - Mandatory notification; Optional bg_image; Optional text_color; Optional modal, @@ -45,11 +44,16 @@ public: Params(); }; - void show(); + void show(LLNotificationPtr); /*virtual*/ void draw(); void hide(); + void setBackgroundImage(LLUIImage* image); + void setTextColor(LLColor4 color); + void setCanClose(bool can_close); private: + void displayLatestNotification(); + LLNotificationPtr getCurrentNotification(); friend class LLUICtrlFactory; LLWindowShade(const Params& p); @@ -60,7 +64,7 @@ private: void onEnterNotificationText(LLUICtrl* ctrl, const std::string& name); void onClickIgnore(LLUICtrl* ctrl); - LLNotificationPtr mNotification; + std::vector mNotifications; LLSD mNotificationResponse; bool mModal; S32 mFormHeight; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 74fa5d350a..7650fe9229 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -133,10 +133,15 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : navigateHome(); } - // FIXME: How do we create a bevel now? -// LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 ); -// mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN ); -// addChild( mBorder ); + LLWindowShade::Params params; + params.name = "notification_shade"; + params.rect = getLocalRect(); + params.follows.flags = FOLLOWS_ALL; + params.modal = true; + + mWindowShade = LLUICtrlFactory::create(params); + + addChild(mWindowShade); } LLMediaCtrl::~LLMediaCtrl() @@ -1092,39 +1097,28 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) void LLMediaCtrl::showNotification(LLNotificationPtr notify) { - delete mWindowShade; + LLWindowShade* shade = getChild("notification_shade"); - LLWindowShade::Params params; - params.name = "notification_shade"; - params.rect = getLocalRect(); - params.follows.flags = FOLLOWS_ALL; - params.notification = notify; - params.modal = true; - //HACK: don't hardcode this if (notify->getIcon() == "Popup_Caution") { - params.bg_image.name = "Yellow_Gradient"; - params.text_color = LLColor4::black; + shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient")); + shade->setTextColor(LLColor4::black); + shade->setCanClose(true); } - else - //HACK: another one since XUI doesn't support what we need right now - if (notify->getName() == "AuthRequest") + else if (notify->getName() == "AuthRequest") { - params.bg_image.name = "Yellow_Gradient"; - params.text_color = LLColor4::black; - params.can_close = false; + shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient")); + shade->setTextColor(LLColor4::black); + shade->setCanClose(false); } else { //HACK: make this a property of the notification itself, "cancellable" - params.can_close = false; - params.text_color.control = "LabelTextColor"; + shade->setCanClose(false); + shade->setTextColor(LLUIColorTable::instance().getColor("LabelTextColor")); } - mWindowShade = LLUICtrlFactory::create(params); - - addChild(mWindowShade); - mWindowShade->show(); + mWindowShade->show(notify); } void LLMediaCtrl::hideNotification() diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 933b40ec79..39c0628cbe 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -1351,7 +1351,6 @@ void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify) LLWindowShade::Params params; params.rect = mMediaRegion->getLocalRect(); params.follows.flags = FOLLOWS_ALL; - params.notification = notify; //HACK: don't hardcode this if (notify->getIcon() == "Popup_Caution") @@ -1369,7 +1368,7 @@ void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify) mWindowShade = LLUICtrlFactory::create(params); mMediaRegion->addChild(mWindowShade); - mWindowShade->show(); + mWindowShade->show(notify); } void LLPanelPrimMediaControls::hideNotification() -- cgit v1.3 From 35feb03d27036f82a6bca60c1be8d864de990646 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 12 Dec 2011 15:50:10 -0800 Subject: EXP-1711 FIX LLWindowShade doesn't stack multiple notifications added configurable shade color to window_shade --- indra/llui/llwindowshade.cpp | 3 ++- indra/llui/llwindowshade.h | 3 ++- indra/newview/skins/default/xui/en/widgets/window_shade.xml | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/widgets/window_shade.xml (limited to 'indra/llui') diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index 0b4cfe68a6..1e8b47de29 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -43,6 +43,7 @@ LLWindowShade::Params::Params() : bg_image("bg_image"), modal("modal", false), text_color("text_color"), + shade_color("shade_color"), can_close("can_close", true) { changeDefault(mouse_opaque, false); @@ -90,7 +91,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) panel_p.name = "background_area"; panel_p.mouse_opaque = false; panel_p.background_visible = false; - panel_p.bg_alpha_color = LLColor4(0.f, 0.f, 0.f, 0.2f); + panel_p.bg_alpha_color = params.shade_color; LLLayoutPanel* dummy_panel = LLUICtrlFactory::create(panel_p); stackp->addChild(dummy_panel); diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h index 1dcab4e32f..1ae84028dd 100644 --- a/indra/llui/llwindowshade.h +++ b/indra/llui/llwindowshade.h @@ -37,7 +37,8 @@ public: struct Params : public LLInitParam::Block { Optional bg_image; - Optional text_color; + Optional text_color, + shade_color; Optional modal, can_close; diff --git a/indra/newview/skins/default/xui/en/widgets/window_shade.xml b/indra/newview/skins/default/xui/en/widgets/window_shade.xml new file mode 100644 index 0000000000..23eb2f13fb --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/window_shade.xml @@ -0,0 +1,2 @@ + + -- cgit v1.3 From e859c3446b5c631fe0a9806434aa19b64a0d9113 Mon Sep 17 00:00:00 2001 From: Leslie Linden Date: Mon, 12 Dec 2011 16:06:22 -0800 Subject: Added missing line end to satisfy coding policy --- indra/llui/llwindowshade.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index 1e8b47de29..ae8b30b1ba 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -383,4 +383,5 @@ LLNotificationPtr LLWindowShade::getCurrentNotification() return LLNotificationPtr(); } return mNotifications.back(); -} \ No newline at end of file +} + -- cgit v1.3 From 0c0ff35d19969cc762dce510a4d5ee4649d96a24 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 13 Dec 2011 13:11:55 -0800 Subject: EXP-1551 FIX Ability to toggle button flashing added "EnableButtonFlashing" setting --- indra/llui/llbutton.cpp | 18 +++++++++++++----- indra/llui/lltabcontainer.cpp | 13 +++++++------ indra/newview/app_settings/settings.xml | 11 +++++++++++ 3 files changed, 31 insertions(+), 11 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 93d8282aa7..f0d92d597a 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -589,15 +589,23 @@ void LLButton::getOverlayImageSize(S32& overlay_width, S32& overlay_height) // virtual void LLButton::draw() { + static LLCachedControl sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); bool flash = FALSE; - if( mFlashing ) + if( mFlashing) { - F32 elapsed = mFlashingTimer.getElapsedTimeF32(); - S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); - // flash on or off? - flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); + if ( sEnableButtonFlashing) + { + F32 elapsed = mFlashingTimer.getElapsedTimeF32(); + S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); + // flash on or off? + flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); + } + else + { // otherwise just highlight button in flash color + flash = true; + } } bool pressed_by_keyboard = FALSE; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index d5f8707381..5fc2cc350d 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -98,24 +98,25 @@ class LLCustomButtonIconCtrl : public LLButton { public: struct Params - : public LLInitParam::Block + : public LLInitParam::Block { // LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value Optional icon_ctrl_pad; - Params(): - icon_ctrl_pad("icon_ctrl_pad", 1) + Params() + : icon_ctrl_pad("icon_ctrl_pad", 1) {} }; protected: friend class LLUICtrlFactory; - LLCustomButtonIconCtrl(const Params& p): - LLButton(p), + + LLCustomButtonIconCtrl(const Params& p) + : LLButton(p), mIcon(NULL), mIconAlignment(LLFontGL::HCENTER), mIconCtrlPad(p.icon_ctrl_pad) - {} + {} public: diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index aa8ad53a3d..1ea623791d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1150,6 +1150,17 @@ Value 0 + EnableButtonFlashing + + Comment + Allow UI to flash buttons to get your attention + Persist + 1 + Type + Boolean + Value + 1 + ButtonHPad Comment -- cgit v1.3 From 0ccf2b5a1c08c897326c0ce47caa48e30ec4b5fa Mon Sep 17 00:00:00 2001 From: Seth ProductEngine Date: Wed, 21 Dec 2011 14:10:02 +0200 Subject: EXP-1693 FIXED the date localization in Item Profile window, Voice Morphs window and in scroll list widget in general. - Added a customizable date format string to be used for scroll list cell of "date" type. - The date localization does not change the value of a scroll list cell changing only its string representation. - Added using localized week days and month names from strings.xml for all locales not only Ja and Pl as it was before. - Changed the date format in Item Profile window (French locale) as noted in the issue description. - For this fix the French locale still needs the localization of the following strings in strings.xml: --- indra/llcommon/llstring.cpp | 5 +++++ indra/llui/llscrolllistcell.cpp | 10 +++++++++- indra/newview/llappviewer.cpp | 23 ++++++++-------------- indra/newview/skins/default/xui/en/strings.xml | 3 +++ .../skins/default/xui/fr/sidepanel_item_info.xml | 2 +- 5 files changed, 26 insertions(+), 17 deletions(-) (limited to 'indra/llui') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index e7fe656808..1193a4ef8d 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -1122,6 +1122,11 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, struct tm * gmt = gmtime (&loc_seconds); replacement = LLStringOps::sMonthList[gmt->tm_mon]; } + else if(LLStringOps::sMonthShortList.size() == 12 && code == "%b") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sMonthShortList[gmt->tm_mon]; + } else if( !LLStringOps::sDayFormat.empty() && code == "%d" ) { struct tm * gmt = gmtime (&loc_seconds); diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 9d25c7180d..786e18b187 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -29,6 +29,8 @@ #include "llscrolllistcell.h" +#include "lltrans.h" + #include "llcheckboxctrl.h" #include "llui.h" // LLUIImage #include "lluictrlfactory.h" @@ -428,7 +430,13 @@ LLScrollListDate::LLScrollListDate( const LLScrollListCell::Params& p) void LLScrollListDate::setValue(const LLSD& value) { mDate = value.asDate(); - LLScrollListText::setValue(mDate.asRFC1123()); + + std::string date_str = LLTrans::getString("ScrollListCellDateFormat"); + LLSD substitution; + substitution["datetime"] = mDate.secondsSinceEpoch(); + LLStringUtil::format(date_str, substitution); + + LLScrollListText::setValue(date_str); } const LLSD LLScrollListDate::getValue() const diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b45f9c55fb..9595e82a07 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1043,21 +1043,14 @@ bool LLAppViewer::init() LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; - //EXT-7013 - On windows for some locale (Japanese) standard - //datetime formatting functions didn't support some parameters such as "weekday". - //Names for days and months localized in xml are also useful for Polish locale(STORM-107). - std::string language = gSavedSettings.getString("Language"); - if(language == "ja" || language == "pl") - { - LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); - LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); - LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); - LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); - LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); - - LLStringOps::sAM = LLTrans::getString("dateTimeAM"); - LLStringOps::sPM = LLTrans::getString("dateTimePM"); - } + LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); + LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); + LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); + LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); + LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); + + LLStringOps::sAM = LLTrans::getString("dateTimeAM"); + LLStringOps::sPM = LLTrans::getString("dateTimePM"); LLAgentLanguage::init(); diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ac5b027ea1..e31fd167bc 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3498,6 +3498,9 @@ Abuse Report [MDAY] AM PM + + + [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] US$ [AMOUNT] diff --git a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml index 95649d3934..0b5333fc80 100644 --- a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml @@ -13,7 +13,7 @@ Le propriĆ©taire peut : - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] + [wkday,datetime,local] [day,datetime,local] [mth,datetime,local] [year,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] (inventaire) -- cgit v1.3 From 3861249a749c99c2a7b05d15ef82f8ff21453d05 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 3 Jan 2012 09:41:16 -0800 Subject: use lazy deletion of views via die() method to avoid some potential crashes --- indra/llui/llmenugl.cpp | 7 ++++++- indra/llui/llview.cpp | 6 ++++++ indra/newview/llfavoritesbar.cpp | 4 ++-- indra/newview/llfloatercolorpicker.cpp | 2 +- indra/newview/llfloatersnapshot.cpp | 2 +- indra/newview/llfolderview.cpp | 4 ++-- indra/newview/llgrouplist.cpp | 2 +- indra/newview/llpanelpeople.cpp | 10 +++++----- indra/newview/llpanelprofile.cpp | 2 +- indra/newview/llpanelteleporthistory.cpp | 2 +- 10 files changed, 26 insertions(+), 15 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index cb237fca7c..95ecbb1c94 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -947,9 +947,14 @@ LLMenuItemBranchGL::LLMenuItemBranchGL(const LLMenuItemBranchGL::Params& p) LLMenuItemBranchGL::~LLMenuItemBranchGL() { - delete mBranchHandle.get(); + if (mBranchHandle.get()) + { + mBranchHandle.get()->die(); + } } + + // virtual LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse) const { diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 486babb0ab..1529381773 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -121,6 +121,7 @@ LLView::Params::Params() LLView::LLView(const LLView::Params& p) : mVisible(p.visible), + mInDraw(false), mName(p.name), mParentView(NULL), mReshapeFlags(FOLLOWS_NONE), @@ -281,6 +282,8 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child) // virtual bool LLView::addChild(LLView* child, S32 tab_group) { + llassert_always(mInDraw == false); + if (!child) { return false; @@ -330,6 +333,7 @@ bool LLView::addChildInBack(LLView* child, S32 tab_group) // remove the specified child from the view, and set it's parent to NULL. void LLView::removeChild(LLView* child) { + llassert_always(mInDraw == false); //llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child->mParentView == this) { @@ -1081,6 +1085,7 @@ void LLView::draw() void LLView::drawChildren() { + mInDraw = true; if (!mChildList.empty()) { LLView* rootp = LLUI::getRootView(); @@ -1119,6 +1124,7 @@ void LLView::drawChildren() } --sDepth; } + mInDraw = false; } void LLView::dirtyRect() diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 4f2fd47488..f4b6dc2c81 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -405,8 +405,8 @@ LLFavoritesBarCtrl::~LLFavoritesBarCtrl() { gInventory.removeObserver(this); - delete mOverflowMenuHandle.get(); - delete mContextMenuHandle.get(); + if (mOverflowMenuHandle.get()) mOverflowMenuHandle.get()->die(); + if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); } BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 659e52271a..05d73c2416 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -271,7 +271,7 @@ void LLFloaterColorPicker::destroyUI () if ( mSwatchView ) { this->removeChild ( mSwatchView ); - delete mSwatchView; + mSwatchView->die();; mSwatchView = NULL; } } diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 1b3290d5a8..2dd031b5d3 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1977,7 +1977,7 @@ LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key) // Destroys the object LLFloaterSnapshot::~LLFloaterSnapshot() { - delete impl.mPreviewHandle.get(); + if (impl.mPreviewHandle.get()) impl.mPreviewHandle.get()->die(); //unfreeze everything else gSavedSettings.setBOOL("FreezeTime", FALSE); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 6ec2598e44..20fe85472f 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -299,7 +299,7 @@ LLFolderView::~LLFolderView( void ) mAutoOpenItems.removeAllNodes(); gIdleCallbacks.deleteFunction(idle, this); - delete mPopupMenuHandle.get(); + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); mAutoOpenItems.removeAllNodes(); clearSelection(); @@ -1969,7 +1969,7 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderView::deleteAllChildren() { closeRenamer(); - delete mPopupMenuHandle.get(); + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); mPopupMenuHandle = LLHandle(); mScrollContainer = NULL; mRenameItem = NULL; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index f7ed1116cb..bbf66ca750 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -95,7 +95,7 @@ LLGroupList::LLGroupList(const Params& p) LLGroupList::~LLGroupList() { gAgent.removeListener(this); - delete mContextMenuHandle.get(); + if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); } // virtual diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index d5e289e6e6..9c46f04abf 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -526,11 +526,11 @@ LLPanelPeople::~LLPanelPeople() LLVoiceClient::getInstance()->removeObserver(this); } - delete mGroupPlusMenuHandle.get(); - delete mNearbyViewSortMenuHandle.get(); - delete mFriendsViewSortMenuHandle.get(); - delete mGroupsViewSortMenuHandle.get(); - delete mRecentViewSortMenuHandle.get(); + if (mGroupPlusMenuHandle.get()) mGroupPlusMenuHandle.get()->die(); + if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); + if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); + if (mGroupsViewSortMenuHandle.get()) mGroupsViewSortMenuHandle.get()->die(); + if (mRecentViewSortMenuHandle.get()) mRecentViewSortMenuHandle.get()->die(); } diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index b1eeabb028..e2e7006773 100755 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -177,7 +177,7 @@ LLPanelProfile::ChildStack::~ChildStack() LLView* viewp = *it; if (viewp) { - delete viewp; + viewp->die(); } } mStack.pop_back(); diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index d3543daff0..1f1cccad85 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -388,7 +388,7 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel() LLTeleportHistoryPanel::~LLTeleportHistoryPanel() { LLTeleportHistoryFlatItemStorage::instance().purge(); - delete mGearMenuHandle.get(); + if (mGearMenuHandle.get()) mGearMenuHandle.get()->die(); mTeleportHistoryChangedConnection.disconnect(); } -- cgit v1.3 From 1b1ad93c5d341eb564a7e6fc1ae9298473d8a98e Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 3 Jan 2012 12:21:30 -0800 Subject: EXP-1512 FIX changing UI size changes cursor position in notecards fixed case where adding text between 2 consecutive newlines created gibberish --- indra/llui/lltextbase.cpp | 15 +++++++++++++-- indra/llui/llview.h | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 1f890b625f..0040be45c7 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1513,6 +1513,8 @@ void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg LLTextBase::segment_set_t::iterator LLTextBase::getEditableSegIterContaining(S32 index) { segment_set_t::iterator it = getSegIterContaining(index); + segment_set_t::iterator orig_it = it; + if (it == mSegments.end()) return it; if (!(*it)->canEdit() @@ -1520,13 +1522,18 @@ LLTextBase::segment_set_t::iterator LLTextBase::getEditableSegIterContaining(S32 && it != mSegments.begin()) { it--; + if ((*it)->canEdit()) + { + return it; + } } - return it; + return orig_it; } LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaining(S32 index) const { segment_set_t::const_iterator it = getSegIterContaining(index); + segment_set_t::const_iterator orig_it = it; if (it == mSegments.end()) return it; if (!(*it)->canEdit() @@ -1534,8 +1541,12 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaini && it != mSegments.begin()) { it--; + if ((*it)->canEdit()) + { + return it; + } } - return it; + return orig_it; } LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index) diff --git a/indra/llui/llview.h b/indra/llui/llview.h index f21fb37e18..f1fac5f69c 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -612,6 +612,8 @@ private: S32 mNextInsertionOrdinal; + bool mInDraw; + static LLWindow* sWindow; // All root views must know about their window. typedef std::map default_widget_map_t; -- cgit v1.3 From 9c8f6ba6a51b799d16e89e995bbcf3b0dcc15c62 Mon Sep 17 00:00:00 2001 From: Leslie Linden Date: Wed, 4 Jan 2012 17:37:57 -0800 Subject: Modified CRASH assert to not occur in release mode per Richard --- indra/llui/llview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 1529381773..542f57ee5f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -282,7 +282,8 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child) // virtual bool LLView::addChild(LLView* child, S32 tab_group) { - llassert_always(mInDraw == false); + // NOTE: Changed this to not crash in release mode + llassert(mInDraw == false); if (!child) { -- cgit v1.3 From 757a955bd700eb4f838762dcbe789a77ee052064 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 6 Jan 2012 12:07:52 -0800 Subject: Looking for better fix to EXP-1693 - date localization Backed out changeset: 4f3024e9d629 --- indra/llcommon/llstring.cpp | 5 ----- indra/llui/llscrolllistcell.cpp | 10 +--------- indra/newview/llappviewer.cpp | 23 ++++++++++++++-------- indra/newview/skins/default/xui/en/strings.xml | 3 --- .../skins/default/xui/fr/sidepanel_item_info.xml | 2 +- 5 files changed, 17 insertions(+), 26 deletions(-) (limited to 'indra/llui') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 1193a4ef8d..e7fe656808 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -1122,11 +1122,6 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, struct tm * gmt = gmtime (&loc_seconds); replacement = LLStringOps::sMonthList[gmt->tm_mon]; } - else if(LLStringOps::sMonthShortList.size() == 12 && code == "%b") - { - struct tm * gmt = gmtime (&loc_seconds); - replacement = LLStringOps::sMonthShortList[gmt->tm_mon]; - } else if( !LLStringOps::sDayFormat.empty() && code == "%d" ) { struct tm * gmt = gmtime (&loc_seconds); diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 786e18b187..9d25c7180d 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -29,8 +29,6 @@ #include "llscrolllistcell.h" -#include "lltrans.h" - #include "llcheckboxctrl.h" #include "llui.h" // LLUIImage #include "lluictrlfactory.h" @@ -430,13 +428,7 @@ LLScrollListDate::LLScrollListDate( const LLScrollListCell::Params& p) void LLScrollListDate::setValue(const LLSD& value) { mDate = value.asDate(); - - std::string date_str = LLTrans::getString("ScrollListCellDateFormat"); - LLSD substitution; - substitution["datetime"] = mDate.secondsSinceEpoch(); - LLStringUtil::format(date_str, substitution); - - LLScrollListText::setValue(date_str); + LLScrollListText::setValue(mDate.asRFC1123()); } const LLSD LLScrollListDate::getValue() const diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 33d4563feb..0861fe85a8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1044,14 +1044,21 @@ bool LLAppViewer::init() LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; - LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); - LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); - LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); - LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); - LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); - - LLStringOps::sAM = LLTrans::getString("dateTimeAM"); - LLStringOps::sPM = LLTrans::getString("dateTimePM"); + //EXT-7013 - On windows for some locale (Japanese) standard + //datetime formatting functions didn't support some parameters such as "weekday". + //Names for days and months localized in xml are also useful for Polish locale(STORM-107). + std::string language = gSavedSettings.getString("Language"); + if(language == "ja" || language == "pl") + { + LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); + LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); + LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); + LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); + LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); + + LLStringOps::sAM = LLTrans::getString("dateTimeAM"); + LLStringOps::sPM = LLTrans::getString("dateTimePM"); + } LLAgentLanguage::init(); diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 492e51e0fd..9752a07b66 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3503,9 +3503,6 @@ Abuse Report [MDAY] AM PM - - - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] US$ [AMOUNT] diff --git a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml index 0b5333fc80..95649d3934 100644 --- a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml @@ -13,7 +13,7 @@ Le propriĆ©taire peut : - [wkday,datetime,local] [day,datetime,local] [mth,datetime,local] [year,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] + [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] (inventaire) -- cgit v1.3 From 3169f4a96fd4c62d1390cd53ff2aaa4cb28fb047 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Wed, 11 Jan 2012 10:19:11 -0800 Subject: assert for updating views while drawing was too aggressive made assert match actual error condition for list iterators reviewed by Leslie --- indra/llui/llview.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 542f57ee5f..004681325f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -282,9 +282,6 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child) // virtual bool LLView::addChild(LLView* child, S32 tab_group) { - // NOTE: Changed this to not crash in release mode - llassert(mInDraw == false); - if (!child) { return false; @@ -334,10 +331,11 @@ bool LLView::addChildInBack(LLView* child, S32 tab_group) // remove the specified child from the view, and set it's parent to NULL. void LLView::removeChild(LLView* child) { - llassert_always(mInDraw == false); //llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child->mParentView == this) { + // if we are removing an item we are currently iterating over, that would be bad + llassert(child->mInDraw == false); mChildList.remove( child ); child->mParentView = NULL; if (child->isCtrl()) @@ -1086,7 +1084,6 @@ void LLView::draw() void LLView::drawChildren() { - mInDraw = true; if (!mChildList.empty()) { LLView* rootp = LLUI::getRootView(); @@ -1105,7 +1102,10 @@ void LLView::drawChildren() LLUI::pushMatrix(); { LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); + // flag the fact we are in draw here, in case overridden draw() method attempts to remove this widget + viewp->mInDraw = true; viewp->draw(); + viewp->mInDraw = false; if (sDebugRects) { @@ -1125,7 +1125,6 @@ void LLView::drawChildren() } --sDepth; } - mInDraw = false; } void LLView::dirtyRect() -- cgit v1.3 From 33a17d8a83b3810e344e663395219d3130cb34c3 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 11 Jan 2012 17:43:17 -0800 Subject: EXP-1549 : Disable the Remove button menu item in the toolbar contextual menu if no button clicked --- indra/llui/lltoolbar.cpp | 9 ++++++++- indra/llui/lltoolbar.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 7f96c1373c..9b31a6449d 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -151,14 +151,20 @@ void LLToolBar::createContextMenu() if (menu) { menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mPopupMenuHandle = menu->getHandle(); + mRemoveButtonHandle = menu->getChild("Remove button")->getHandle(); } else { llwarns << "Unable to load toolbars context menu." << llendl; } } + + if (mRemoveButtonHandle.get()) + { + // Disable/Enable the "Remove button" menu item depending on whether or not a button was clicked + mRemoveButtonHandle.get()->setEnabled(mRightMouseTargetButton != NULL); + } } void LLToolBar::initFromParams(const LLToolBar::Params& p) @@ -401,6 +407,7 @@ BOOL LLToolBar::handleRightMouseDown(S32 x, S32 y, MASK mask) { // Determine which button the mouse was over during the click in case the context menu action // is intended to affect the button. + mRightMouseTargetButton = NULL; BOOST_FOREACH(LLToolBarButton* button, mButtons) { LLRect button_rect; diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h index 51fe23ddd1..a50c60282c 100644 --- a/indra/llui/lltoolbar.h +++ b/indra/llui/lltoolbar.h @@ -271,6 +271,7 @@ private: LLLayoutStack* mCenteringStack; LLPanel* mButtonPanel; LLHandle mPopupMenuHandle; + LLHandle mRemoveButtonHandle; LLToolBarButton* mRightMouseTargetButton; -- cgit v1.3 From cd4204b2730350eede126190814621b65308c422 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 16 Jan 2012 11:03:33 -0800 Subject: EXP-1758 WIP Progress spinner not shown during merketplace synch if Merchant Outbox floater was previously minimized rewrote layout_stack resizing logic to be symmetrical --- indra/llui/lllayoutstack.cpp | 784 ++++++++++++--------- indra/llui/lllayoutstack.h | 69 +- indra/llui/llresizebar.cpp | 4 +- indra/llui/llresizebar.h | 1 + indra/llui/llwindowshade.cpp | 4 +- indra/newview/llchathistory.cpp | 1 - indra/newview/llchicletbar.cpp | 27 - indra/newview/llfloaternotificationsconsole.cpp | 2 +- indra/newview/llimfloater.cpp | 3 - indra/newview/llsidepanelinventory.cpp | 1 - .../skins/default/xui/en/floater_help_browser.xml | 1 - .../skins/default/xui/en/floater_im_session.xml | 5 +- .../skins/default/xui/en/floater_media_browser.xml | 4 - .../default/xui/en/floater_test_layout_stacks.xml | 223 ++++++ .../skins/default/xui/en/floater_ui_preview.xml | 2 + .../default/xui/en/floater_voice_controls.xml | 5 +- .../skins/default/xui/en/floater_web_content.xml | 5 +- indra/newview/skins/default/xui/en/main_view.xml | 2 - .../skins/default/xui/en/menu_inventory_add.xml | 1 + .../default/xui/en/panel_adhoc_control_panel.xml | 6 +- .../skins/default/xui/en/panel_bottomtray_lite.xml | 8 +- .../skins/default/xui/en/panel_chiclet_bar.xml | 4 - .../skins/default/xui/en/panel_classified_info.xml | 12 +- .../skins/default/xui/en/panel_edit_classified.xml | 2 - .../skins/default/xui/en/panel_edit_pick.xml | 2 - .../skins/default/xui/en/panel_edit_profile.xml | 2 - .../skins/default/xui/en/panel_edit_wearable.xml | 2 - .../default/xui/en/panel_group_control_panel.xml | 11 +- .../default/xui/en/panel_group_info_sidetray.xml | 5 +- .../default/xui/en/panel_im_control_panel.xml | 23 +- .../skins/default/xui/en/panel_landmarks.xml | 4 - indra/newview/skins/default/xui/en/panel_login.xml | 2 - .../skins/default/xui/en/panel_main_inventory.xml | 4 - .../skins/default/xui/en/panel_navigation_bar.xml | 1 - .../skins/default/xui/en/panel_nearby_media.xml | 10 +- .../skins/default/xui/en/panel_outfit_edit.xml | 6 +- .../default/xui/en/panel_outfits_inventory.xml | 2 - .../newview/skins/default/xui/en/panel_people.xml | 12 - .../skins/default/xui/en/panel_pick_info.xml | 3 - indra/newview/skins/default/xui/en/panel_picks.xml | 5 - .../skins/default/xui/en/panel_place_profile.xml | 2 - .../newview/skins/default/xui/en/panel_places.xml | 10 - .../default/xui/en/panel_postcard_settings.xml | 2 - .../default/xui/en/panel_prim_media_controls.xml | 35 +- .../skins/default/xui/en/panel_progress.xml | 3 - .../skins/default/xui/en/panel_snapshot_local.xml | 2 - .../default/xui/en/panel_snapshot_profile.xml | 2 - .../skins/default/xui/en/panel_toolbar_view.xml | 5 - .../skins/default/xui/en/sidepanel_inventory.xml | 12 +- 49 files changed, 755 insertions(+), 588 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml (limited to 'indra/llui') diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 0e7060e22c..b67030dc34 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -34,10 +34,13 @@ #include "llpanel.h" #include "llresizebar.h" #include "llcriticaldamp.h" +#include "boost/foreach.hpp" static LLDefaultChildRegistry::Register register_layout_stack("layout_stack"); static LLLayoutStack::LayoutStackRegistry::Register register_layout_panel("layout_panel"); +static const F32 MAX_FRACTIONAL_VALUE = 0.99999f; + void LLLayoutStack::OrientationNames::declareValues() { declare("horizontal", HORIZONTAL); @@ -49,15 +52,12 @@ void LLLayoutStack::OrientationNames::declareValues() // LLLayoutPanel::Params::Params() : expanded_min_dim("expanded_min_dim", 0), - min_dim("min_dim", 0), - max_dim("max_dim", S32_MAX), - user_resize("user_resize", true), + min_dim("min_dim", -1), + user_resize("user_resize", false), 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::LLLayoutPanel(const Params& p) @@ -65,7 +65,6 @@ LLLayoutPanel::LLLayoutPanel(const Params& p) mExpandedMinDimSpecified(false), mExpandedMinDim(p.min_dim), mMinDim(p.min_dim), - mMaxDim(p.max_dim), mAutoResize(p.auto_resize), mUserResize(p.user_resize), mCollapsed(FALSE), @@ -73,6 +72,8 @@ LLLayoutPanel::LLLayoutPanel(const Params& p) mVisibleAmt(1.f), // default to fully visible mResizeBar(NULL), mFractionalSize(0.f), + mTargetDim(0), + mIgnoreReshape(false), mOrientation(LLLayoutStack::HORIZONTAL) { // Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value @@ -103,33 +104,85 @@ LLLayoutPanel::~LLLayoutPanel() mResizeBar = NULL; } -void LLLayoutPanel::reshape(S32 width, S32 height, BOOL called_from_parent) +F32 LLLayoutPanel::getAutoResizeFactor() const +{ + return mVisibleAmt * (1.f - mCollapseAmt); +} + +F32 LLLayoutPanel::getVisibleAmount() const +{ + return mVisibleAmt; +} + +S32 LLLayoutPanel::getLayoutDim() const +{ + return llround((mOrientation == LLLayoutStack::HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight()); +} + +S32 LLLayoutPanel::getVisibleDim() const +{ + F32 min_dim = getRelevantMinDim(); + return llround(mVisibleAmt + * (min_dim + + (((F32)mTargetDim - min_dim) * (1.f - mCollapseAmt)))); +} + +void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientation ) { - if (mOrientation == LLLayoutStack::HORIZONTAL) + mOrientation = orientation; + S32 layout_dim = llround((mOrientation == LLLayoutStack::HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight()); + + if (mMinDim == -1) { - mFractionalSize += width - llround(mFractionalSize); + if (!mAutoResize) + { + setMinDim(layout_dim); + } + else + { + setMinDim(0); + } } - else + + mTargetDim = llmax(layout_dim, getMinDim()); +} + +void LLLayoutPanel::setVisible( BOOL visible ) +{ + if (visible != getVisible()) { - mFractionalSize += height - llround(mFractionalSize); + LLLayoutStack* stackp = dynamic_cast(getParent()); + stackp->mNeedsLayout = true; } - LLPanel::reshape(width, height, called_from_parent); + LLPanel::setVisible(visible); } -F32 LLLayoutPanel::getCollapseFactor() +void LLLayoutPanel::reshape( S32 width, S32 height, BOOL called_from_parent /*= TRUE*/ ) { - if (mOrientation == LLLayoutStack::HORIZONTAL) + if (!mIgnoreReshape && !mAutoResize) { - F32 collapse_amt = - clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getWidth())); - return mVisibleAmt * collapse_amt; + mTargetDim = (mOrientation == LLLayoutStack::HORIZONTAL) ? width : height; } - else + LLPanel::reshape(width, height, called_from_parent); +} + +void LLLayoutPanel::handleReshape(const LLRect& new_rect, bool by_user) +{ + LLLayoutStack* stackp = dynamic_cast(getParent()); + if (stackp) { - F32 collapse_amt = - clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getHeight()))); - return mVisibleAmt * collapse_amt; + stackp->mNeedsLayout = true; + if (by_user) + { + // tell layout stack to account for new shape + stackp->updatePanelRect(this, new_rect); + } } + LLPanel::handleReshape(new_rect, by_user); } // @@ -147,12 +200,11 @@ LLLayoutStack::Params::Params() LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) : LLView(p), - mMinWidth(0), - mMinHeight(0), mPanelSpacing(p.border_size), mOrientation(p.orientation), mAnimate(p.animate), mAnimatedThisFrame(false), + mNeedsLayout(true), mClip(p.clip), mOpenTimeConstant(p.open_time_constant), mCloseTimeConstant(p.close_time_constant) @@ -169,26 +221,26 @@ void LLLayoutStack::draw() { updateLayout(); - e_panel_list_t::iterator panel_it; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + // always clip to stack itself + LLLocalClipRect clip(getLocalRect()); + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { // clip to layout rectangle, not bounding rectangle - LLRect clip_rect = (*panel_it)->getRect(); + LLRect clip_rect = panelp->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 + panelp->getVisibleDim(); } else { - clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor()); + clip_rect.mBottom = clip_rect.mTop - panelp->getVisibleDim(); } - LLPanel* panelp = (*panel_it); - - LLLocalClipRect clip(clip_rect, mClip); - // only force drawing invisible children if visible amount is non-zero - drawChild(panelp, 0, 0, !clip_rect.isEmpty()); + {LLLocalClipRect clip(clip_rect, mClip); + // only force drawing invisible children if visible amount is non-zero + drawChild(panelp, 0, 0, !clip_rect.isEmpty()); + } } mAnimatedThisFrame = false; } @@ -201,12 +253,10 @@ void LLLayoutStack::removeChild(LLView* view) { mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp)); delete embedded_panelp; + updateFractionalSizes(); + mNeedsLayout = true; } - // need to update resizebars - - calcMinExtents(); - LLView::removeChild(view); } @@ -221,29 +271,15 @@ bool LLLayoutStack::addChild(LLView* child, S32 tab_group) LLLayoutPanel* panelp = dynamic_cast(child); if (panelp) { - panelp->mFractionalSize = (mOrientation == HORIZONTAL) - ? panelp->getRect().getWidth() - : panelp->getRect().getHeight(); panelp->setOrientation(mOrientation); mPanels.push_back(panelp); + createResizeBar(panelp); + mNeedsLayout = true; } - return LLView::addChild(child, tab_group); -} - -void LLLayoutStack::movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front) -{ - LLLayoutPanel* embedded_panel_to_move = findEmbeddedPanel(panel_to_move); - LLLayoutPanel* embedded_target_panel = move_to_front ? *mPanels.begin() : findEmbeddedPanel(target_panel); + BOOL result = LLView::addChild(child, tab_group); - if (!embedded_panel_to_move || !embedded_target_panel || embedded_panel_to_move == embedded_target_panel) - { - llwarns << "One of the panels was not found in stack or NULL was passed instead of valid panel" << llendl; - return; - } - e_panel_list_t::iterator it = std::find(mPanels.begin(), mPanels.end(), embedded_panel_to_move); - mPanels.erase(it); - it = move_to_front ? mPanels.begin() : std::find(mPanels.begin(), mPanels.end(), embedded_target_panel); - mPanels.insert(it, embedded_panel_to_move); + updateFractionalSizes(); + return result; } void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate) @@ -258,23 +294,19 @@ void LLLayoutStack::addPanel(LLLayoutPanel* panel, EAnimate animate) } } -void LLLayoutStack::removePanel(LLPanel* panel) -{ - removeChild(panel); -} - void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed) { LLLayoutPanel* panel_container = findEmbeddedPanel(panel); if (!panel_container) return; panel_container->mCollapsed = collapsed; + mNeedsLayout = true; } void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize) { LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); - + if (panel) { panel->mAutoResize = auto_resize; @@ -291,51 +323,246 @@ void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_ } } -bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_dimp) + +static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks"); + +void LLLayoutStack::updateLayout() +{ + LLFastTimer ft(FTM_UPDATE_LAYOUT); + + if (!mNeedsLayout) return; + + bool animation_in_progress = animatePanels(); + F32 total_visible_fraction = 0.f; + S32 space_to_distribute = (mOrientation == HORIZONTAL) + ? getRect().getWidth() + : getRect().getHeight(); + + // first, assign minimum dimensions + LLLayoutPanel* panelp = NULL; + BOOST_FOREACH(panelp, mPanels) + { + if (panelp->mAutoResize) + { + panelp->mTargetDim = panelp->getRelevantMinDim(); + } + space_to_distribute -= panelp->getVisibleDim() + llround((F32)mPanelSpacing * panelp->getVisibleAmount()); + total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor(); + } + + llassert(total_visible_fraction < 1.01f); + + // don't need spacing after last panel + space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0; + + // scale up space to distribute, since some of might will go to an invisible fraction of the auto-resize space + space_to_distribute = (total_visible_fraction > 0.f) + ? llround((F32)space_to_distribute / total_visible_fraction) + : space_to_distribute; + + if (space_to_distribute > 0) + { // give space proportionally to auto resize panels, even invisible ones + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize == TRUE) + { + S32 delta = llround((F32)space_to_distribute * panelp->mFractionalSize/* * panelp->getAutoResizeFactor()*/); + panelp->mTargetDim += delta; + } + } + } + + F32 cur_pos = (mOrientation == HORIZONTAL) ? 0.f : (F32)getRect().getHeight(); + + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + F32 panel_dim = panelp->mTargetDim; + F32 panel_visible_dim = panelp->getVisibleDim(); + + LLRect panel_rect; + if (mOrientation == HORIZONTAL) + { + panel_rect.setLeftTopAndSize(llround(cur_pos), + getRect().getHeight(), + llround(panel_dim), + getRect().getHeight()); + } + else + { + panel_rect.setLeftTopAndSize(0, + llround(cur_pos), + getRect().getWidth(), + llround(panel_dim)); + } + panelp->setIgnoreReshape(true); + panelp->setShape(panel_rect); + panelp->setIgnoreReshape(false); + + static LLUICachedControl resize_bar_overlap ("UIResizeBarOverlap", 0); + LLRect resize_bar_rect(panel_rect); + + F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount(); + if (mOrientation == HORIZONTAL) + { + resize_bar_rect.mLeft = panel_rect.mRight - resize_bar_overlap; + resize_bar_rect.mRight = panel_rect.mRight + panel_spacing + resize_bar_overlap; + + cur_pos += panel_visible_dim + panel_spacing; + } + else //VERTICAL + { + resize_bar_rect.mTop = panel_rect.mBottom + resize_bar_overlap; + resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing - resize_bar_overlap; + + cur_pos -= panel_visible_dim + panel_spacing; + } + panelp->mResizeBar->setShape(resize_bar_rect); + } + + updateResizeBarLimits(); + + // clear animation flag at end, since panel resizes will set it + // and leave it set if there is any animation in progress + mNeedsLayout = animation_in_progress; +} // end LLLayoutStack::updateLayout + +LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const +{ + if (!panelp) return NULL; + + e_panel_list_t::const_iterator panel_it; + BOOST_FOREACH(LLLayoutPanel* p, mPanels) + { + if (p == panelp) + { + return p; + } + } + return NULL; +} + +LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const { - LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); + LLLayoutPanel* result = NULL; - if (panel && min_dimp) + BOOST_FOREACH(LLLayoutPanel* p, mPanels) { - *min_dimp = panel->getRelevantMinDim(); + if (p->getName() == name) + { + result = p; + break; + } } - return NULL != panel; + return result; } -bool LLLayoutStack::getPanelMaxSize(const std::string& panel_name, S32* max_dimp) +void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp) { - LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name); + BOOST_FOREACH(LLLayoutPanel* lp, mPanels) + { + if (lp->mResizeBar == NULL) + { + LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; + LLRect resize_bar_rect = getRect(); - if (panel) + LLResizeBar::Params resize_params; + resize_params.name("resize"); + resize_params.resizing_view(lp); + resize_params.min_size(lp->getRelevantMinDim()); + resize_params.side(side); + resize_params.snapping_enabled(false); + LLResizeBar* resize_bar = LLUICtrlFactory::create(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) { - if (max_dimp) *max_dimp = panel->mMaxDim; + LLResizeBar* resize_barp = (*panel_it)->mResizeBar; + sendChildToFront(resize_barp); } +} - return NULL != panel; +// update layout stack animations, etc. once per frame +// NOTE: we use this to size world view based on animating UI, *before* we draw the UI +// we might still need to call updateLayout during UI draw phase, in case UI elements +// are resizing themselves dynamically +//static +void LLLayoutStack::updateClass() +{ + for (instance_iter it = beginInstances(); it != endInstances(); ++it) + { + it->updateLayout(); + } } -static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks"); -void LLLayoutStack::updateLayout(BOOL force_resize) +void LLLayoutStack::updateFractionalSizes() { - LLFastTimer ft(FTM_UPDATE_LAYOUT); - static LLUICachedControl resize_bar_overlap ("UIResizeBarOverlap", 0); - calcMinExtents(); - createResizeBars(); + F32 total_resizable_dim = 0; + S32 num_auto_resize_panels = 0; + + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim()); + num_auto_resize_panels++; + } + } - // calculate current extents - F32 total_size = 0.f; + F32 total_fractional_size = 0.f; + + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + F32 panel_resizable_dim = llmax(0.f, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim())); + panelp->mFractionalSize = llmin(MAX_FRACTIONAL_VALUE, (panel_resizable_dim == 0.f) + ? (1.f - MAX_FRACTIONAL_VALUE) + : panel_resizable_dim / total_resizable_dim); + total_fractional_size += panelp->mFractionalSize; + // check for NaNs + llassert(panelp->mFractionalSize == panelp->mFractionalSize); + } + } + if (total_fractional_size == 0.f) + { // equal distribution + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + panelp->mFractionalSize = 1.f / (F32)num_auto_resize_panels; + } + } + } + else + { // renormalize + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) + { + panelp->mFractionalSize /= total_fractional_size; + } + } + } +} + +bool LLLayoutStack::animatePanels() +{ + bool animation_in_progress = false; + // // animate visibility // - e_panel_list_t::iterator panel_it; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { - LLLayoutPanel* panelp = (*panel_it); - if (panelp->getVisible()) + if (panelp->getVisible()) { - if (mAnimate) + if (mAnimate && panelp->mVisibleAmt < 1.f) { if (!mAnimatedThisFrame) { @@ -345,15 +572,21 @@ void LLLayoutStack::updateLayout(BOOL force_resize) panelp->mVisibleAmt = 1.f; } } + + animation_in_progress = true; } else { - panelp->mVisibleAmt = 1.f; + if (panelp->mVisibleAmt != 1.f) + { + panelp->mVisibleAmt = 1.f; + animation_in_progress = true; + } } } else // not visible { - if (mAnimate) + if (mAnimate && panelp->mVisibleAmt > 0.f) { if (!mAnimatedThisFrame) { @@ -363,297 +596,206 @@ void LLLayoutStack::updateLayout(BOOL force_resize) panelp->mVisibleAmt = 0.f; } } + + animation_in_progress = true; } else { - panelp->mVisibleAmt = 0.f; + if (panelp->mVisibleAmt != 0.f) + { + panelp->mVisibleAmt = 0.f; + animation_in_progress = true; + } } } F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f; - panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); - - total_size += panelp->mFractionalSize * panelp->getCollapseFactor(); - // want n-1 panel gaps for n panels - if (panel_it != mPanels.begin()) - { - total_size += mPanelSpacing; - } - } - - S32 num_resizable_panels = 0; - F32 shrink_headroom_available = 0.f; - F32 shrink_headroom_total = 0.f; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - LLLayoutPanel* panelp = (*panel_it); - - // panels that are not fully visible do not count towards shrink headroom - if (panelp->getCollapseFactor() < 1.f) - { - continue; - } - - F32 cur_size = panelp->mFractionalSize; - F32 min_size = (F32)panelp->getRelevantMinDim(); - - // if currently resizing a panel or the panel is flagged as not automatically resizing - // only track total available headroom, but don't use it for automatic resize logic - if (panelp->mResizeBar->hasMouseCapture() - || (!panelp->mAutoResize - && !force_resize)) - { - shrink_headroom_total += cur_size - min_size; - } - else - { - num_resizable_panels++; - - shrink_headroom_available += cur_size - min_size; - shrink_headroom_total += cur_size - min_size; - } - } - - // calculate how many pixels need to be distributed among layout panels - // positive means panels need to grow, negative means shrink - F32 pixels_to_distribute = (mOrientation == HORIZONTAL) - ? getRect().getWidth() - total_size - : getRect().getHeight() - total_size; - - // now we distribute the pixels... - F32 cur_x = 0.f; - F32 cur_y = (F32)getRect().getHeight(); - - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - LLLayoutPanel* panelp = (*panel_it); - - F32 min_size = panelp->getRelevantMinDim(); - F32 delta_size = 0.f; - - // if panel can automatically resize (not animating, and resize flag set)... - if (panelp->getCollapseFactor() == 1.f - && (force_resize || panelp->mAutoResize) - && !panelp->mResizeBar->hasMouseCapture()) + if (panelp->mCollapseAmt != collapse_state) { - if (pixels_to_distribute < 0.f) + if (!mAnimatedThisFrame) { - // shrink proportionally to amount over minimum - // so we can do this in one pass - delta_size = (shrink_headroom_available > 0.f) - ? pixels_to_distribute * ((F32)(panelp->mFractionalSize - min_size) / shrink_headroom_available) - : 0.f; - shrink_headroom_available -= (panelp->mFractionalSize - min_size); + panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); } - else + animation_in_progress = true; + + if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) { - // grow all elements equally - delta_size = pixels_to_distribute / (F32)num_resizable_panels; - num_resizable_panels--; + panelp->mCollapseAmt = collapse_state; } - - panelp->mFractionalSize = llmax(min_size, panelp->mFractionalSize + delta_size); - pixels_to_distribute -= delta_size; } + } - // adjust running headroom count based on new sizes - shrink_headroom_total += delta_size; + mAnimatedThisFrame = true; - LLRect panel_rect; - if (mOrientation == HORIZONTAL) - { - panel_rect.setLeftTopAndSize(llround(cur_x), - llround(cur_y), - llround(panelp->mFractionalSize), - getRect().getHeight()); - } - else - { - panel_rect.setLeftTopAndSize(llround(cur_x), - llround(cur_y), - getRect().getWidth(), - llround(panelp->mFractionalSize)); - } - panelp->setShape(panel_rect); + return animation_in_progress; +} - LLRect resize_bar_rect = panel_rect; - if (mOrientation == HORIZONTAL) - { - resize_bar_rect.mLeft = panel_rect.mRight - resize_bar_overlap; - resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + resize_bar_overlap; - } - else - { - resize_bar_rect.mTop = panel_rect.mBottom + resize_bar_overlap; - resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - resize_bar_overlap; - } - (*panel_it)->mResizeBar->setRect(resize_bar_rect); +void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& new_rect ) +{ + S32 new_dim = (mOrientation == HORIZONTAL) + ? new_rect.getWidth() + : new_rect.getHeight(); + S32 delta_dim = new_dim - resized_panel->getVisibleDim(); + if (delta_dim == 0) return; - F32 size = ((*panel_it)->mFractionalSize * (*panel_it)->getCollapseFactor()) + (F32)mPanelSpacing; - if (mOrientation == HORIZONTAL) - { - cur_x += size; - } - else //VERTICAL - { - cur_y -= size; - } - } + F32 total_visible_fraction = 0.f; + F32 delta_auto_resize_headroom = 0.f; + F32 total_auto_resize_headroom = 0.f; - // update resize bars with new limits - LLLayoutPanel* last_resizeable_panel = NULL; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - LLLayoutPanel* panelp = (*panel_it); - S32 relevant_min = panelp->getRelevantMinDim(); + LLLayoutPanel* other_resize_panel = NULL; + LLLayoutPanel* following_panel = NULL; - if (mOrientation == HORIZONTAL) + BOOST_REVERSE_FOREACH(LLLayoutPanel* panelp, mPanels) + { + if (panelp->mAutoResize) { - (*panel_it)->mResizeBar->setResizeLimits( - relevant_min, - relevant_min + llround(shrink_headroom_total)); + total_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); + total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor(); } - else //VERTICAL + + if (panelp == resized_panel) { - (*panel_it)->mResizeBar->setResizeLimits( - relevant_min, - relevant_min + llround(shrink_headroom_total)); + other_resize_panel = following_panel; } - // toggle resize bars based on panel visibility, resizability, etc - BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize; - (*panel_it)->mResizeBar->setVisible(resize_bar_enabled); - - if ((*panel_it)->mUserResize || (*panel_it)->mAutoResize) + if (panelp->getVisible() && !panelp->mCollapsed) { - last_resizeable_panel = (*panel_it); + following_panel = panelp; } } - // hide last resize bar as there is nothing past it - // resize bars need to be in between two resizable panels - if (last_resizeable_panel) + if (resized_panel->mAutoResize == FALSE) { - last_resizeable_panel->mResizeBar->setVisible(FALSE); + delta_auto_resize_headroom += -delta_dim; } - - // not enough room to fit existing contents - if (force_resize == FALSE - // layout did not complete by reaching target position - && ((mOrientation == VERTICAL && llround(cur_y) != -mPanelSpacing) - || (mOrientation == HORIZONTAL && llround(cur_x) != getRect().getWidth() + mPanelSpacing))) + if (other_resize_panel && other_resize_panel->mAutoResize == FALSE) { - // do another layout pass with all stacked elements contributing - // even those that don't usually resize - llassert_always(force_resize == FALSE); - updateLayout(TRUE); + delta_auto_resize_headroom += delta_dim; } - mAnimatedThisFrame = true; -} // end LLLayoutStack::updateLayout + //delta_auto_resize_headroom = (total_visible_fraction > 0.f) + // ? delta_auto_resize_headroom / total_visible_fraction + // : 0.f; -LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const -{ - if (!panelp) return NULL; + F32 fraction_given_up = 0.f; + F32 fraction_remaining = 1.f; + F32 updated_auto_resize_headroom = total_auto_resize_headroom + delta_auto_resize_headroom; - e_panel_list_t::const_iterator panel_it; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + enum { - if ((*panel_it) == panelp) - { - return *panel_it; - } - } - return NULL; -} - -LLLayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const -{ - LLLayoutPanel* result = NULL; + BEFORE_RESIZED_PANEL, + RESIZED_PANEL, + NEXT_PANEL, + AFTER_RESIZED_PANEL + } which_panel = BEFORE_RESIZED_PANEL; - for (e_panel_list_t::const_iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) { - LLLayoutPanel* p = *panel_it; + if (!panelp->getVisible() || panelp->mCollapsed) continue; - if (p->getName() == name) + if (panelp == resized_panel) { - result = p; - break; + which_panel = RESIZED_PANEL; } - } - - return result; -} -// Compute sum of min_width or min_height of children -void LLLayoutStack::calcMinExtents() -{ - mMinWidth = 0; - mMinHeight = 0; - - e_panel_list_t::iterator panel_it; - for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) - { - if (mOrientation == HORIZONTAL) + switch(which_panel) { - mMinWidth += (*panel_it)->getRelevantMinDim(); - if (panel_it != mPanels.begin()) + case BEFORE_RESIZED_PANEL: + if (panelp->mAutoResize) + { // freeze current size as fraction of overall auto_resize space + F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom; + F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor, + 0.f, + MAX_FRACTIONAL_VALUE); + F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize); + fraction_given_up -= fraction_delta; + fraction_remaining -= panelp->mFractionalSize; + panelp->mFractionalSize += fraction_delta; + llassert(!llisnan(panelp->mFractionalSize)); + } + else { - mMinWidth += mPanelSpacing; + // leave non auto-resize panels alone } - } - else //VERTICAL - { - mMinHeight += (*panel_it)->getRelevantMinDim(); - if (panel_it != mPanels.begin()) + break; + case RESIZED_PANEL: + if (panelp->mAutoResize) + { // freeze new size as fraction + F32 new_fractional_size = (updated_auto_resize_headroom == 0.f) + ? 1.f + : llmin(MAX_FRACTIONAL_VALUE, ((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom)); + fraction_given_up -= new_fractional_size - panelp->mFractionalSize; + fraction_remaining -= panelp->mFractionalSize; + panelp->mFractionalSize = new_fractional_size; + llassert(!llisnan(panelp->mFractionalSize)); + } + else + { // freeze new size as original size + panelp->mTargetDim = new_dim; + fraction_remaining -= fraction_given_up; + } + which_panel = NEXT_PANEL; + break; + case NEXT_PANEL: + if (panelp->mAutoResize) + { + F32 new_fractional_size = (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom) + / updated_auto_resize_headroom; + fraction_given_up -= new_fractional_size - panelp->mFractionalSize; + fraction_remaining -= panelp->mFractionalSize; + panelp->mFractionalSize = new_fractional_size; + } + else + { + panelp->mTargetDim -= delta_dim; + } + which_panel = AFTER_RESIZED_PANEL; + break; + case AFTER_RESIZED_PANEL: + if (panelp->mAutoResize) { - mMinHeight += mPanelSpacing; + panelp->mFractionalSize += (panelp->mFractionalSize / fraction_remaining) * fraction_given_up; } + default: + break; } } } -void LLLayoutStack::createResizeBars() +void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent) { - for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + mNeedsLayout = true; + LLView::reshape(width, height, called_from_parent); +} + +void LLLayoutStack::updateResizeBarLimits() +{ + LLLayoutPanel* previous_visible_panelp = NULL; + BOOST_REVERSE_FOREACH(LLLayoutPanel* visible_panelp, mPanels) { - LLLayoutPanel* lp = (*panel_it); - if (lp->mResizeBar == NULL) + if (!visible_panelp->getVisible() || visible_panelp->mCollapsed) { - 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->getRelevantMinDim()); - resize_params.side(side); - resize_params.snapping_enabled(false); - LLResizeBar* resize_bar = LLUICtrlFactory::create(resize_params); - lp->mResizeBar = resize_bar; - LLView::addChild(resize_bar, 0); + visible_panelp->mResizeBar->setVisible(FALSE); + continue; + } - // 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); - } + // toggle resize bars based on panel visibility, resizability, etc + if (visible_panelp->mUserResize + && previous_visible_panelp + && previous_visible_panelp->mUserResize) + { + visible_panelp->mResizeBar->setVisible(TRUE); + visible_panelp->mResizeBar->setResizeLimits(visible_panelp->getRelevantMinDim(), + visible_panelp->getVisibleDim() + + (previous_visible_panelp->getVisibleDim() + - previous_visible_panelp->getRelevantMinDim())); + } + else + { + visible_panelp->mResizeBar->setVisible(FALSE); } - } -} -// update layout stack animations, etc. once per frame -// NOTE: we use this to size world view based on animating UI, *before* we draw the UI -// we might still need to call updateLayout during UI draw phase, in case UI elements -// are resizing themselves dynamically -//static -void LLLayoutStack::updateClass() -{ - for (instance_iter it = beginInstances(); it != endInstances(); ++it) - { - it->updateLayout(); + previous_visible_panelp = visible_panelp; } } diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 3b308a359d..a343e11cec 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2010, Linden Reshasearch, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -72,12 +72,11 @@ public: /*virtual*/ void removeChild(LLView*); /*virtual*/ BOOL postBuild(); /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); - S32 getMinWidth() const { return mMinWidth; } - S32 getMinHeight() const { return mMinHeight; } - typedef enum e_animate { NO_ANIMATE, @@ -85,47 +84,27 @@ public: } EAnimate; void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE); - void removePanel(LLPanel* panel); void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE); S32 getNumPanels() { return mPanels.size(); } - /** - * Moves panel_to_move before target_panel inside layout stack (both panels should already be there). - * If move_to_front is true target_panel is ignored and panel_to_move is moved to the beginning of mPanels - */ - void movePanel(LLPanel* panel_to_move, LLPanel* target_panel, bool move_to_front = false); void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize); void setPanelUserResize(const std::string& panel_name, BOOL user_resize); - /** - * Gets minimal dimension along layout_stack axis of the specified by name panel. - * - * @returns true if specified by panel_name internal panel exists, false otherwise. - */ - bool getPanelMinSize(const std::string& panel_name, S32* min_dimp); - - /** - * Gets maximal dimension along layout_stack axis of the specified by name panel. - * - * @returns true if specified by panel_name internal panel exists, false otherwise. - */ - bool getPanelMaxSize(const std::string& panel_name, S32* max_dim); - - void updateLayout(BOOL force_resize = FALSE); - + void updateLayout(); + S32 getPanelSpacing() const { return mPanelSpacing; } - BOOL getAnimate () const { return mAnimate; } - void setAnimate (BOOL animate) { mAnimate = animate; } static void updateClass(); protected: LLLayoutStack(const Params&); friend class LLUICtrlFactory; + friend class LLLayoutPanel; private: - void createResizeBars(); - void calcMinExtents(); + void updateResizeBarLimits(); + bool animatePanels(); + void createResizeBar(LLLayoutPanel* panel); const ELayoutOrientation mOrientation; @@ -134,9 +113,9 @@ private: LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const; LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const; + void updateFractionalSizes(); + void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect ); - S32 mMinWidth; // calculated by calcMinExtents - S32 mMinHeight; // calculated by calcMinExtents S32 mPanelSpacing; // true if we already applied animation this frame @@ -145,6 +124,7 @@ private: bool mClip; F32 mOpenTimeConstant; F32 mCloseTimeConstant; + bool mNeedsLayout; }; // end class LLLayoutStack @@ -156,8 +136,7 @@ public: struct Params : public LLInitParam::Block { Optional expanded_min_dim, - min_dim, - max_dim; + min_dim; Optional user_resize, auto_resize; @@ -168,14 +147,17 @@ public: void initFromParams(const Params& p); + void handleReshape(const LLRect& new_rect, bool by_user); + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + + void setVisible(BOOL visible); + S32 getLayoutDim() const; S32 getMinDim() const { return mMinDim; } void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; } - S32 getMaxDim() const { return mMaxDim; } - void setMaxDim(S32 value) { mMaxDim = value; } - S32 getExpandedMinDim() const { return mExpandedMinDim; } void setExpandedMinDim(S32 value) { mExpandedMinDim = value; mExpandedMinDimSpecified = true; } @@ -191,8 +173,14 @@ public: return min_dim; } - F32 getCollapseFactor(); - void setOrientation(LLLayoutStack::ELayoutOrientation orientation) { mOrientation = orientation; } + F32 getAutoResizeFactor() const; + F32 getVisibleAmount() const; + S32 getVisibleDim() const; + + void setOrientation(LLLayoutStack::ELayoutOrientation orientation); + void storeOriginalDim(); + + void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; } protected: LLLayoutPanel(const Params& p); @@ -201,13 +189,14 @@ protected: S32 mExpandedMinDim; S32 mMinDim; - S32 mMaxDim; bool mAutoResize; bool mUserResize; bool mCollapsed; F32 mVisibleAmt; F32 mCollapseAmt; F32 mFractionalSize; + S32 mTargetDim; + bool mIgnoreReshape; LLLayoutStack::ELayoutOrientation mOrientation; class LLResizeBar* mResizeBar; }; diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index 02f60c76fa..87aeb4d7a7 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -79,6 +79,8 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p) BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask) { + if (!canResize()) return FALSE; + // Route future Mouse messages here preemptively. (Release on mouse up.) // No handler needed for focus lost since this clas has no state that depends on it. gFocusMgr.setMouseCapture( this ); @@ -243,7 +245,7 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) handled = TRUE; } - if( handled ) + if( handled && canResize() ) { switch( mSide ) { diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 0725fbd846..6daf191918 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -70,6 +70,7 @@ public: void setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; } void setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; } void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; } + bool canResize() { return getEnabled() && mMaxSize > mMinSize; } private: S32 mDragLastScreenX; diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index ae8b30b1ba..a8bb29374e 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -176,12 +176,12 @@ void LLWindowShade::draw() { hide(); } - else if (notification_area->getCollapseFactor() < 0.01f) + else if (notification_area->getVisibleAmount() < 0.01f) { displayLatestNotification(); } - if (!notification_area->getVisible() && (notification_area->getCollapseFactor() < 0.001f)) + if (!notification_area->getVisible() && (notification_area->getVisibleAmount() < 0.001f)) { getChildRef("background_area").setBackgroundVisible(false); setMouseOpaque(false); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 42de47e777..f530d10ddc 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -621,7 +621,6 @@ void LLChatHistory::initFromParams(const LLChatHistory::Params& p) panel_p.has_border = false; panel_p.mouse_opaque = false; panel_p.min_dim = 30; - panel_p.max_dim = S32_MAX; panel_p.auto_resize = true; panel_p.user_resize = false; diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index a879651060..a32fd307f1 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -42,28 +42,6 @@ namespace { const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; - S32 get_panel_min_width(LLLayoutStack* stack, LLView* panel) - { - S32 minimal_width = 0; - llassert(stack); - if ( stack && panel && panel->getVisible() ) - { - stack->getPanelMinSize(panel->getName(), &minimal_width); - } - return minimal_width; - } - - S32 get_panel_max_width(LLLayoutStack* stack, LLPanel* panel) - { - S32 max_width = 0; - llassert(stack); - if ( stack && panel && panel->getVisible() ) - { - stack->getPanelMaxSize(panel->getName(), &max_width); - } - return max_width; - } - S32 get_curr_width(LLUICtrl* ctrl) { S32 cur_width = 0; @@ -234,15 +212,10 @@ void LLChicletBar::reshape(S32 width, S32 height, BOOL called_from_parent) { // Firstly, update layout stack to ensure we deal with correct panel sizes. { - BOOL saved_anim = mToolbarStack->getAnimate(); // Set chiclet panel to be autoresized by default. mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE); - // Disable animation to prevent layout updating in several frames. - mToolbarStack->setAnimate(FALSE); // Force the updating of layout to reset panels collapse factor. mToolbarStack->updateLayout(); - // Restore animate state. - mToolbarStack->setAnimate(saved_anim); } // chiclet bar is narrowed diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 29af81d64c..2681d4b34d 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -220,7 +220,7 @@ void LLFloaterNotificationConsole::addChannel(const std::string& name, bool open void LLFloaterNotificationConsole::removeChannel(const std::string& name) { LLPanel* panelp = getChild(name); - getChildRef("notification_channels").removePanel(panelp); + getChildRef("notification_channels").removeChild(panelp); delete panelp; updateResizeLimits(); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f5cda52d44..228260c41a 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -385,9 +385,6 @@ void LLIMFloater::onSlide() getChild("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible()); getChild("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible()); - - LLLayoutStack* stack = getChild("im_panels"); - if (stack) stack->setAnimate(true); } //static diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 9d069c3996..e40cc4662b 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -248,7 +248,6 @@ BOOL LLSidepanelInventory::postBuild() // Disable user_resize on main inventory panel by default inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false); - inv_stack->setPanelUserResize(INBOX_OUTBOX_LAYOUT_PANEL_NAME, false); // Collapse marketplace panel by default inv_stack->collapsePanel(getChild(INBOX_OUTBOX_LAYOUT_PANEL_NAME), true); diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml index d101bca694..cd075abc41 100644 --- a/indra/newview/skins/default/xui/en/floater_help_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml @@ -34,7 +34,6 @@ left_delta="0" top_delta="0" name="external_controls" - user_resize="false" width="620"> + auto_resize="false"> " + // which equates to the following nesting: + // button + // param + // nested_param1 + // nested_param2 + // nested_param3 + mCurReadDepth++; + for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();) + { + std::string child_name(childp->getName()->mString); + S32 num_tokens_pushed = 0; + + // for non "dotted" child nodes check to see if child node maps to another widget type + // and if not, treat as a child element of the current node + // e.g. will interpret as "button.rect" + // since there is no widget named "rect" + if (child_name.find(".") == std::string::npos) + { + mNameStack.push_back(std::make_pair(child_name, true)); + num_tokens_pushed++; + } + else + { + // parse out "dotted" name into individual tokens + tokenizer name_tokens(child_name, sep); + + tokenizer::iterator name_token_it = name_tokens.begin(); + if(name_token_it == name_tokens.end()) + { + childp = childp->getNextSibling(); + continue; + } + + // check for proper nesting + if (mNameStack.empty()) + { + if (*name_token_it != mRootNodeName) + { + childp = childp->getNextSibling(); + continue; + } + } + else if(mNameStack.back().first != *name_token_it) + { + childp = childp->getNextSibling(); + continue; + } + + // now ignore first token + ++name_token_it; + + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, true)); + num_tokens_pushed++; + } + } + + // recurse and visit children XML nodes + if(readXUIImpl(childp, block)) + { + // child node successfully parsed, remove from DOM + + values_parsed = true; + LLXMLNodePtr node_to_remove = childp; + childp = childp->getNextSibling(); + + nodep->deleteChild(node_to_remove); + } + else + { + childp = childp->getNextSibling(); + } + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } + } + mCurReadDepth--; + return values_parsed; +} + +bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) +{ + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); + + bool any_parsed = false; + bool silent = mCurReadDepth > 0; + + for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin(); + attribute_it != nodep->mAttributes.end(); + ++attribute_it) + { + S32 num_tokens_pushed = 0; + std::string attribute_name(attribute_it->first->mString); + mCurReadNode = attribute_it->second; + + tokenizer name_tokens(attribute_name, sep); + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, true)); + num_tokens_pushed++; + } + + // child nodes are not necessarily valid attributes, so don't complain once we've recursed + any_parsed |= block.submitValue(mNameStack, *this, silent); + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } + } + + return any_parsed; +} + +void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block) +{ + mWriteRootNode = node; + name_stack_t name_stack = Parser::name_stack_t(); + block.serializeBlock(*this, name_stack, diff_block); + mOutNodes.clear(); +} + +// go from a stack of names to a specific XML node +LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack) +{ + LLXMLNodePtr out_node = mWriteRootNode; + + name_stack_t::iterator next_it = stack.begin(); + for (name_stack_t::iterator it = stack.begin(); + it != stack.end(); + it = next_it) + { + ++next_it; + if (it->first.empty()) + { + it->second = false; + continue; + } + + out_nodes_t::iterator found_it = mOutNodes.find(it->first); + + // node with this name not yet written + if (found_it == mOutNodes.end() || it->second) + { + // make an attribute if we are the last element on the name stack + bool is_attribute = next_it == stack.end(); + LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute); + out_node->addChild(new_node); + mOutNodes[it->first] = new_node; + out_node = new_node; + it->second = false; + } + else + { + out_node = found_it->second; + } + } + + return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node); +} + +bool LLXUIParser::readFlag(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode == DUMMY_NODE; +} + +bool LLXUIParser::writeFlag(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + // just create node + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + return node.notNull(); +} + +bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr) +{ + S32 value; + LLXUIParser& self = static_cast(parser); + bool success = self.mCurReadNode->getBoolValue(1, &value); + *((bool*)val_ptr) = (value != FALSE); + return success; +} + +bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setBoolValue(*((bool*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + *((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue(); + return true; +} + +bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + const std::string* string_val = reinterpret_cast(val_ptr); + if (string_val->find('\n') != std::string::npos + || string_val->size() > MAX_STRING_ATTRIBUTE_SIZE) + { + // don't write strings with newlines into attributes + std::string attribute_name = node->getName()->mString; + LLXMLNodePtr parent_node = node->mParent; + parent_node->deleteChild(node); + // write results in text contents of node + if (attribute_name == "value") + { + // "value" is implicit, just write to parent + node = parent_node; + } + else + { + // create a child that is not an attribute, but with same name + node = parent_node->createChild(attribute_name.c_str(), false); + } + } + node->setStringValue(*string_val); + return true; + } + return false; +} + +bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getByteValue(1, (U8*)val_ptr); +} + +bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setUnsignedValue(*((U8*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + S32 value; + if(self.mCurReadNode->getIntValue(1, &value)) + { + *((S8*)val_ptr) = value; + return true; + } + return false; +} + +bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setIntValue(*((S8*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + U32 value; + if(self.mCurReadNode->getUnsignedValue(1, &value)) + { + *((U16*)val_ptr) = value; + return true; + } + return false; +} + +bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setUnsignedValue(*((U16*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + S32 value; + if(self.mCurReadNode->getIntValue(1, &value)) + { + *((S16*)val_ptr) = value; + return true; + } + return false; +} + +bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setIntValue(*((S16*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr); +} + +bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setUnsignedValue(*((U32*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getIntValue(1, (S32*)val_ptr); +} + +bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setIntValue(*((S32*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr); +} + +bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setFloatValue(*((F32*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr); +} + +bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setDoubleValue(*((F64*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + LLColor4* colorp = (LLColor4*)val_ptr; + if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3) + { + return true; + } + + return false; +} + +bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + LLColor4 color = *((LLColor4*)val_ptr); + node->setFloatValue(4, color.mV); + return true; + } + return false; +} + +bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + LLUIColor* param = (LLUIColor*)val_ptr; + LLColor4 color; + bool success = self.mCurReadNode->getFloatValue(4, color.mV) >= 3; + if (success) + { + param->set(color); + return true; + } + return false; +} + +bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + LLUIColor color = *((LLUIColor*)val_ptr); + //RN: don't write out the color that is represented by a function + // rely on param block exporting to get the reference to the color settings + if (color.isReference()) return false; + node->setFloatValue(4, color.get().mV); + return true; + } + return false; +} + +bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + LLUUID temp_id; + // LLUUID::set is destructive, so use temporary value + if (temp_id.set(self.mCurReadNode->getSanitizedValue())) + { + *(LLUUID*)(val_ptr) = temp_id; + return true; + } + return false; +} + +bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setStringValue(((LLUUID*)val_ptr)->asString()); + return true; + } + return false; +} + +bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + *((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue()); + return true; +} + +bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + std::string string_val = ((LLSD*)val_ptr)->asString(); + if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE) + { + // don't write strings with newlines into attributes + std::string attribute_name = node->getName()->mString; + LLXMLNodePtr parent_node = node->mParent; + parent_node->deleteChild(node); + // write results in text contents of node + if (attribute_name == "value") + { + // "value" is implicit, just write to parent + node = parent_node; + } + else + { + node = parent_node->createChild(attribute_name.c_str(), false); + } + } + + node->setStringValue(string_val); + return true; + } + return false; +} + +/*virtual*/ std::string LLXUIParser::getCurrentElementName() +{ + std::string full_name; + for (name_stack_t::iterator it = mNameStack.begin(); + it != mNameStack.end(); + ++it) + { + full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." + } + + return full_name; +} + +void LLXUIParser::parserWarning(const std::string& message) +{ +#ifdef LL_WINDOWS + // use Visual Studo friendly formatting of output message for easy access to originating xml + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); + utf16str += '\n'; + OutputDebugString(utf16str.c_str()); +#else + Parser::parserWarning(message); +#endif +} + +void LLXUIParser::parserError(const std::string& message) +{ +#ifdef LL_WINDOWS + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); + utf16str += '\n'; + OutputDebugString(utf16str.c_str()); +#else + Parser::parserError(message); +#endif +} + + +// +// LLSimpleXUIParser +// + +struct ScopedFile +{ + ScopedFile( const std::string& filename, const char* accessmode ) + { + mFile = LLFile::fopen(filename, accessmode); + } + + ~ScopedFile() + { + fclose(mFile); + mFile = NULL; + } + + S32 getRemainingBytes() + { + if (!isOpen()) return 0; + + S32 cur_pos = ftell(mFile); + fseek(mFile, 0L, SEEK_END); + S32 file_size = ftell(mFile); + fseek(mFile, cur_pos, SEEK_SET); + return file_size - cur_pos; + } + + bool isOpen() { return mFile != NULL; } + + LLFILE* mFile; +}; +LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb) +: Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs), + mCurReadDepth(0), + mElementCB(element_cb) +{ + if (sSimpleXUIReadFuncs.empty()) + { + registerParserFuncs(readFlag); + registerParserFuncs(readBoolValue); + registerParserFuncs(readStringValue); + registerParserFuncs(readU8Value); + registerParserFuncs(readS8Value); + registerParserFuncs(readU16Value); + registerParserFuncs(readS16Value); + registerParserFuncs(readU32Value); + registerParserFuncs(readS32Value); + registerParserFuncs(readF32Value); + registerParserFuncs(readF64Value); + registerParserFuncs(readColor4Value); + registerParserFuncs(readUIColorValue); + registerParserFuncs(readUUIDValue); + registerParserFuncs(readSDValue); + } +} + +LLSimpleXUIParser::~LLSimpleXUIParser() +{ +} + + +bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent) +{ + LLFastTimer timer(FTM_PARSE_XUI); + + mParser = XML_ParserCreate(NULL); + XML_SetUserData(mParser, this); + XML_SetElementHandler( mParser, startElementHandler, endElementHandler); + XML_SetCharacterDataHandler( mParser, characterDataHandler); + + mOutputStack.push_back(std::make_pair(&block, 0)); + mNameStack.clear(); + mCurFileName = filename; + mCurReadDepth = 0; + setParseSilently(silent); + + ScopedFile file(filename, "rb"); + if( !file.isOpen() ) + { + LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL; + XML_ParserFree( mParser ); + return false; + } + + S32 bytes_read = 0; + + S32 buffer_size = file.getRemainingBytes(); + void* buffer = XML_GetBuffer(mParser, buffer_size); + if( !buffer ) + { + LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL; + XML_ParserFree( mParser ); + return false; + } + + bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile); + if( bytes_read <= 0 ) + { + LL_WARNS("ReadXUI") << "Error while reading file " << filename << LL_ENDL; + XML_ParserFree( mParser ); + return false; + } + + mEmptyLeafNode.push_back(false); + + if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) ) + { + LL_WARNS("ReadXUI") << "Error while parsing file " << filename << LL_ENDL; + XML_ParserFree( mParser ); + return false; + } + + mEmptyLeafNode.pop_back(); + + XML_ParserFree( mParser ); + return true; +} + +void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts) +{ + LLSimpleXUIParser* self = reinterpret_cast(userData); + self->startElement(name, atts); +} + +void LLSimpleXUIParser::endElementHandler(void *userData, const char *name) +{ + LLSimpleXUIParser* self = reinterpret_cast(userData); + self->endElement(name); +} + +void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len) +{ + LLSimpleXUIParser* self = reinterpret_cast(userData); + self->characterData(s, len); +} + +void LLSimpleXUIParser::characterData(const char *s, int len) +{ + mTextContents += std::string(s, len); +} + +void LLSimpleXUIParser::startElement(const char *name, const char **atts) +{ + processText(); + + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); + + if (mElementCB) + { + LLInitParam::BaseBlock* blockp = mElementCB(*this, name); + if (blockp) + { + mOutputStack.push_back(std::make_pair(blockp, 0)); + } + } + + mOutputStack.back().second++; + S32 num_tokens_pushed = 0; + std::string child_name(name); + + if (mOutputStack.back().second == 1) + { // root node for this block + mScope.push_back(child_name); + } + else + { // compound attribute + if (child_name.find(".") == std::string::npos) + { + mNameStack.push_back(std::make_pair(child_name, true)); + num_tokens_pushed++; + mScope.push_back(child_name); + } + else + { + // parse out "dotted" name into individual tokens + tokenizer name_tokens(child_name, sep); + + tokenizer::iterator name_token_it = name_tokens.begin(); + if(name_token_it == name_tokens.end()) + { + return; + } + + // check for proper nesting + if(!mScope.empty() && *name_token_it != mScope.back()) + { + return; + } + + // now ignore first token + ++name_token_it; + + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, true)); + num_tokens_pushed++; + } + mScope.push_back(mNameStack.back().first); + } + } + + // parent node is not empty + mEmptyLeafNode.back() = false; + // we are empty if we have no attributes + mEmptyLeafNode.push_back(atts[0] == NULL); + + mTokenSizeStack.push_back(num_tokens_pushed); + readAttributes(atts); + +} + +void LLSimpleXUIParser::endElement(const char *name) +{ + bool has_text = processText(); + + // no text, attributes, or children + if (!has_text && mEmptyLeafNode.back()) + { + // submit this as a valueless name (even though there might be text contents we haven't seen yet) + mCurAttributeValueBegin = NO_VALUE_MARKER; + mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); + } + + if (--mOutputStack.back().second == 0) + { + if (mOutputStack.empty()) + { + LL_ERRS("ReadXUI") << "Parameter block output stack popped while empty." << LL_ENDL; + } + mOutputStack.pop_back(); + } + + S32 num_tokens_to_pop = mTokenSizeStack.back(); + mTokenSizeStack.pop_back(); + while(num_tokens_to_pop-- > 0) + { + mNameStack.pop_back(); + } + mScope.pop_back(); + mEmptyLeafNode.pop_back(); +} + +bool LLSimpleXUIParser::readAttributes(const char **atts) +{ + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); + + bool any_parsed = false; + for(S32 i = 0; atts[i] && atts[i+1]; i += 2 ) + { + std::string attribute_name(atts[i]); + mCurAttributeValueBegin = atts[i+1]; + + S32 num_tokens_pushed = 0; + tokenizer name_tokens(attribute_name, sep); + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, true)); + num_tokens_pushed++; + } + + // child nodes are not necessarily valid attributes, so don't complain once we've recursed + any_parsed |= mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } + } + return any_parsed; +} + +bool LLSimpleXUIParser::processText() +{ + if (!mTextContents.empty()) + { + LLStringUtil::trim(mTextContents); + if (!mTextContents.empty()) + { + mNameStack.push_back(std::make_pair(std::string("value"), true)); + mCurAttributeValueBegin = mTextContents.c_str(); + mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); + mNameStack.pop_back(); + } + mTextContents.clear(); + return true; + } + return false; +} + +/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName() +{ + std::string full_name; + for (name_stack_t::iterator it = mNameStack.begin(); + it != mNameStack.end(); + ++it) + { + full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." + } + + return full_name; +} + +void LLSimpleXUIParser::parserWarning(const std::string& message) +{ +#ifdef LL_WINDOWS + // use Visual Studo friendly formatting of output message for easy access to originating xml + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str()); + utf16str += '\n'; + OutputDebugString(utf16str.c_str()); +#else + Parser::parserWarning(message); +#endif +} + +void LLSimpleXUIParser::parserError(const std::string& message) +{ +#ifdef LL_WINDOWS + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str()); + utf16str += '\n'; + OutputDebugString(utf16str.c_str()); +#else + Parser::parserError(message); +#endif +} + +bool LLSimpleXUIParser::readFlag(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return self.mCurAttributeValueBegin == NO_VALUE_MARKER; +} + +bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + if (!strcmp(self.mCurAttributeValueBegin, "true")) + { + *((bool*)val_ptr) = true; + return true; + } + else if (!strcmp(self.mCurAttributeValueBegin, "false")) + { + *((bool*)val_ptr) = false; + return true; + } + + return false; +} + +bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + *((std::string*)val_ptr) = self.mCurAttributeValueBegin; + return true; +} + +bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + LLColor4 value; + + if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) + { + *(LLColor4*)(val_ptr) = value; + return true; + } + return false; +} + +bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + LLColor4 value; + LLUIColor* colorp = (LLUIColor*)val_ptr; + + if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) + { + colorp->set(value); + return true; + } + return false; +} + +bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + LLUUID temp_id; + // LLUUID::set is destructive, so use temporary value + if (temp_id.set(std::string(self.mCurAttributeValueBegin))) + { + *(LLUUID*)(val_ptr) = temp_id; + return true; + } + return false; +} + +bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + *((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin); + return true; +} diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h new file mode 100644 index 0000000000..d7cd256967 --- /dev/null +++ b/indra/llui/llxuiparser.h @@ -0,0 +1,242 @@ +/** + * @file llxuiparser.h + * @brief Utility functions for handling XUI structures in XML + * + * $LicenseInfo:firstyear=2003&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 LLXUIPARSER_H +#define LLXUIPARSER_H + +#include "llinitparam.h" +#include "llregistry.h" +#include "llpointer.h" + +#include +#include +#include +#include + + + +class LLView; + + +typedef LLPointer LLXMLNodePtr; + + +// lookup widget type by name +class LLWidgetTypeRegistry +: public LLRegistrySingleton +{}; + + +// global static instance for registering all widget types +typedef boost::function LLWidgetCreatorFunc; + +typedef LLRegistry widget_registry_t; + +class LLChildRegistryRegistry +: public LLRegistrySingleton +{}; + + + +class LLXSDWriter : public LLInitParam::Parser +{ + LOG_CLASS(LLXSDWriter); +public: + void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); + + /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } + + LLXSDWriter(); + +protected: + void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector* possible_values); + void addAttributeToSchema(LLXMLNodePtr nodep, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector* possible_values); + LLXMLNodePtr mAttributeNode; + LLXMLNodePtr mElementNode; + LLXMLNodePtr mSchemaNode; + + typedef std::set string_set_t; + typedef std::map attributes_map_t; + attributes_map_t mAttributesWritten; +}; + + + +// NOTE: DOES NOT WORK YET +// should support child widgets for XUI +class LLXUIXSDWriter : public LLXSDWriter +{ +public: + void writeXSD(const std::string& name, const std::string& path, const LLInitParam::BaseBlock& block); +}; + + +class LLXUIParserImpl; + +class LLXUIParser : public LLInitParam::Parser +{ +LOG_CLASS(LLXUIParser); + +public: + LLXUIParser(); + typedef LLInitParam::Parser::name_stack_t name_stack_t; + + /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ void parserWarning(const std::string& message); + /*virtual*/ void parserError(const std::string& message); + + void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false); + void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL); + +private: + bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block); + bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block); + + //reader helper functions + static bool readFlag(Parser& parser, void* val_ptr); + static bool readBoolValue(Parser& parser, void* val_ptr); + static bool readStringValue(Parser& parser, void* val_ptr); + static bool readU8Value(Parser& parser, void* val_ptr); + static bool readS8Value(Parser& parser, void* val_ptr); + static bool readU16Value(Parser& parser, void* val_ptr); + static bool readS16Value(Parser& parser, void* val_ptr); + static bool readU32Value(Parser& parser, void* val_ptr); + static bool readS32Value(Parser& parser, void* val_ptr); + static bool readF32Value(Parser& parser, void* val_ptr); + static bool readF64Value(Parser& parser, void* val_ptr); + static bool readColor4Value(Parser& parser, void* val_ptr); + static bool readUIColorValue(Parser& parser, void* val_ptr); + static bool readUUIDValue(Parser& parser, void* val_ptr); + static bool readSDValue(Parser& parser, void* val_ptr); + + //writer helper functions + static bool writeFlag(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeStringValue(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeU8Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeS8Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeU16Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeS16Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeU32Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeSDValue(Parser& parser, const void* val_ptr, name_stack_t&); + + LLXMLNodePtr getNode(name_stack_t& stack); + +private: + Parser::name_stack_t mNameStack; + LLXMLNodePtr mCurReadNode; + // Root of the widget XML sub-tree, for example, "line_editor" + LLXMLNodePtr mWriteRootNode; + + typedef std::map out_nodes_t; + out_nodes_t mOutNodes; + LLXMLNodePtr mLastWrittenChild; + S32 mCurReadDepth; + std::string mCurFileName; + std::string mRootNodeName; +}; + +// LLSimpleXUIParser is a streamlined SAX-based XUI parser that does not support localization +// or parsing of a tree of independent param blocks, such as child widgets. +// Use this for reading non-localized files that only need a single param block as a result. +// +// NOTE: In order to support nested block parsing, we need callbacks for start element that +// push new blocks contexts on the mScope stack. +// NOTE: To support localization without building a DOM, we need to enforce consistent +// ordering of child elements from base file to localized diff file. Then we can use a pair +// of coroutines to perform matching of xml nodes during parsing. Not sure if the overhead +// of coroutines would offset the gain from SAX parsing +class LLSimpleXUIParserImpl; + +class LLSimpleXUIParser : public LLInitParam::Parser +{ +LOG_CLASS(LLSimpleXUIParser); +public: + typedef LLInitParam::Parser::name_stack_t name_stack_t; + typedef LLInitParam::BaseBlock* (*element_start_callback_t)(LLSimpleXUIParser&, const char* block_name); + + LLSimpleXUIParser(element_start_callback_t element_cb = NULL); + virtual ~LLSimpleXUIParser(); + + /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ void parserWarning(const std::string& message); + /*virtual*/ void parserError(const std::string& message); + + bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false); + + +private: + //reader helper functions + static bool readFlag(Parser&, void* val_ptr); + static bool readBoolValue(Parser&, void* val_ptr); + static bool readStringValue(Parser&, void* val_ptr); + static bool readU8Value(Parser&, void* val_ptr); + static bool readS8Value(Parser&, void* val_ptr); + static bool readU16Value(Parser&, void* val_ptr); + static bool readS16Value(Parser&, void* val_ptr); + static bool readU32Value(Parser&, void* val_ptr); + static bool readS32Value(Parser&, void* val_ptr); + static bool readF32Value(Parser&, void* val_ptr); + static bool readF64Value(Parser&, void* val_ptr); + static bool readColor4Value(Parser&, void* val_ptr); + static bool readUIColorValue(Parser&, void* val_ptr); + static bool readUUIDValue(Parser&, void* val_ptr); + static bool readSDValue(Parser&, void* val_ptr); + +private: + static void startElementHandler(void *userData, const char *name, const char **atts); + static void endElementHandler(void *userData, const char *name); + static void characterDataHandler(void *userData, const char *s, int len); + + void startElement(const char *name, const char **atts); + void endElement(const char *name); + void characterData(const char *s, int len); + bool readAttributes(const char **atts); + bool processText(); + + Parser::name_stack_t mNameStack; + struct XML_ParserStruct* mParser; + LLXMLNodePtr mLastWrittenChild; + S32 mCurReadDepth; + std::string mCurFileName; + std::string mTextContents; + const char* mCurAttributeValueBegin; + std::vector mTokenSizeStack; + std::vector mScope; + std::vector mEmptyLeafNode; + element_start_callback_t mElementCB; + + std::vector > mOutputStack; +}; + + +#endif //LLXUIPARSER_H diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index c75df86891..cb3b7abb14 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -105,28 +105,6 @@ LLStyle::Params::Params() namespace LLInitParam { - Param::Param(BaseBlock* enclosing_block) - : mIsProvided(false) - { - const U8* my_addr = reinterpret_cast(this); - const U8* block_addr = reinterpret_cast(enclosing_block); - mEnclosingBlockOffset = (U16)(my_addr - block_addr); - } - - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} - void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} - 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, bool new_name){ return true; } - void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const {} - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_value, S32 max_value) const { return true; } - bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } - bool BaseBlock::validateBlock(bool emit_errors) const { return true; } - ParamValue >::ParamValue(const LLUIColor& color) : super_t(color) {} diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index c1fb050206..8f0a48018f 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -70,21 +70,6 @@ S32 LLUIImage::getHeight() const return 0; } -namespace LLInitParam -{ - BlockDescriptor::BlockDescriptor() {} - ParamDescriptor::ParamDescriptor(param_handle_t p, - merge_func_t merge_func, - deserialize_func_t deserialize_func, - serialize_func_t serialize_func, - validation_func_t validation_func, - inspect_func_t inspect_func, - S32 min_count, - S32 max_count){} - ParamDescriptor::~ParamDescriptor() {} - -} - namespace tut { struct LLUrlEntryData diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 7183413463..963473c92a 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -63,40 +63,6 @@ S32 LLUIImage::getHeight() const namespace LLInitParam { - BlockDescriptor::BlockDescriptor() {} - ParamDescriptor::ParamDescriptor(param_handle_t p, - merge_func_t merge_func, - deserialize_func_t deserialize_func, - serialize_func_t serialize_func, - validation_func_t validation_func, - inspect_func_t inspect_func, - S32 min_count, - S32 max_count){} - ParamDescriptor::~ParamDescriptor() {} - - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} - param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} - void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} - - 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(this); - const U8* block_addr = reinterpret_cast(enclosing_block); - mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr)); - } - - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; } - void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const {} - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const { return true; } - bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } - bool BaseBlock::validateBlock(bool emit_errors) const { return true; } - ParamValue >::ParamValue(const LLUIColor& color) : super_t(color) {} diff --git a/indra/llxuixml/CMakeLists.txt b/indra/llxuixml/CMakeLists.txt deleted file mode 100644 index daed4de6ce..0000000000 --- a/indra/llxuixml/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -# -*- cmake -*- - -project(llxuixml) - -include(00-Common) -include(LLCommon) -include(LLMath) -include(LLXML) - -include_directories( - ${LLCOMMON_INCLUDE_DIRS} - ${LLMATH_INCLUDE_DIRS} - ${LLXML_INCLUDE_DIRS} - ) - -set(llxuixml_SOURCE_FILES - llinitparam.cpp - lltrans.cpp - lluicolor.cpp - llxuiparser.cpp - ) - -set(llxuixml_HEADER_FILES - CMakeLists.txt - - llinitparam.h - lltrans.h - llregistry.h - lluicolor.h - llxuiparser.h - ) - -set_source_files_properties(${llxuixml_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND llxuixml_SOURCE_FILES ${llxuixml_HEADER_FILES}) - -add_library (llxuixml ${llxuixml_SOURCE_FILES}) -# Libraries on which this library depends, needed for Linux builds -# Sort by high-level to low-level -target_link_libraries(llxuixml - llxml - llcommon - llmath - ) diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp deleted file mode 100644 index db72aa19b9..0000000000 --- a/indra/llxuixml/llinitparam.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/** - * @file llinitparam.cpp - * @brief parameter block abstraction for creating complex objects and - * parsing construction parameters from xml and LLSD - * - * $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$ - */ - -#include "linden_common.h" - -#include "llinitparam.h" - - -namespace LLInitParam -{ - // - // Param - // - Param::Param(BaseBlock* enclosing_block) - : mIsProvided(false) - { - const U8* my_addr = reinterpret_cast(this); - const U8* block_addr = reinterpret_cast(enclosing_block); - mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr); - } - - // - // ParamDescriptor - // - ParamDescriptor::ParamDescriptor(param_handle_t p, - merge_func_t merge_func, - deserialize_func_t deserialize_func, - serialize_func_t serialize_func, - validation_func_t validation_func, - inspect_func_t inspect_func, - S32 min_count, - S32 max_count) - : mParamHandle(p), - mMergeFunc(merge_func), - mDeserializeFunc(deserialize_func), - mSerializeFunc(serialize_func), - mValidationFunc(validation_func), - mInspectFunc(inspect_func), - mMinCount(min_count), - mMaxCount(max_count), - mUserData(NULL) - {} - - ParamDescriptor::ParamDescriptor() - : mParamHandle(0), - mMergeFunc(NULL), - mDeserializeFunc(NULL), - mSerializeFunc(NULL), - mValidationFunc(NULL), - mInspectFunc(NULL), - mMinCount(0), - mMaxCount(0), - mUserData(NULL) - {} - - ParamDescriptor::~ParamDescriptor() - { - delete mUserData; - } - - // - // Parser - // - Parser::~Parser() - {} - - void Parser::parserWarning(const std::string& message) - { - if (mParseSilently) return; - llwarns << message << llendl; - } - - void Parser::parserError(const std::string& message) - { - if (mParseSilently) return; - llerrs << message << llendl; - } - - - // - // BlockDescriptor - // - void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data) - { - mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end()); - std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams)); - std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList)); - std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams)); - } - - BlockDescriptor::BlockDescriptor() - : mMaxParamOffset(0), - mInitializationState(UNINITIALIZED), - mCurrentBlockPtr(NULL) - {} - - // called by each derived class in least to most derived order - void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size) - { - descriptor.mCurrentBlockPtr = this; - descriptor.mMaxParamOffset = block_size; - - switch(descriptor.mInitializationState) - { - case BlockDescriptor::UNINITIALIZED: - // copy params from base class here - descriptor.aggregateBlockData(base_descriptor); - - descriptor.mInitializationState = BlockDescriptor::INITIALIZING; - break; - case BlockDescriptor::INITIALIZING: - descriptor.mInitializationState = BlockDescriptor::INITIALIZED; - break; - case BlockDescriptor::INITIALIZED: - // nothing to do - break; - } - } - - param_handle_t BaseBlock::getHandleFromParam(const Param* param) const - { - const U8* param_address = reinterpret_cast(param); - const U8* baseblock_address = reinterpret_cast(this); - return (param_address - baseblock_address); - } - - bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent) - { - if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true)) - { - if (!silent) - { - p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str())); - } - return false; - } - return true; - } - - - bool BaseBlock::validateBlock(bool emit_errors) const - { - const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it) - { - const Param* param = getParamFromHandle(it->first); - if (!it->second(param)) - { - if (emit_errors) - { - llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl; - } - return false; - } - } - return true; - } - - void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const - { - // named param is one like LLView::Params::follows - // unnamed param is like LLView::Params::rect - implicit - const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - - for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); - it != block_data.mUnnamedParams.end(); - ++it) - { - param_handle_t param_handle = (*it)->mParamHandle; - const Param* param = getParamFromHandle(param_handle); - ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc; - if (serialize_func) - { - const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - // each param descriptor remembers its serial number - // so we can inspect the same param under different names - // and see that it has the same number - name_stack.push_back(std::make_pair("", true)); - serialize_func(*param, parser, name_stack, diff_param); - name_stack.pop_back(); - } - } - - for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); - it != block_data.mNamedParams.end(); - ++it) - { - param_handle_t param_handle = it->second->mParamHandle; - const Param* param = getParamFromHandle(param_handle); - ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc; - if (serialize_func && param->anyProvided()) - { - // Ensure this param has not already been serialized - // Prevents from being serialized as its own tag. - bool duplicate = false; - for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); - it2 != block_data.mUnnamedParams.end(); - ++it2) - { - if (param_handle == (*it2)->mParamHandle) - { - duplicate = true; - break; - } - } - - //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers - // don't know how to detect them - if (duplicate) - { - continue; - } - - name_stack.push_back(std::make_pair(it->first, !duplicate)); - const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - serialize_func(*param, parser, name_stack, diff_param); - name_stack.pop_back(); - } - } - } - - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const - { - // named param is one like LLView::Params::follows - // unnamed param is like LLView::Params::rect - implicit - const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - - for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); - it != block_data.mUnnamedParams.end(); - ++it) - { - param_handle_t param_handle = (*it)->mParamHandle; - const Param* param = getParamFromHandle(param_handle); - ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc; - if (inspect_func) - { - name_stack.push_back(std::make_pair("", true)); - inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount); - name_stack.pop_back(); - } - } - - for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); - it != block_data.mNamedParams.end(); - ++it) - { - param_handle_t param_handle = it->second->mParamHandle; - const Param* param = getParamFromHandle(param_handle); - ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc; - if (inspect_func) - { - // Ensure this param has not already been inspected - bool duplicate = false; - for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); - it2 != block_data.mUnnamedParams.end(); - ++it2) - { - if (param_handle == (*it2)->mParamHandle) - { - duplicate = true; - break; - } - } - - name_stack.push_back(std::make_pair(it->first, !duplicate)); - inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount); - name_stack.pop_back(); - } - } - - return true; - } - - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored) - { - BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - bool names_left = name_stack_range.first != name_stack_range.second; - - bool new_name = names_left - ? name_stack_range.first->second - : true; - - if (names_left) - { - const std::string& top_name = name_stack_range.first->first; - - ParamDescriptor::deserialize_func_t deserialize_func = NULL; - Param* paramp = NULL; - - BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name); - if (found_it != block_data.mNamedParams.end()) - { - // find pointer to member parameter from offset table - paramp = getParamFromHandle(found_it->second->mParamHandle); - deserialize_func = found_it->second->mDeserializeFunc; - - Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second); - ++new_name_stack.first; - if (deserialize_func(*paramp, p, new_name_stack, new_name)) - { - // value is no longer new, we know about it now - name_stack_range.first->second = false; - return true; - } - else - { - return false; - } - } - } - - // try to parse unnamed parameters, in declaration order - for ( BlockDescriptor::param_list_t::iterator it = block_data.mUnnamedParams.begin(); - it != block_data.mUnnamedParams.end(); - ++it) - { - Param* paramp = getParamFromHandle((*it)->mParamHandle); - ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc; - - if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name)) - { - return true; - } - } - - // if no match, and no names left on stack, this is just an existence assertion of this block - // verify by calling readValue with NoParamValue type, an inherently unparseable type - if (!names_left) - { - Flag no_value; - return p.readValue(no_value); - } - - return false; - } - - //static - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) - { - // create a copy of the param descriptor in mAllParams - // so other data structures can store a pointer to it - block_data.mAllParams.push_back(in_param); - ParamDescriptorPtr param(block_data.mAllParams.back()); - - std::string name(char_name); - if ((size_t)param->mParamHandle > block_data.mMaxParamOffset) - { - llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block" << llendl; - } - - if (name.empty()) - { - block_data.mUnnamedParams.push_back(param); - } - else - { - // don't use insert, since we want to overwrite existing entries - block_data.mNamedParams[name] = param; - } - - if (param->mValidationFunc) - { - block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); - } - } - - void BaseBlock::addSynonym(Param& param, const std::string& synonym) - { - BlockDescriptor& block_data = mostDerivedBlockDescriptor(); - if (block_data.mInitializationState == BlockDescriptor::INITIALIZING) - { - param_handle_t handle = getHandleFromParam(¶m); - - // check for invalid derivation from a paramblock (i.e. without using - // Block - if ((size_t)handle > block_data.mMaxParamOffset) - { - llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block" << llendl; - } - - ParamDescriptorPtr param_descriptor = findParamDescriptor(param); - if (param_descriptor) - { - if (synonym.empty()) - { - block_data.mUnnamedParams.push_back(param_descriptor); - } - else - { - block_data.mNamedParams[synonym] = param_descriptor; - } - } - } - } - - const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const - { - param_handle_t handle = getHandleFromParam(paramp); - for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it) - { - if (it->second->mParamHandle == handle) - { - return it->first; - } - } - - return LLStringUtil::null; - } - - ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param) - { - param_handle_t handle = getHandleFromParam(¶m); - BlockDescriptor& descriptor = mostDerivedBlockDescriptor(); - BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end(); - for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin(); - it != end_it; - ++it) - { - if ((*it)->mParamHandle == handle) return *it; - } - return ParamDescriptorPtr(); - } - - // take all provided params from other and apply to self - // NOTE: this requires that "other" is of the same derived type as this - bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) - { - bool some_param_changed = false; - BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end(); - for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin(); - it != end_it; - ++it) - { - const Param* other_paramp = other.getParamFromHandle((*it)->mParamHandle); - ParamDescriptor::merge_func_t merge_func = (*it)->mMergeFunc; - if (merge_func) - { - Param* paramp = getParamFromHandle((*it)->mParamHandle); - llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle); - some_param_changed |= merge_func(*paramp, *other_paramp, overwrite); - } - } - return some_param_changed; - } -} diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h deleted file mode 100644 index ab20957760..0000000000 --- a/indra/llxuixml/llinitparam.h +++ /dev/null @@ -1,2294 +0,0 @@ -/** - * @file llinitparam.h - * @brief parameter block abstraction for creating complex objects and - * parsing construction parameters from xml and LLSD - * - * $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_LLPARAM_H -#define LL_LLPARAM_H - -#include -#include -#include -#include -#include - -#include "llerror.h" - -namespace LLInitParam -{ - // used to indicate no matching value to a given name when parsing - struct Flag{}; - - template const T& defaultValue() { static T value; return value; } - - template ::value > - struct ParamCompare - { - static bool equals(const T &a, const T &b) - { - return a == b; - } - }; - - // boost function types are not comparable - template - struct ParamCompare - { - static bool equals(const T&a, const T &b) - { - return false; - } - }; - - template<> - struct ParamCompare - { - static bool equals(const LLSD &a, const LLSD &b) { return false; } - }; - - template<> - struct ParamCompare - { - static bool equals(const Flag& a, const Flag& b) { return false; } - }; - - - // helper functions and classes - typedef ptrdiff_t param_handle_t; - - // empty default implementation of key cache - // leverages empty base class optimization - template - class TypeValues - { - private: - struct Inaccessable{}; - public: - typedef std::map value_name_map_t; - typedef Inaccessable name_t; - - void setValueName(const std::string& key) {} - std::string getValueName() const { return ""; } - std::string calcValueName(const T& value) const { return ""; } - void clearValueName() const {} - - static bool getValueFromName(const std::string& name, T& value) - { - return false; - } - - static bool valueNamesExist() - { - return false; - } - - static std::vector* getPossibleValues() - { - return NULL; - } - - static value_name_map_t* getValueNames() {return NULL;} - }; - - template > - class TypeValuesHelper - { - public: - typedef typename std::map value_name_map_t; - typedef std::string name_t; - - //TODO: cache key by index to save on param block size - void setValueName(const std::string& value_name) - { - mValueName = value_name; - } - - std::string getValueName() const - { - return mValueName; - } - - std::string calcValueName(const T& value) const - { - value_name_map_t* map = getValueNames(); - for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); - it != end_it; - ++it) - { - if (ParamCompare::equals(it->second, value)) - { - return it->first; - } - } - - return ""; - } - - void clearValueName() const - { - mValueName.clear(); - } - - static bool getValueFromName(const std::string& name, T& value) - { - value_name_map_t* map = getValueNames(); - typename value_name_map_t::iterator found_it = map->find(name); - if (found_it == map->end()) return false; - - value = found_it->second; - return true; - } - - static bool valueNamesExist() - { - return !getValueNames()->empty(); - } - - static value_name_map_t* getValueNames() - { - static value_name_map_t sMap; - static bool sInitialized = false; - - if (!sInitialized) - { - sInitialized = true; - DERIVED_TYPE::declareValues(); - } - return &sMap; - } - - static std::vector* getPossibleValues() - { - static std::vector sValues; - - value_name_map_t* map = getValueNames(); - for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); - it != end_it; - ++it) - { - sValues.push_back(it->first); - } - return &sValues; - } - - static void declare(const std::string& name, const T& value) - { - (*getValueNames())[name] = value; - } - - protected: - static void getName(const std::string& name, const T& value) - {} - - mutable std::string mValueName; - }; - - class Parser - { - LOG_CLASS(Parser); - - public: - - struct CompareTypeID - { - bool operator()(const std::type_info* lhs, const std::type_info* rhs) const - { - return lhs->before(*rhs); - } - }; - - typedef std::vector > name_stack_t; - typedef std::pair name_stack_range_t; - typedef std::vector possible_values_t; - - typedef bool (*parser_read_func_t)(Parser& parser, void* output); - typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&); - typedef boost::function parser_inspect_func_t; - - typedef std::map parser_read_func_map_t; - typedef std::map parser_write_func_map_t; - typedef std::map parser_inspect_func_map_t; - - Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map) - : mParseSilently(false), - mParserReadFuncs(&read_map), - mParserWriteFuncs(&write_map), - mParserInspectFuncs(&inspect_map) - {} - virtual ~Parser(); - - template bool readValue(T& param) - { - parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); - if (found_it != mParserReadFuncs->end()) - { - return found_it->second(*this, (void*)¶m); - } - return false; - } - - template bool writeValue(const T& param, name_stack_t& name_stack) - { - parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); - if (found_it != mParserWriteFuncs->end()) - { - return found_it->second(*this, (const void*)¶m, name_stack); - } - return false; - } - - // dispatch inspection to registered inspection functions, for each parameter in a param block - template bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values) - { - parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T)); - if (found_it != mParserInspectFuncs->end()) - { - found_it->second(name_stack, min_count, max_count, possible_values); - return true; - } - return false; - } - - virtual std::string getCurrentElementName() = 0; - virtual void parserWarning(const std::string& message); - virtual void parserError(const std::string& message); - void setParseSilently(bool silent) { mParseSilently = silent; } - - protected: - template - void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL) - { - mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func)); - mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func)); - } - - template - void registerInspectFunc(parser_inspect_func_t inspect_func) - { - mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func)); - } - - bool mParseSilently; - - private: - parser_read_func_map_t* mParserReadFuncs; - parser_write_func_map_t* mParserWriteFuncs; - parser_inspect_func_map_t* mParserInspectFuncs; - }; - - class Param; - - // various callbacks and constraints associated with an individual param - struct ParamDescriptor - { - struct UserData - { - virtual ~UserData() {} - }; - - typedef bool(*merge_func_t)(Param&, const Param&, bool); - typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool); - typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param); - typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count); - typedef bool(*validation_func_t)(const Param*); - - ParamDescriptor(param_handle_t p, - merge_func_t merge_func, - deserialize_func_t deserialize_func, - serialize_func_t serialize_func, - validation_func_t validation_func, - inspect_func_t inspect_func, - S32 min_count, - S32 max_count); - - ParamDescriptor(); - ~ParamDescriptor(); - - param_handle_t mParamHandle; - merge_func_t mMergeFunc; - deserialize_func_t mDeserializeFunc; - serialize_func_t mSerializeFunc; - inspect_func_t mInspectFunc; - validation_func_t mValidationFunc; - S32 mMinCount; - S32 mMaxCount; - S32 mNumRefs; - UserData* mUserData; - }; - - typedef boost::shared_ptr ParamDescriptorPtr; - - // each derived Block class keeps a static data structure maintaining offsets to various params - class BlockDescriptor - { - public: - BlockDescriptor(); - - typedef enum e_initialization_state - { - UNINITIALIZED, - INITIALIZING, - INITIALIZED - } EInitializationState; - - void aggregateBlockData(BlockDescriptor& src_block_data); - - typedef boost::unordered_map param_map_t; - typedef std::vector param_list_t; - typedef std::list all_params_list_t; - typedef std::vector > param_validation_list_t; - - param_map_t mNamedParams; // parameters with associated names - param_list_t mUnnamedParams; // parameters with_out_ associated names - param_validation_list_t mValidationList; // parameters that must be validated - all_params_list_t mAllParams; // all parameters, owns descriptors - size_t mMaxParamOffset; - EInitializationState mInitializationState; // whether or not static block data has been initialized - class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed - }; - - class BaseBlock - { - public: - //TODO: implement in terms of owned_ptr - template - class Lazy - { - public: - Lazy() - : mPtr(NULL) - {} - - ~Lazy() - { - delete mPtr; - } - - Lazy(const Lazy& other) - { - if (other.mPtr) - { - mPtr = new T(*other.mPtr); - } - else - { - mPtr = NULL; - } - } - - Lazy& operator = (const Lazy& other) - { - if (other.mPtr) - { - mPtr = new T(*other.mPtr); - } - else - { - mPtr = NULL; - } - return *this; - } - - bool empty() const - { - return mPtr == NULL; - } - - void set(const T& other) - { - delete mPtr; - mPtr = new T(other); - } - - const T& get() const - { - return ensureInstance(); - } - - T& get() - { - return ensureInstance(); - } - - private: - // lazily allocate an instance of T - T* ensureInstance() const - { - if (mPtr == NULL) - { - mPtr = new T(); - } - return mPtr; - } - - private: - // if you get a compilation error with this, that means you are using a forward declared struct for T - // unfortunately, the type traits we rely on don't work with forward declared typed - //static const int dummy = sizeof(T); - - mutable T* mPtr; - }; - - // "Multiple" constraint types, put here in root class to avoid ambiguity during use - struct AnyAmount - { - enum { minCount = 0 }; - enum { maxCount = U32_MAX }; - }; - - template - struct AtLeast - { - enum { minCount = MIN_AMOUNT }; - enum { maxCount = U32_MAX }; - }; - - template - struct AtMost - { - enum { minCount = 0 }; - enum { maxCount = MAX_AMOUNT }; - }; - - template - struct Between - { - enum { minCount = MIN_AMOUNT }; - enum { maxCount = MAX_AMOUNT }; - }; - - template - struct Exactly - { - enum { minCount = EXACT_COUNT }; - enum { maxCount = EXACT_COUNT }; - }; - - // this typedef identifies derived classes as being blocks - typedef void baseblock_base_class_t; - LOG_CLASS(BaseBlock); - friend class Param; - - virtual ~BaseBlock() {} - bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false); - - param_handle_t getHandleFromParam(const Param* param) const; - bool validateBlock(bool emit_errors = true) const; - - Param* getParamFromHandle(const param_handle_t param_handle) - { - if (param_handle == 0) return NULL; - - U8* baseblock_address = reinterpret_cast(this); - return reinterpret_cast(baseblock_address + param_handle); - } - - const Param* getParamFromHandle(const param_handle_t param_handle) const - { - const U8* baseblock_address = reinterpret_cast(this); - return reinterpret_cast(baseblock_address + param_handle); - } - - void addSynonym(Param& param, const std::string& synonym); - - // Blocks can override this to do custom tracking of changes - virtual void paramChanged(const Param& changed_param, bool user_provided) {} - - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; - bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; - - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } - - // take all provided params from other and apply to self - bool overwriteFrom(const BaseBlock& other) - { - return false; - } - - // take all provided params that are not already provided, and apply to self - bool fillFrom(const BaseBlock& other) - { - return false; - } - - static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); - - ParamDescriptorPtr findParamDescriptor(const Param& param); - - protected: - void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); - - - bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite) - { - return mergeBlock(block_data, source, overwrite); - } - // take all provided params from other and apply to self - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); - - static BlockDescriptor& selfBlockDescriptor() - { - static BlockDescriptor sBlockDescriptor; - return sBlockDescriptor; - } - - private: - const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; - }; - - template - struct ParamCompare, false > - { - static bool equals(const BaseBlock::Lazy& a, const BaseBlock::Lazy& b) { return !a.empty() || !b.empty(); } - }; - - class Param - { - public: - void setProvided(bool is_provided = true) - { - mIsProvided = is_provided; - enclosingBlock().paramChanged(*this, is_provided); - } - - Param& operator =(const Param& other) - { - mIsProvided = other.mIsProvided; - // don't change mEnclosingblockoffset - return *this; - } - protected: - - bool anyProvided() const { return mIsProvided; } - - Param(BaseBlock* enclosing_block); - - // store pointer to enclosing block as offset to reduce space and allow for quick copying - BaseBlock& enclosingBlock() const - { - const U8* my_addr = reinterpret_cast(this); - // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class - return *const_cast - (reinterpret_cast - (my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); - } - - private: - friend class BaseBlock; - - U32 mEnclosingBlockOffset:31; - U32 mIsProvided:1; - - }; - - // these templates allow us to distinguish between template parameters - // that derive from BaseBlock and those that don't - template - struct IsBlock - { - static const bool value = false; - struct EmptyBase {}; - typedef EmptyBase base_class_t; - }; - - template - struct IsBlock - { - static const bool value = true; - typedef BaseBlock base_class_t; - }; - - template - struct IsBlock, typename T::baseblock_base_class_t > - { - static const bool value = true; - typedef BaseBlock base_class_t; - }; - - template::value> - class ParamValue : public NAME_VALUE_LOOKUP - { - public: - typedef const T& value_assignment_t; - typedef T value_t; - typedef ParamValue self_t; - - ParamValue(): mValue() {} - ParamValue(value_assignment_t other) : mValue(other) {} - - void setValue(value_assignment_t val) - { - mValue = val; - } - - value_assignment_t getValue() const - { - return mValue; - } - - T& getValue() - { - return mValue; - } - - operator value_assignment_t() const - { - return mValue; - } - - value_assignment_t operator()() const - { - return mValue; - } - - void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) - { - if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue)) - { - setValueName(name); - } - - return *this; - } - - protected: - T mValue; - }; - - template - class ParamValue - : public T, - public NAME_VALUE_LOOKUP - { - public: - typedef const T& value_assignment_t; - typedef T value_t; - typedef ParamValue self_t; - - ParamValue() - : T(), - mValidated(false) - {} - - ParamValue(value_assignment_t other) - : T(other), - mValidated(false) - {} - - void setValue(value_assignment_t val) - { - *this = val; - } - - value_assignment_t getValue() const - { - return *this; - } - - T& getValue() - { - return *this; - } - - operator value_assignment_t() const - { - return *this; - } - - value_assignment_t operator()() const - { - return *this; - } - - void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) - { - if (NAME_VALUE_LOOKUP::getValueFromName(name, *this)) - { - setValueName(name); - } - - return *this; - } - - protected: - mutable bool mValidated; // lazy validation flag - }; - - template - class ParamValue - : public NAME_VALUE_LOOKUP - { - public: - typedef const std::string& value_assignment_t; - typedef std::string value_t; - typedef ParamValue self_t; - - ParamValue(): mValue() {} - ParamValue(value_assignment_t other) : mValue(other) {} - - void setValue(value_assignment_t val) - { - if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue)) - { - NAME_VALUE_LOOKUP::setValueName(val); - } - else - { - mValue = val; - } - } - - value_assignment_t getValue() const - { - return mValue; - } - - std::string& getValue() - { - return mValue; - } - - operator value_assignment_t() const - { - return mValue; - } - - value_assignment_t operator()() const - { - return mValue; - } - - protected: - std::string mValue; - }; - - - template > - struct ParamIterator - { - typedef typename std::vector >::const_iterator const_iterator; - typedef typename std::vector >::iterator iterator; - }; - - // specialize for custom parsing/decomposition of specific classes - // e.g. TypedParam has left, top, right, bottom, etc... - template, - bool HAS_MULTIPLE_VALUES = false, - bool VALUE_IS_BLOCK = IsBlock >::value> - class TypedParam - : public Param, - public ParamValue - { - public: - typedef TypedParam self_t; - typedef ParamValue param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - - using param_value_t::operator(); - - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) - { - if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) - { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); - } - - setValue(value); - } - - bool isProvided() const { return Param::anyProvided(); } - - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) - { - self_t& typed_param = static_cast(param); - // no further names in stack, attempt to parse value now - if (name_stack_range.first == name_stack_range.second) - { - if (parser.readValue(typed_param.getValue())) - { - typed_param.clearValueName(); - typed_param.setProvided(); - return true; - } - - // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) - { - typed_param.setValueName(name); - typed_param.setProvided(); - return true; - } - - } - } - } - return false; - } - - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) - { - const self_t& typed_param = static_cast(param); - if (!typed_param.isProvided()) return; - - if (!name_stack.empty()) - { - name_stack.back().second = true; - } - - std::string key = typed_param.getValueName(); - - // first try to write out name of name/value pair - - if (!key.empty()) - { - if (!diff_param || !ParamCompare::equals(static_cast(diff_param)->getValueName(), key)) - { - parser.writeValue(key, name_stack); - } - } - // then try to serialize value directly - else if (!diff_param || !ParamCompare::equals(typed_param.getValue(), static_cast(diff_param)->getValue())) - { - if (!parser.writeValue(typed_param.getValue(), name_stack)) - { - std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); - if (!diff_param || !ParamCompare::equals(static_cast(diff_param)->getValueName(), calculated_key)) - { - parser.writeValue(calculated_key, name_stack); - } - } - } - } - - static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) - { - // tell parser about our actual type - parser.inspectValue(name_stack, min_count, max_count, NULL); - // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) - if (name_value_lookup_t::getPossibleValues()) - { - parser.inspectValue(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); - } - } - - void set(value_assignment_t val, bool flag_as_provided = true) - { - param_value_t::clearValueName(); - setValue(val); - setProvided(flag_as_provided); - } - - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) - { - return static_cast(param_value_t::operator =(name)); - } - - protected: - - self_t& operator =(const self_t& other) - { - param_value_t::operator =(other); - Param::operator =(other); - return *this; - } - - static bool mergeWith(Param& dst, const Param& src, bool overwrite) - { - const self_t& src_typed_param = static_cast(src); - self_t& dst_typed_param = static_cast(dst); - - if (src_typed_param.isProvided() - && (overwrite || !dst_typed_param.isProvided())) - { - dst_typed_param.set(src_typed_param.getValue()); - return true; - } - return false; - } - }; - - // parameter that is a block - template - class TypedParam - : public Param, - public ParamValue - { - public: - typedef ParamValue param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; - typedef TypedParam self_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - - using param_value_t::operator(); - - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr), - param_value_t(value) - { - if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) - { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); - } - } - - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) - { - self_t& typed_param = static_cast(param); - // attempt to parse block... - if(typed_param.deserializeBlock(parser, name_stack_range, new_name)) - { - typed_param.clearValueName(); - typed_param.setProvided(); - return true; - } - - if(name_value_lookup_t::valueNamesExist()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) - { - typed_param.setValueName(name); - typed_param.setProvided(); - return true; - } - - } - } - return false; - } - - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) - { - const self_t& typed_param = static_cast(param); - if (!typed_param.isProvided()) return; - - if (!name_stack.empty()) - { - name_stack.back().second = true; - } - - std::string key = typed_param.getValueName(); - if (!key.empty()) - { - if (!parser.writeValue(key, name_stack)) - { - return; - } - } - else - { - typed_param.serializeBlock(parser, name_stack, static_cast(diff_param)); - } - } - - static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) - { - // I am a param that is also a block, so just recurse into my contents - const self_t& typed_param = static_cast(param); - typed_param.inspectBlock(parser, name_stack, min_count, max_count); - } - - // a param-that-is-a-block is provided when the user has set one of its child params - // *and* the block as a whole validates - bool isProvided() const - { - // only validate block when it hasn't already passed validation with current data - if (Param::anyProvided() && !param_value_t::mValidated) - { - // a sub-block is "provided" when it has been filled in enough to be valid - param_value_t::mValidated = param_value_t::validateBlock(false); - } - return Param::anyProvided() && param_value_t::mValidated; - } - - // assign block contents to this param-that-is-a-block - void set(value_assignment_t val, bool flag_as_provided = true) - { - setValue(val); - param_value_t::clearValueName(); - // force revalidation of block - // next call to isProvided() will update provision status based on validity - param_value_t::mValidated = false; - setProvided(flag_as_provided); - } - - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) - { - return static_cast(param_value_t::operator =(name)); - } - - // propagate changed status up to enclosing block - /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) - { - param_value_t::paramChanged(changed_param, user_provided); - if (user_provided) - { - // a child param has been explicitly changed - // so *some* aspect of this block is now provided - param_value_t::mValidated = false; - setProvided(); - param_value_t::clearValueName(); - } - else - { - Param::enclosingBlock().paramChanged(*this, user_provided); - } - } - - protected: - - self_t& operator =(const self_t& other) - { - param_value_t::operator =(other); - Param::operator =(other); - return *this; - } - - static bool mergeWith(Param& dst, const Param& src, bool overwrite) - { - const self_t& src_typed_param = static_cast(src); - self_t& dst_typed_param = static_cast(dst); - - if (src_typed_param.anyProvided()) - { - if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) - { - dst_typed_param.clearValueName(); - dst_typed_param.setProvided(true); - return true; - } - } - return false; - } - }; - - // container of non-block parameters - template - class TypedParam - : public Param - { - public: - typedef TypedParam self_t; - typedef ParamValue param_value_t; - typedef typename std::vector container_t; - typedef const container_t& value_assignment_t; - - typedef typename param_value_t::value_t value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) - { - std::copy(value.begin(), value.end(), std::back_inserter(mValues)); - - if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) - { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); - } - } - - bool isProvided() const { return Param::anyProvided(); } - - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) - { - self_t& typed_param = static_cast(param); - value_t value; - // no further names in stack, attempt to parse value now - if (name_stack_range.first == name_stack_range.second) - { - // attempt to read value directly - if (parser.readValue(value)) - { - typed_param.add(value); - return true; - } - - // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) - { - typed_param.add(value); - typed_param.mValues.back().setValueName(name); - return true; - } - - } - } - } - return false; - } - - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) - { - const self_t& typed_param = static_cast(param); - if (!typed_param.isProvided() || name_stack.empty()) return; - - for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); - it != end_it; - ++it) - { - std::string key = it->getValueName(); - name_stack.back().second = true; - - if(key.empty()) - // not parsed via name values, write out value directly - { - bool value_written = parser.writeValue(*it, name_stack); - if (!value_written) - { - std::string calculated_key = it->calcValueName(it->getValue()); - if (!parser.writeValue(calculated_key, name_stack)) - { - break; - } - } - } - else - { - if(!parser.writeValue(key, name_stack)) - { - break; - } - } - } - } - - static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) - { - parser.inspectValue(name_stack, min_count, max_count, NULL); - if (name_value_lookup_t::getPossibleValues()) - { - parser.inspectValue(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); - } - } - - void set(value_assignment_t val, bool flag_as_provided = true) - { - mValues = val; - setProvided(flag_as_provided); - } - - param_value_t& add() - { - mValues.push_back(param_value_t(value_t())); - Param::setProvided(); - return mValues.back(); - } - - void add(const value_t& item) - { - param_value_t param_value; - param_value.setValue(item); - mValues.push_back(param_value); - setProvided(); - } - - void add(const typename name_value_lookup_t::name_t& name) - { - value_t value; - - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) - { - add(value); - mValues.back().setValueName(name); - } - } - - // implicit conversion - operator value_assignment_t() const { return mValues; } - // explicit conversion - value_assignment_t operator()() const { return mValues; } - - typedef typename container_t::iterator iterator; - typedef typename container_t::const_iterator const_iterator; - iterator begin() { return mValues.begin(); } - iterator end() { return mValues.end(); } - const_iterator begin() const { return mValues.begin(); } - const_iterator end() const { return mValues.end(); } - bool empty() const { return mValues.empty(); } - size_t size() const { return mValues.size(); } - - U32 numValidElements() const - { - return mValues.size(); - } - - protected: - static bool mergeWith(Param& dst, const Param& src, bool overwrite) - { - const self_t& src_typed_param = static_cast(src); - self_t& dst_typed_param = static_cast(dst); - - if (overwrite) - { - std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues)); - } - else - { - container_t new_values(src_typed_param.mValues); - std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values)); - std::swap(dst_typed_param.mValues, new_values); - } - - if (src_typed_param.begin() != src_typed_param.end()) - { - dst_typed_param.setProvided(); - } - return true; - } - - container_t mValues; - }; - - // container of block parameters - template - class TypedParam - : public Param - { - public: - typedef TypedParam self_t; - typedef ParamValue param_value_t; - typedef typename std::vector container_t; - typedef const container_t& value_assignment_t; - typedef typename param_value_t::value_t value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) - { - std::copy(value.begin(), value.end(), back_inserter(mValues)); - - if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) - { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); - } - } - - bool isProvided() const { return Param::anyProvided(); } - - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) - { - self_t& typed_param = static_cast(param); - bool new_value = false; - - if (new_name || typed_param.mValues.empty()) - { - new_value = true; - typed_param.mValues.push_back(value_t()); - } - - param_value_t& value = typed_param.mValues.back(); - - // attempt to parse block... - if(value.deserializeBlock(parser, name_stack_range, new_name)) - { - typed_param.setProvided(); - return true; - } - else if(name_value_lookup_t::valueNamesExist()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value.getValue())) - { - typed_param.mValues.back().setValueName(name); - typed_param.setProvided(); - return true; - } - - } - } - - if (new_value) - { // failed to parse new value, pop it off - typed_param.mValues.pop_back(); - } - - return false; - } - - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) - { - const self_t& typed_param = static_cast(param); - if (!typed_param.isProvided() || name_stack.empty()) return; - - for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); - it != end_it; - ++it) - { - name_stack.back().second = true; - - std::string key = it->getValueName(); - if (!key.empty()) - { - parser.writeValue(key, name_stack); - } - // Not parsed via named values, write out value directly - // NOTE: currently we don't worry about removing default values in Multiple - else - { - it->serializeBlock(parser, name_stack, NULL); - } - } - } - - static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) - { - // I am a vector of blocks, so describe my contents recursively - param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); - } - - void set(value_assignment_t val, bool flag_as_provided = true) - { - mValues = val; - setProvided(flag_as_provided); - } - - param_value_t& add() - { - mValues.push_back(value_t()); - setProvided(); - return mValues.back(); - } - - void add(const value_t& item) - { - mValues.push_back(item); - setProvided(); - } - - void add(const typename name_value_lookup_t::name_t& name) - { - value_t value; - - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) - { - add(value); - mValues.back().setValueName(name); - } - } - - // implicit conversion - operator value_assignment_t() const { return mValues; } - // explicit conversion - value_assignment_t operator()() const { return mValues; } - - typedef typename container_t::iterator iterator; - typedef typename container_t::const_iterator const_iterator; - iterator begin() { return mValues.begin(); } - iterator end() { return mValues.end(); } - const_iterator begin() const { return mValues.begin(); } - const_iterator end() const { return mValues.end(); } - bool empty() const { return mValues.empty(); } - size_t size() const { return mValues.size(); } - - U32 numValidElements() const - { - U32 count = 0; - for (const_iterator it = mValues.begin(), end_it = mValues.end(); - it != end_it; - ++it) - { - if(it->validateBlock(false)) count++; - } - return count; - } - - protected: - - static bool mergeWith(Param& dst, const Param& src, bool overwrite) - { - const self_t& src_typed_param = static_cast(src); - self_t& dst_typed_param = static_cast(dst); - - if (overwrite) - { - std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues)); - } - else - { - container_t new_values(src_typed_param.mValues); - std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values)); - std::swap(dst_typed_param.mValues, new_values); - } - - if (src_typed_param.begin() != src_typed_param.end()) - { - dst_typed_param.setProvided(); - } - - return true; - } - - container_t mValues; - }; - - template - class ChoiceBlock : public BASE_BLOCK - { - typedef ChoiceBlock self_t; - typedef ChoiceBlock enclosing_block_t; - typedef BASE_BLOCK base_block_t; - - LOG_CLASS(self_t); - public: - // take all provided params from other and apply to self - bool overwriteFrom(const self_t& other) - { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, true); - } - - // take all provided params that are not already provided, and apply to self - bool fillFrom(const self_t& other) - { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, false); - } - - bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) - { - bool source_override = source_provided && (overwrite || !dest_provided); - - if (source_override || source.mCurChoice == mCurChoice) - { - return mergeBlock(block_data, source, overwrite); - } - return false; - } - - // merge with other block - bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite) - { - mCurChoice = other.mCurChoice; - return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite); - } - - // clear out old choice when param has changed - /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) - { - param_handle_t changed_param_handle = base_block_t::getHandleFromParam(&changed_param); - // if we have a new choice... - if (changed_param_handle != mCurChoice) - { - // clear provided flag on previous choice - Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice); - if (previous_choice) - { - previous_choice->setProvided(false); - } - mCurChoice = changed_param_handle; - } - base_block_t::paramChanged(changed_param, user_provided); - } - - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } - - protected: - ChoiceBlock() - : mCurChoice(0) - { - BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); - } - - // Alternatives are mutually exclusive wrt other Alternatives in the same block. - // One alternative in a block will always have isChosen() == true. - // At most one alternative in a block will have isProvided() == true. - template > - class Alternative : public TypedParam - { - public: - friend class ChoiceBlock; - - typedef Alternative self_t; - typedef TypedParam >::value> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; - - using super_t::operator =; - - explicit Alternative(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), - mOriginalValue(val) - { - // assign initial choice to first declared option - DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); - if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) - { - if(blockp->mCurChoice == 0) - { - blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this); - } - } - } - - void choose() - { - static_cast(Param::enclosingBlock()).paramChanged(*this, true); - } - - void chooseAs(value_assignment_t val) - { - super_t::set(val); - } - - void operator =(value_assignment_t val) - { - super_t::set(val); - } - - void operator()(typename super_t::value_assignment_t val) - { - super_t::set(val); - } - - operator value_assignment_t() const - { - return (*this)(); - } - - value_assignment_t operator()() const - { - if (static_cast(Param::enclosingBlock()).getCurrentChoice() == this) - { - return super_t::getValue(); - } - return mOriginalValue; - } - - bool isChosen() const - { - return static_cast(Param::enclosingBlock()).getCurrentChoice() == this; - } - - private: - T mOriginalValue; - }; - - protected: - static BlockDescriptor& selfBlockDescriptor() - { - static BlockDescriptor sBlockDescriptor; - return sBlockDescriptor; - } - - private: - param_handle_t mCurChoice; - - const Param* getCurrentChoice() const - { - return base_block_t::getParamFromHandle(mCurChoice); - } - }; - - template - class Block - : public BASE_BLOCK - { - typedef Block self_t; - typedef Block block_t; - - public: - typedef BASE_BLOCK base_block_t; - - // take all provided params from other and apply to self - bool overwriteFrom(const self_t& other) - { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, true); - } - - // take all provided params that are not already provided, and apply to self - bool fillFrom(const self_t& other) - { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, false); - } - - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } - - protected: - Block() - { - //#pragma message("Parsing LLInitParam::Block") - BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); - } - - // - // Nested classes for declaring parameters - // - template > - class Optional : public TypedParam - { - public: - typedef TypedParam >::value> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; - - using super_t::operator(); - using super_t::operator =; - - explicit Optional(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) - { - //#pragma message("Parsing LLInitParam::Block::Optional") - } - - Optional& operator =(value_assignment_t val) - { - set(val); - return *this; - } - - DERIVED_BLOCK& operator()(value_assignment_t val) - { - super_t::set(val); - return static_cast(Param::enclosingBlock()); - } - }; - - template > - class Mandatory : public TypedParam - { - public: - typedef TypedParam >::value> super_t; - typedef Mandatory self_t; - typedef typename super_t::value_assignment_t value_assignment_t; - - using super_t::operator(); - using super_t::operator =; - - // mandatory parameters require a name to be parseable - explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) - {} - - Mandatory& operator =(value_assignment_t val) - { - set(val); - return *this; - } - - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) - { - super_t::set(val); - return static_cast(Param::enclosingBlock()); - } - - static bool validate(const Param* p) - { - // valid only if provided - return static_cast(p)->isProvided(); - } - - }; - - template > - class Multiple : public TypedParam - { - public: - typedef TypedParam >::value> super_t; - typedef Multiple self_t; - typedef typename super_t::container_t container_t; - typedef typename super_t::value_assignment_t value_assignment_t; - typedef typename super_t::iterator iterator; - typedef typename super_t::const_iterator const_iterator; - - explicit Multiple(const char* name = "") - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) - {} - - Multiple& operator =(value_assignment_t val) - { - set(val); - return *this; - } - - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) - { - super_t::set(val); - return static_cast(Param::enclosingBlock()); - } - - static bool validate(const Param* paramp) - { - U32 num_valid = ((super_t*)paramp)->numValidElements(); - return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount; - } - }; - - class Deprecated : public Param - { - public: - explicit Deprecated(const char* name) - : Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) - { - BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); - if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) - { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - NULL, - &deserializeParam, - NULL, - NULL, - NULL, - 0, S32_MAX)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); - } - } - - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) - { - if (name_stack_range.first == name_stack_range.second) - { - //std::string message = llformat("Deprecated value %s ignored", getName().c_str()); - //parser.parserWarning(message); - return true; - } - - return false; - } - }; - - // different semantics for documentation purposes, but functionally identical - typedef Deprecated Ignored; - - protected: - static BlockDescriptor& selfBlockDescriptor() - { - static BlockDescriptor sBlockDescriptor; - return sBlockDescriptor; - } - - template - void changeDefault(TypedParam& param, - typename TypedParam::value_assignment_t value) - { - if (!param.isProvided()) - { - param.set(value, false); - } - } - - }; - - template - class BatchBlock - : public Block - { - public: - typedef BatchBlock self_t; - typedef Block super_t; - - BatchBlock() - {} - - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) - { - if (new_name) - { - // reset block - *static_cast(this) = defaultBatchValue(); - } - return super_t::deserializeBlock(p, name_stack_range, new_name); - } - - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) - { - if (overwrite) - { - *static_cast(this) = defaultBatchValue(); - // merge individual parameters into destination - return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); - } - return false; - } - protected: - static const DERIVED_BLOCK& defaultBatchValue() - { - static DERIVED_BLOCK default_value; - return default_value; - } - }; - - // FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class - // and not the derived class with the actual params - template - class ParamValue , - NAME_VALUE_LOOKUP, - true> - : public NAME_VALUE_LOOKUP, - protected BatchBlock - { - public: - typedef BatchBlock block_t; - typedef const BatchBlock& value_assignment_t; - typedef block_t value_t; - - ParamValue() - : block_t(), - mValidated(false) - {} - - ParamValue(value_assignment_t other) - : block_t(other), - mValidated(false) - { - } - - void setValue(value_assignment_t val) - { - *this = val; - } - - value_assignment_t getValue() const - { - return *this; - } - - BatchBlock& getValue() - { - return *this; - } - - operator value_assignment_t() const - { - return *this; - } - - value_assignment_t operator()() const - { - return *this; - } - - protected: - mutable bool mValidated; // lazy validation flag - }; - - template - class ParamValue , - TypeValues, - IS_BLOCK> - : public IsBlock::base_class_t - { - public: - typedef ParamValue , TypeValues, false> self_t; - typedef const T& value_assignment_t; - typedef T value_t; - - ParamValue() - : mValue(), - mValidated(false) - {} - - ParamValue(value_assignment_t other) - : mValue(other), - mValidated(false) - {} - - void setValue(value_assignment_t val) - { - mValue.set(val); - } - - value_assignment_t getValue() const - { - return mValue.get(); - } - - T& getValue() - { - return mValue.get(); - } - - operator value_assignment_t() const - { - return mValue.get(); - } - - value_assignment_t operator()() const - { - return mValue.get(); - } - - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) - { - return mValue.get().deserializeBlock(p, name_stack_range, new_name); - } - - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const - { - if (mValue.empty()) return; - - mValue.get().serializeBlock(p, name_stack, diff_block); - } - - bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const - { - if (mValue.empty()) return false; - - return mValue.get().inspectBlock(p, name_stack, min_count, max_count); - } - - protected: - mutable bool mValidated; // lazy validation flag - - private: - BaseBlock::Lazy mValue; - }; - - template <> - class ParamValue , - false> - : public TypeValues, - public BaseBlock - { - public: - typedef ParamValue, false> self_t; - typedef const LLSD& value_assignment_t; - - ParamValue() - : mValidated(false) - {} - - ParamValue(value_assignment_t other) - : mValue(other), - mValidated(false) - {} - - void setValue(value_assignment_t val) { mValue = val; } - - value_assignment_t getValue() const { return mValue; } - LLSD& getValue() { return mValue; } - - operator value_assignment_t() const { return mValue; } - value_assignment_t operator()() const { return mValue; } - - - // block param interface - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; - bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const - { - //TODO: implement LLSD params as schema type Any - return true; - } - - protected: - mutable bool mValidated; // lazy validation flag - - private: - static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack); - - LLSD mValue; - }; - - template - class CustomParamValue - : public Block > >, - public TypeValues - { - public: - typedef enum e_value_age - { - VALUE_NEEDS_UPDATE, // mValue needs to be refreshed from the block parameters - VALUE_AUTHORITATIVE, // mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue) - BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative - } EValueAge; - - typedef ParamValue > derived_t; - typedef CustomParamValue self_t; - typedef Block block_t; - typedef const T& value_assignment_t; - typedef T value_t; - - - CustomParamValue(const T& value = T()) - : mValue(value), - mValueAge(VALUE_AUTHORITATIVE), - mValidated(false) - {} - - bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name) - { - derived_t& typed_param = static_cast(*this); - // try to parse direct value T - if (name_stack_range.first == name_stack_range.second) - { - if(parser.readValue(typed_param.mValue)) - { - typed_param.mValueAge = VALUE_AUTHORITATIVE; - typed_param.updateBlockFromValue(false); - - typed_param.clearValueName(); - - return true; - } - } - - // fall back on parsing block components for T - return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name); - } - - void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const - { - const derived_t& typed_param = static_cast(*this); - const derived_t* diff_param = static_cast(diff_block); - - std::string key = typed_param.getValueName(); - - // first try to write out name of name/value pair - if (!key.empty()) - { - if (!diff_param || !ParamCompare::equals(diff_param->getValueName(), key)) - { - parser.writeValue(key, name_stack); - } - } - // then try to serialize value directly - else if (!diff_param || !ParamCompare::equals(typed_param.getValue(), diff_param->getValue())) - { - - if (!parser.writeValue(typed_param.getValue(), name_stack)) - { - //RN: *always* serialize provided components of BlockValue (don't pass diff_param on), - // since these tend to be viewed as the constructor arguments for the value T. It seems - // cleaner to treat the uniqueness of a BlockValue according to the generated value, and - // not the individual components. This way will not - // be exported as , since it was probably the intent of the user to - // be specific about the RGB color values. This also fixes an issue where we distinguish - // between rect.left not being provided and rect.left being explicitly set to 0 (same as default) - - if (typed_param.mValueAge == VALUE_AUTHORITATIVE) - { - // if the value is authoritative but the parser doesn't accept the value type - // go ahead and make a copy, and splat the value out to its component params - // and serialize those params - derived_t copy(typed_param); - copy.updateBlockFromValue(true); - copy.block_t::serializeBlock(parser, name_stack, NULL); - } - else - { - block_t::serializeBlock(parser, name_stack, NULL); - } - } - } - } - - bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const - { - // first, inspect with actual type... - parser.inspectValue(name_stack, min_count, max_count, NULL); - if (TypeValues::getPossibleValues()) - { - //...then inspect with possible string values... - parser.inspectValue(name_stack, min_count, max_count, TypeValues::getPossibleValues()); - } - // then recursively inspect contents... - return block_t::inspectBlock(parser, name_stack, min_count, max_count); - } - - bool validateBlock(bool emit_errors = true) const - { - if (mValueAge == VALUE_NEEDS_UPDATE) - { - if (block_t::validateBlock(emit_errors)) - { - // clear stale keyword associated with old value - TypeValues::clearValueName(); - mValueAge = BLOCK_AUTHORITATIVE; - static_cast(const_cast(this))->updateValueFromBlock(); - return true; - } - else - { - //block value incomplete, so not considered provided - // will attempt to revalidate on next call to isProvided() - return false; - } - } - else - { - // we have a valid value in hand - return true; - } - } - - // propagate change status up to enclosing block - /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) - { - BaseBlock::paramChanged(changed_param, user_provided); - if (user_provided) - { - // a parameter changed, so our value is out of date - mValueAge = VALUE_NEEDS_UPDATE; - } - } - - void setValue(value_assignment_t val) - { - derived_t& typed_param = static_cast(*this); - // set param version number to be up to date, so we ignore block contents - mValueAge = VALUE_AUTHORITATIVE; - mValue = val; - typed_param.clearValueName(); - static_cast(this)->updateBlockFromValue(false); - } - - value_assignment_t getValue() const - { - validateBlock(true); - return mValue; - } - - T& getValue() - { - validateBlock(true); - return mValue; - } - - operator value_assignment_t() const - { - return getValue(); - } - - value_assignment_t operator()() const - { - return getValue(); - } - - protected: - - // use this from within updateValueFromBlock() to set the value without making it authoritative - void updateValue(value_assignment_t value) - { - mValue = value; - } - - bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite) - { - bool source_override = source_provided && (overwrite || !dst_provided); - - const derived_t& src_typed_param = static_cast(source); - - if (source_override && src_typed_param.mValueAge == VALUE_AUTHORITATIVE) - { - // copy value over - setValue(src_typed_param.getValue()); - return true; - } - // merge individual parameters into destination - if (mValueAge == VALUE_AUTHORITATIVE) - { - static_cast(this)->updateBlockFromValue(dst_provided); - } - return mergeBlock(block_data, source, overwrite); - } - - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& source, bool overwrite) - { - return block_t::mergeBlock(block_data, source, overwrite); - } - - mutable bool mValidated; // lazy validation flag - - private: - mutable T mValue; - mutable EValueAge mValueAge; - }; -} - - -#endif // LL_LLPARAM_H diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h deleted file mode 100644 index 36ce6a97b7..0000000000 --- a/indra/llxuixml/llregistry.h +++ /dev/null @@ -1,351 +0,0 @@ -/** - * @file llregistry.h - * @brief template classes for registering name, value pairs in nested scopes, statically, etc. - * - * $LicenseInfo:firstyear=2001&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_LLREGISTRY_H -#define LL_LLREGISTRY_H - -#include - -#include -#include "llsingleton.h" - -template -class LLRegistryDefaultComparator -{ - bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; } -}; - -template > -class LLRegistry -{ -public: - typedef LLRegistry registry_t; - typedef typename boost::add_reference::type>::type ref_const_key_t; - typedef typename boost::add_reference::type>::type ref_const_value_t; - typedef typename boost::add_reference::type ref_value_t; - typedef typename boost::add_pointer::type>::type ptr_const_value_t; - typedef typename boost::add_pointer::type ptr_value_t; - - class Registrar - { - friend class LLRegistry; - public: - typedef typename std::map registry_map_t; - - bool add(ref_const_key_t key, ref_const_value_t value) - { - if (mMap.insert(std::make_pair(key, value)).second == false) - { - llwarns << "Tried to register " << key << " but it was already registered!" << llendl; - return false; - } - return true; - } - - void remove(ref_const_key_t key) - { - mMap.erase(key); - } - - void replace(ref_const_key_t key, ref_const_value_t value) - { - mMap[key] = value; - } - - typename registry_map_t::const_iterator beginItems() const - { - return mMap.begin(); - } - - typename registry_map_t::const_iterator endItems() const - { - return mMap.end(); - } - - protected: - ptr_value_t getValue(ref_const_key_t key) - { - typename registry_map_t::iterator found_it = mMap.find(key); - if (found_it != mMap.end()) - { - return &(found_it->second); - } - return NULL; - } - - ptr_const_value_t getValue(ref_const_key_t key) const - { - typename registry_map_t::const_iterator found_it = mMap.find(key); - if (found_it != mMap.end()) - { - return &(found_it->second); - } - return NULL; - } - - // if the registry is used to store pointers, and null values are valid entries - // then use this function to check the existence of an entry - bool exists(ref_const_key_t key) const - { - return mMap.find(key) != mMap.end(); - } - - bool empty() const - { - return mMap.empty(); - } - - protected: - // use currentRegistrar() or defaultRegistrar() - Registrar() {} - ~Registrar() {} - - private: - registry_map_t mMap; - }; - - typedef typename std::list scope_list_t; - typedef typename std::list::iterator scope_list_iterator_t; - typedef typename std::list::const_iterator scope_list_const_iterator_t; - - LLRegistry() - {} - - ~LLRegistry() {} - - ptr_value_t getValue(ref_const_key_t key) - { - for(scope_list_iterator_t it = mActiveScopes.begin(); - it != mActiveScopes.end(); - ++it) - { - ptr_value_t valuep = (*it)->getValue(key); - if (valuep != NULL) return valuep; - } - return mDefaultRegistrar.getValue(key); - } - - ptr_const_value_t getValue(ref_const_key_t key) const - { - for(scope_list_const_iterator_t it = mActiveScopes.begin(); - it != mActiveScopes.end(); - ++it) - { - ptr_value_t valuep = (*it)->getValue(key); - if (valuep != NULL) return valuep; - } - return mDefaultRegistrar.getValue(key); - } - - bool exists(ref_const_key_t key) const - { - for(scope_list_const_iterator_t it = mActiveScopes.begin(); - it != mActiveScopes.end(); - ++it) - { - if ((*it)->exists(key)) return true; - } - - return mDefaultRegistrar.exists(key); - } - - bool empty() const - { - for(scope_list_const_iterator_t it = mActiveScopes.begin(); - it != mActiveScopes.end(); - ++it) - { - if (!(*it)->empty()) return false; - } - - return mDefaultRegistrar.empty(); - } - - - Registrar& defaultRegistrar() - { - return mDefaultRegistrar; - } - - const Registrar& defaultRegistrar() const - { - return mDefaultRegistrar; - } - - - Registrar& currentRegistrar() - { - if (!mActiveScopes.empty()) - { - return *mActiveScopes.front(); - } - - return mDefaultRegistrar; - } - - const Registrar& currentRegistrar() const - { - if (!mActiveScopes.empty()) - { - return *mActiveScopes.front(); - } - - return mDefaultRegistrar; - } - - -protected: - void addScope(Registrar* scope) - { - // newer scopes go up front - mActiveScopes.insert(mActiveScopes.begin(), scope); - } - - void removeScope(Registrar* scope) - { - // O(N) but should be near the beggining and N should be small and this is safer than storing iterators - scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope); - if (iter != mActiveScopes.end()) - { - mActiveScopes.erase(iter); - } - } - -private: - scope_list_t mActiveScopes; - Registrar mDefaultRegistrar; -}; - -template > -class LLRegistrySingleton - : public LLRegistry, - public LLSingleton -{ - friend class LLSingleton; -public: - typedef LLRegistry registry_t; - typedef const KEY& ref_const_key_t; - typedef const VALUE& ref_const_value_t; - typedef VALUE* ptr_value_t; - typedef const VALUE* ptr_const_value_t; - typedef LLSingleton singleton_t; - - class ScopedRegistrar : public registry_t::Registrar - { - public: - ScopedRegistrar(bool push_scope = true) - { - if (push_scope) - { - pushScope(); - } - } - - ~ScopedRegistrar() - { - if (!singleton_t::destroyed()) - { - popScope(); - } - } - - void pushScope() - { - singleton_t::instance().addScope(this); - } - - void popScope() - { - singleton_t::instance().removeScope(this); - } - - ptr_value_t getValueFromScope(ref_const_key_t key) - { - return getValue(key); - } - - ptr_const_value_t getValueFromScope(ref_const_key_t key) const - { - return getValue(key); - } - - private: - typename std::list::iterator mListIt; - }; - - class StaticRegistrar : public registry_t::Registrar - { - public: - virtual ~StaticRegistrar() {} - StaticRegistrar(ref_const_key_t key, ref_const_value_t value) - { - singleton_t::instance().mStaticScope->add(key, value); - } - }; - - // convenience functions - typedef typename LLRegistry::Registrar& ref_registrar_t; - static ref_registrar_t currentRegistrar() - { - return singleton_t::instance().registry_t::currentRegistrar(); - } - - static ref_registrar_t defaultRegistrar() - { - return singleton_t::instance().registry_t::defaultRegistrar(); - } - - static ptr_value_t getValue(ref_const_key_t key) - { - return singleton_t::instance().registry_t::getValue(key); - } - -protected: - // DERIVED_TYPE needs to derive from LLRegistrySingleton - LLRegistrySingleton() - : mStaticScope(NULL) - {} - - virtual void initSingleton() - { - mStaticScope = new ScopedRegistrar(); - } - - virtual ~LLRegistrySingleton() - { - delete mStaticScope; - } - -private: - ScopedRegistrar* mStaticScope; -}; - -// helper macro for doing static registration -#define GLUED_TOKEN(x, y) x ## y -#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y) -#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE); - -#endif diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp deleted file mode 100644 index 5388069c24..0000000000 --- a/indra/llxuixml/lltrans.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/** - * @file lltrans.cpp - * @brief LLTrans implementation - * - * $LicenseInfo:firstyear=2000&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$ - */ - -#include "linden_common.h" - -#include "lltrans.h" - -#include "llfasttimer.h" // for call count statistics -#include "llxuiparser.h" -#include "llsd.h" -#include "llxmlnode.h" - -#include - -LLTrans::template_map_t LLTrans::sStringTemplates; -LLStringUtil::format_map_t LLTrans::sDefaultArgs; - -struct StringDef : public LLInitParam::Block -{ - Mandatory name; - Mandatory value; - - StringDef() - : name("name"), - value("value") - {} -}; - -struct StringTable : public LLInitParam::Block -{ - Multiple strings; - StringTable() - : strings("string") - {} -}; - -//static -bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set& default_args) -{ - std::string xml_filename = "(strings file)"; - if (!root->hasName("strings")) - { - llerrs << "Invalid root node name in " << xml_filename - << ": was " << root->getName() << ", expected \"strings\"" << llendl; - } - - StringTable string_table; - LLXUIParser parser; - parser.readXUI(root, string_table, xml_filename); - - if (!string_table.validateBlock()) - { - llerrs << "Problem reading strings: " << xml_filename << llendl; - return false; - } - - sStringTemplates.clear(); - sDefaultArgs.clear(); - - for(LLInitParam::ParamIterator::const_iterator it = string_table.strings.begin(); - it != string_table.strings.end(); - ++it) - { - LLTransTemplate xml_template(it->name, it->value); - sStringTemplates[xml_template.mName] = xml_template; - - std::set::const_iterator iter = default_args.find(xml_template.mName); - if (iter != default_args.end()) - { - std::string name = *iter; - if (name[0] != '[') - name = llformat("[%s]",name.c_str()); - sDefaultArgs[name] = xml_template.mText; - } - } - - return true; -} - - -//static -bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root) -{ - std::string xml_filename = "(language strings file)"; - if (!root->hasName("strings")) - { - llerrs << "Invalid root node name in " << xml_filename - << ": was " << root->getName() << ", expected \"strings\"" << llendl; - } - - StringTable string_table; - LLXUIParser parser; - parser.readXUI(root, string_table, xml_filename); - - if (!string_table.validateBlock()) - { - llerrs << "Problem reading strings: " << xml_filename << llendl; - return false; - } - - for(LLInitParam::ParamIterator::const_iterator it = string_table.strings.begin(); - it != string_table.strings.end(); - ++it) - { - // share the same map with parseStrings() so we can search the strings using the same getString() function.- angela - LLTransTemplate xml_template(it->name, it->value); - sStringTemplates[xml_template.mName] = xml_template; - } - - return true; -} - - - -static LLFastTimer::DeclareTimer FTM_GET_TRANS("Translate string"); - -//static -std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args) -{ - // Don't care about time as much as call count. Make sure we're not - // calling LLTrans::getString() in an inner loop. JC - LLFastTimer timer(FTM_GET_TRANS); - - template_map_t::iterator iter = sStringTemplates.find(xml_desc); - if (iter != sStringTemplates.end()) - { - std::string text = iter->second.mText; - LLStringUtil::format_map_t args = sDefaultArgs; - args.insert(msg_args.begin(), msg_args.end()); - LLStringUtil::format(text, args); - - return text; - } - else - { - LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; - return "MissingString("+xml_desc+")"; - } -} - -//static -std::string LLTrans::getString(const std::string &xml_desc, const LLSD& msg_args) -{ - // Don't care about time as much as call count. Make sure we're not - // calling LLTrans::getString() in an inner loop. JC - LLFastTimer timer(FTM_GET_TRANS); - - template_map_t::iterator iter = sStringTemplates.find(xml_desc); - if (iter != sStringTemplates.end()) - { - std::string text = iter->second.mText; - LLStringUtil::format(text, msg_args); - return text; - } - else - { - LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; - return "MissingString("+xml_desc+")"; - } -} - -//static -bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args) -{ - LLFastTimer timer(FTM_GET_TRANS); - - template_map_t::iterator iter = sStringTemplates.find(xml_desc); - if (iter != sStringTemplates.end()) - { - std::string text = iter->second.mText; - LLStringUtil::format_map_t args = sDefaultArgs; - args.insert(msg_args.begin(), msg_args.end()); - LLStringUtil::format(text, args); - result = text; - return true; - } - else - { - LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; - return false; - } -} - -//static -bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLSD& msg_args) -{ - LLFastTimer timer(FTM_GET_TRANS); - - template_map_t::iterator iter = sStringTemplates.find(xml_desc); - if (iter != sStringTemplates.end()) - { - std::string text = iter->second.mText; - LLStringUtil::format(text, msg_args); - result = text; - return true; - } - else - { - LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; - return false; - } -} - -//static -std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count) -{ - // Compute which string identifier to use - const char* form = ""; - if (language == "ru") // Russian - { - // From GNU ngettext() - // Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; - if (count % 10 == 1 - && count % 100 != 11) - { - // singular, "1 item" - form = "A"; - } - else if (count % 10 >= 2 - && count % 10 <= 4 - && (count % 100 < 10 || count % 100 >= 20) ) - { - // special case "2 items", "23 items", but not "13 items" - form = "B"; - } - else - { - // English-style plural, "5 items" - form = "C"; - } - } - else if (language == "fr" || language == "pt") // French, Brazilian Portuguese - { - // French and Portuguese treat zero as a singular "0 item" not "0 items" - if (count == 0 || count == 1) - { - form = "A"; - } - else - { - // English-style plural - form = "B"; - } - } - else // default - { - // languages like English with 2 forms, singular and plural - if (count == 1) - { - // "1 item" - form = "A"; - } - else - { - // "2 items", also use plural for "0 items" - form = "B"; - } - } - - // Translate that string - LLStringUtil::format_map_t args; - args["[COUNT]"] = llformat("%d", count); - - // Look up "AgeYearsB" or "AgeWeeksC" including the "form" - std::string key = llformat("%s%s", xml_desc.c_str(), form); - return getString(key, args); -} - -void LLTrans::setDefaultArg(const std::string& name, const std::string& value) -{ - sDefaultArgs[name] = value; -} diff --git a/indra/llxuixml/lltrans.h b/indra/llxuixml/lltrans.h deleted file mode 100644 index 128b51d383..0000000000 --- a/indra/llxuixml/lltrans.h +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @file lltrans.h - * @brief LLTrans definition - * - * $LicenseInfo:firstyear=2000&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_TRANS_H -#define LL_TRANS_H - -#include - -#include "llpointer.h" -#include "llstring.h" - -class LLXMLNode; - -class LLSD; - -/** - * @brief String template loaded from strings.xml - */ -class LLTransTemplate -{ -public: - LLTransTemplate(const std::string& name = LLStringUtil::null, const std::string& text = LLStringUtil::null) : mName(name), mText(text) {} - - std::string mName; - std::string mText; -}; - -/** - * @brief Localized strings class - * This class is used to retrieve translations of strings used to build larger ones, as well as - * strings with a general usage that don't belong to any specific floater. For example, - * "Owner:", "Retrieving..." used in the place of a not yet known name, etc. - */ -class LLTrans -{ -public: - LLTrans(); - - /** - * @brief Parses the xml root that holds the strings. Used once on startup -// *FIXME * @param xml_filename Filename to parse - * @param default_args Set of strings (expected to be in the file) to use as default replacement args, e.g. "SECOND_LIFE" - * @returns true if the file was parsed successfully, true if something went wrong - */ - static bool parseStrings(LLPointer & root, const std::set& default_args); - - static bool parseLanguageStrings(LLPointer & root); - - /** - * @brief Returns a translated string - * @param xml_desc String's description - * @param args A list of substrings to replace in the string - * @returns Translated string - */ - static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); - static std::string getString(const std::string &xml_desc, const LLSD& args); - static bool findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& args); - static bool findString(std::string &result, const std::string &xml_desc, const LLSD& args); - - // Returns translated string with [COUNT] replaced with a number, following - // special per-language logic for plural nouns. For example, some languages - // may have different plurals for 0, 1, 2 and > 2. - // See "AgeWeeksA", "AgeWeeksB", etc. in strings.xml for examples. - static std::string getCountString(const std::string& language, const std::string& xml_desc, S32 count); - - /** - * @brief Returns a translated string - * @param xml_desc String's description - * @returns Translated string - */ - static std::string getString(const std::string &xml_desc) - { - LLStringUtil::format_map_t empty; - return getString(xml_desc, empty); - } - - static bool findString(std::string &result, const std::string &xml_desc) - { - LLStringUtil::format_map_t empty; - return findString(result, xml_desc, empty); - } - - static std::string getKeyboardString(const char* keystring) - { - std::string key_str(keystring); - std::string trans_str; - return findString(trans_str, key_str) ? trans_str : key_str; - } - - // get the default args - static const LLStringUtil::format_map_t& getDefaultArgs() - { - return sDefaultArgs; - } - - static void setDefaultArg(const std::string& name, const std::string& value); - - // insert default args into an arg list - static void getArgs(LLStringUtil::format_map_t& args) - { - args.insert(sDefaultArgs.begin(), sDefaultArgs.end()); - } - -private: - typedef std::map template_map_t; - static template_map_t sStringTemplates; - static LLStringUtil::format_map_t sDefaultArgs; -}; - -#endif diff --git a/indra/llxuixml/lluicolor.cpp b/indra/llxuixml/lluicolor.cpp deleted file mode 100644 index f9bb80f8c5..0000000000 --- a/indra/llxuixml/lluicolor.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file lluicolor.cpp - * @brief brief LLUIColor class implementation file - * - * $LicenseInfo:firstyear=2009&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$ - */ - -#include "linden_common.h" - -#include "lluicolor.h" - -LLUIColor::LLUIColor() - :mColorPtr(NULL) -{ -} - - -LLUIColor::LLUIColor(const LLColor4& color) -: mColor(color), - mColorPtr(NULL) -{ -} - -LLUIColor::LLUIColor(const LLUIColor* color) -: mColorPtr(color) -{ -} - -void LLUIColor::set(const LLColor4& color) -{ - mColor = color; - mColorPtr = NULL; -} - -void LLUIColor::set(const LLUIColor* color) -{ - mColorPtr = color; -} - -const LLColor4& LLUIColor::get() const -{ - return (mColorPtr == NULL ? mColor : mColorPtr->get()); -} - -LLUIColor::operator const LLColor4& () const -{ - return get(); -} - -const LLColor4& LLUIColor::operator()() const -{ - return get(); -} - -bool LLUIColor::isReference() const -{ - return mColorPtr != NULL; -} - -namespace LLInitParam -{ - // used to detect equivalence with default values on export - bool ParamCompare::equals(const LLUIColor &a, const LLUIColor &b) - { - // do not detect value equivalence, treat pointers to colors as distinct from color values - return (a.mColorPtr == NULL && b.mColorPtr == NULL ? a.mColor == b.mColor : a.mColorPtr == b.mColorPtr); - } -} diff --git a/indra/llxuixml/lluicolor.h b/indra/llxuixml/lluicolor.h deleted file mode 100644 index 97ebea854a..0000000000 --- a/indra/llxuixml/lluicolor.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file lluicolor.h - * @brief brief LLUIColor class header file - * - * $LicenseInfo:firstyear=2009&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_LLUICOLOR_H_ -#define LL_LLUICOLOR_H_ - -#include "v4color.h" - -namespace LLInitParam -{ - template - struct ParamCompare; -} - -class LLUIColor -{ -public: - LLUIColor(); - LLUIColor(const LLColor4& color); - LLUIColor(const LLUIColor* color); - - void set(const LLColor4& color); - void set(const LLUIColor* color); - - const LLColor4& get() const; - - operator const LLColor4& () const; - const LLColor4& operator()() const; - - bool isReference() const; - -private: - friend struct LLInitParam::ParamCompare; - - const LLUIColor* mColorPtr; - LLColor4 mColor; -}; - -namespace LLInitParam -{ - template<> - struct ParamCompare - { - static bool equals(const LLUIColor& a, const LLUIColor& b); - }; -} - -#endif diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp deleted file mode 100644 index afc76024d1..0000000000 --- a/indra/llxuixml/llxuiparser.cpp +++ /dev/null @@ -1,1756 +0,0 @@ -/** - * @file llxuiparser.cpp - * @brief Utility functions for handling XUI structures in XML - * - * $LicenseInfo:firstyear=2003&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$ - */ - -#include "linden_common.h" - -#include "llxuiparser.h" - -#include "llxmlnode.h" - -#ifdef LL_STANDALONE -#include -#else -#include "expat/expat.h" -#endif - -#include -#include -//#include -#include - -#include "lluicolor.h" - -using namespace BOOST_SPIRIT_CLASSIC_NS; - -const S32 MAX_STRING_ATTRIBUTE_SIZE = 40; - -static LLInitParam::Parser::parser_read_func_map_t sXSDReadFuncs; -static LLInitParam::Parser::parser_write_func_map_t sXSDWriteFuncs; -static LLInitParam::Parser::parser_inspect_func_map_t sXSDInspectFuncs; - -static LLInitParam::Parser::parser_read_func_map_t sSimpleXUIReadFuncs; -static LLInitParam::Parser::parser_write_func_map_t sSimpleXUIWriteFuncs; -static LLInitParam::Parser::parser_inspect_func_map_t sSimpleXUIInspectFuncs; - -const char* NO_VALUE_MARKER = "no_value"; - -const S32 LINE_NUMBER_HERE = 0; - -struct MaxOccursValues : public LLInitParam::TypeValuesHelper -{ - static void declareValues() - { - declare("unbounded", U32_MAX); - } -}; - -struct Occurs : public LLInitParam::Block -{ - Optional minOccurs; - Optional maxOccurs; - - Occurs() - : minOccurs("minOccurs", 0), - maxOccurs("maxOccurs", U32_MAX) - - {} -}; - - -typedef enum -{ - USE_REQUIRED, - USE_OPTIONAL -} EUse; - -namespace LLInitParam -{ - template<> - struct TypeValues : public TypeValuesHelper - { - static void declareValues() - { - declare("required", USE_REQUIRED); - declare("optional", USE_OPTIONAL); - } - }; -} - -struct Element; -struct Group; -struct Choice; -struct Sequence; -struct Any; - -struct Attribute : public LLInitParam::Block -{ - Mandatory name; - Mandatory type; - Mandatory use; - - Attribute() - : name("name"), - type("type"), - use("use") - {} -}; - -struct Any : public LLInitParam::Block -{ - Optional _namespace; - - Any() - : _namespace("namespace") - {} -}; - -struct All : public LLInitParam::Block -{ - Multiple< Lazy > elements; - - All() - : elements("element") - { - maxOccurs = 1; - } -}; - -struct Choice : public LLInitParam::ChoiceBlock -{ - Alternative< Lazy > element; - Alternative< Lazy > group; - Alternative< Lazy > choice; - Alternative< Lazy > sequence; - Alternative< Lazy > any; - - Choice() - : element("element"), - group("group"), - choice("choice"), - sequence("sequence"), - any("any") - {} - -}; - -struct Sequence : public LLInitParam::ChoiceBlock -{ - Alternative< Lazy > element; - Alternative< Lazy > group; - Alternative< Lazy > choice; - Alternative< Lazy > sequence; - Alternative< Lazy > any; -}; - -struct GroupContents : public LLInitParam::ChoiceBlock -{ - Alternative all; - Alternative choice; - Alternative sequence; - - GroupContents() - : all("all"), - choice("choice"), - sequence("sequence") - {} -}; - -struct Group : public LLInitParam::Block -{ - Optional name, - ref; - - Group() - : name("name"), - ref("ref") - {} -}; - -struct Restriction : public LLInitParam::Block -{ -}; - -struct Extension : public LLInitParam::Block -{ -}; - -struct SimpleContent : public LLInitParam::ChoiceBlock -{ - Alternative restriction; - Alternative extension; - - SimpleContent() - : restriction("restriction"), - extension("extension") - {} -}; - -struct SimpleType : public LLInitParam::Block -{ - // TODO -}; - -struct ComplexContent : public LLInitParam::Block -{ - Optional mixed; - - ComplexContent() - : mixed("mixed", true) - {} -}; - -struct ComplexTypeContents : public LLInitParam::ChoiceBlock -{ - Alternative simple_content; - Alternative complex_content; - Alternative group; - Alternative all; - Alternative choice; - Alternative sequence; - - ComplexTypeContents() - : simple_content("simpleContent"), - complex_content("complexContent"), - group("group"), - all("all"), - choice("choice"), - sequence("sequence") - {} -}; - -struct ComplexType : public LLInitParam::Block -{ - Optional name; - Optional mixed; - - Multiple attribute; - Multiple< Lazy > elements; - - ComplexType() - : name("name"), - attribute("xs:attribute"), - elements("xs:element"), - mixed("mixed") - { - } -}; - -struct ElementContents : public LLInitParam::ChoiceBlock -{ - Alternative simpleType; - Alternative complexType; - - ElementContents() - : simpleType("simpleType"), - complexType("complexType") - {} -}; - -struct Element : public LLInitParam::Block -{ - Optional name, - ref, - type; - - Element() - : name("xs:name"), - ref("xs:ref"), - type("xs:type") - {} -}; - -struct Schema : public LLInitParam::Block -{ -private: - Mandatory targetNamespace, - xmlns, - xs; - -public: - Optional attributeFormDefault, - elementFormDefault; - - Mandatory root_element; - - void setNameSpace(const std::string& ns) {targetNamespace = ns; xmlns = ns;} - - Schema(const std::string& ns = LLStringUtil::null) - : attributeFormDefault("attributeFormDefault"), - elementFormDefault("elementFormDefault"), - xs("xmlns:xs"), - targetNamespace("targetNamespace"), - xmlns("xmlns"), - root_element("xs:element") - { - attributeFormDefault = "unqualified"; - elementFormDefault = "qualified"; - xs = "http://www.w3.org/2001/XMLSchema"; - if (!ns.empty()) - { - setNameSpace(ns); - }; - } - -}; - -// -// LLXSDWriter -// -LLXSDWriter::LLXSDWriter() -: Parser(sXSDReadFuncs, sXSDWriteFuncs, sXSDInspectFuncs) -{ - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedByte", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedByte", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedShort", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedShort", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedInt", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:integer", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:float", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:double", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); - registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); -} - -void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) -{ - Schema schema(xml_namespace); - - schema.root_element.name = type_name; - Choice& choice = schema.root_element.complexType.choice; - - choice.minOccurs = 0; - choice.maxOccurs = "unbounded"; - - mSchemaNode = node; - //node->setName("xs:schema"); - //node->createChild("attributeFormDefault", true)->setStringValue("unqualified"); - //node->createChild("elementFormDefault", true)->setStringValue("qualified"); - //node->createChild("targetNamespace", true)->setStringValue(xml_namespace); - //node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema"); - //node->createChild("xmlns", true)->setStringValue(xml_namespace); - - //node = node->createChild("xs:complexType", false); - //node->createChild("name", true)->setStringValue(type_name); - //node->createChild("mixed", true)->setStringValue("true"); - - //mAttributeNode = node; - //mElementNode = node->createChild("xs:choice", false); - //mElementNode->createChild("minOccurs", true)->setStringValue("0"); - //mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded"); - block.inspectBlock(*this); - - // duplicate element choices - LLXMLNodeList children; - mElementNode->getChildren("xs:element", children, FALSE); - for (LLXMLNodeList::iterator child_it = children.begin(); child_it != children.end(); ++child_it) - { - LLXMLNodePtr child_copy = child_it->second->deepCopy(); - std::string child_name; - child_copy->getAttributeString("name", child_name); - child_copy->setAttributeString("name", type_name + "." + child_name); - mElementNode->addChild(child_copy); - } - - LLXMLNodePtr element_declaration_node = mSchemaNode->createChild("xs:element", false); - element_declaration_node->createChild("name", true)->setStringValue(type_name); - element_declaration_node->createChild("type", true)->setStringValue(type_name); -} - -void LLXSDWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector* possible_values) -{ - name_stack_t non_empty_names; - std::string attribute_name; - for (name_stack_t::const_iterator it = stack.begin(); - it != stack.end(); - ++it) - { - const std::string& name = it->first; - if (!name.empty()) - { - non_empty_names.push_back(*it); - } - } - - for (name_stack_t::const_iterator it = non_empty_names.begin(); - it != non_empty_names.end(); - ++it) - { - if (!attribute_name.empty()) - { - attribute_name += "."; - } - attribute_name += it->first; - } - - // only flag non-nested attributes as mandatory, nested attributes have variant syntax - // that can't be properly constrained in XSD - // e.g. vs - bool attribute_mandatory = min_count == 1 && max_count == 1 && non_empty_names.size() == 1; - - // don't bother supporting "Multiple" params as xml attributes - if (max_count <= 1) - { - // add compound attribute to root node - addAttributeToSchema(mAttributeNode, attribute_name, type, attribute_mandatory, possible_values); - } - - // now generated nested elements for compound attributes - if (non_empty_names.size() > 1 && !attribute_mandatory) - { - std::string element_name; - - // traverse all but last element, leaving that as an attribute name - name_stack_t::const_iterator end_it = non_empty_names.end(); - end_it--; - - for (name_stack_t::const_iterator it = non_empty_names.begin(); - it != end_it; - ++it) - { - if (it != non_empty_names.begin()) - { - element_name += "."; - } - element_name += it->first; - } - - std::string short_attribute_name = non_empty_names.back().first; - - LLXMLNodePtr complex_type_node; - - // find existing element node here, starting at tail of child list - if (mElementNode->mChildren.notNull()) - { - for(LLXMLNodePtr element = mElementNode->mChildren->tail; - element.notNull(); - element = element->mPrev) - { - std::string name; - if(element->getAttributeString("name", name) && name == element_name) - { - complex_type_node = element->mChildren->head; - break; - } - } - } - //create complex_type node - // - // - // - // - // - if(complex_type_node.isNull()) - { - complex_type_node = mElementNode->createChild("xs:element", false); - - complex_type_node->createChild("minOccurs", true)->setIntValue(min_count); - complex_type_node->createChild("maxOccurs", true)->setIntValue(max_count); - complex_type_node->createChild("name", true)->setStringValue(element_name); - complex_type_node = complex_type_node->createChild("xs:complexType", false); - } - - addAttributeToSchema(complex_type_node, short_attribute_name, type, false, possible_values); - } -} - -void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector* possible_values) -{ - if (!attribute_name.empty()) - { - LLXMLNodePtr new_enum_type_node; - if (possible_values != NULL) - { - // custom attribute type, for example - // - // - // - // - // - // - new_enum_type_node = new LLXMLNode("xs:simpleType", false); - - LLXMLNodePtr restriction_node = new_enum_type_node->createChild("xs:restriction", false); - restriction_node->createChild("base", true)->setStringValue("xs:string"); - - for (std::vector::const_iterator it = possible_values->begin(); - it != possible_values->end(); - ++it) - { - LLXMLNodePtr enum_node = restriction_node->createChild("xs:enumeration", false); - enum_node->createChild("value", true)->setStringValue(*it); - } - } - - string_set_t& attributes_written = mAttributesWritten[type_declaration_node]; - - string_set_t::iterator found_it = attributes_written.lower_bound(attribute_name); - - // attribute not yet declared - if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it)) - { - attributes_written.insert(found_it, attribute_name); - - LLXMLNodePtr attribute_node = type_declaration_node->createChild("xs:attribute", false); - - // attribute name - attribute_node->createChild("name", true)->setStringValue(attribute_name); - - if (new_enum_type_node.notNull()) - { - attribute_node->addChild(new_enum_type_node); - } - else - { - // simple attribute type - attribute_node->createChild("type", true)->setStringValue(type); - } - - // required or optional - attribute_node->createChild("use", true)->setStringValue(mandatory ? "required" : "optional"); - } - // attribute exists...handle collision of same name attributes with potentially different types - else - { - LLXMLNodePtr attribute_declaration; - if (type_declaration_node.notNull()) - { - for(LLXMLNodePtr node = type_declaration_node->mChildren->tail; - node.notNull(); - node = node->mPrev) - { - std::string name; - if (node->getAttributeString("name", name) && name == attribute_name) - { - attribute_declaration = node; - break; - } - } - } - - bool new_type_is_enum = new_enum_type_node.notNull(); - bool existing_type_is_enum = !attribute_declaration->hasAttribute("type"); - - // either type is enum, revert to string in collision - // don't bother to check for enum equivalence - if (new_type_is_enum || existing_type_is_enum) - { - if (attribute_declaration->hasAttribute("type")) - { - attribute_declaration->setAttributeString("type", "xs:string"); - } - else - { - attribute_declaration->createChild("type", true)->setStringValue("xs:string"); - } - attribute_declaration->deleteChildren("xs:simpleType"); - } - else - { - // check for collision of different standard types - std::string existing_type; - attribute_declaration->getAttributeString("type", existing_type); - // if current type is not the same as the new type, revert to strnig - if (existing_type != type) - { - // ...than use most general type, string - attribute_declaration->setAttributeString("type", "string"); - } - } - } - } -} - -// -// LLXUIXSDWriter -// -void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& path, const LLInitParam::BaseBlock& block) -{ - std::string file_name(path); - file_name += type_name + ".xsd"; - LLXMLNodePtr root_nodep = new LLXMLNode(); - - LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui"); - - // add includes for all possible children - const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name); - const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type); - - // add choices for valid children - if (widget_registryp) - { - // add include declarations for all valid children - for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); - it != widget_registryp->currentRegistrar().endItems(); - ++it) - { - std::string widget_name = it->first; - if (widget_name == type_name) - { - continue; - } - LLXMLNodePtr nodep = new LLXMLNode("xs:include", false); - nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd"); - - // add to front of schema - mSchemaNode->addChild(nodep, mSchemaNode); - } - - for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); - it != widget_registryp->currentRegistrar().endItems(); - ++it) - { - std::string widget_name = it->first; - // - LLXMLNodePtr widget_node = mElementNode->createChild("xs:element", false); - widget_node->createChild("name", true)->setStringValue(widget_name); - widget_node->createChild("type", true)->setStringValue(widget_name); - } - } - - LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w"); - LLXMLNode::writeHeaderToFile(xsd_file); - root_nodep->writeToFile(xsd_file); - fclose(xsd_file); -} - -static LLInitParam::Parser::parser_read_func_map_t sXUIReadFuncs; -static LLInitParam::Parser::parser_write_func_map_t sXUIWriteFuncs; -static LLInitParam::Parser::parser_inspect_func_map_t sXUIInspectFuncs; - -// -// LLXUIParser -// -LLXUIParser::LLXUIParser() -: Parser(sXUIReadFuncs, sXUIWriteFuncs, sXUIInspectFuncs), - mCurReadDepth(0) -{ - if (sXUIReadFuncs.empty()) - { - registerParserFuncs(readFlag, writeFlag); - registerParserFuncs(readBoolValue, writeBoolValue); - registerParserFuncs(readStringValue, writeStringValue); - registerParserFuncs(readU8Value, writeU8Value); - registerParserFuncs(readS8Value, writeS8Value); - registerParserFuncs(readU16Value, writeU16Value); - registerParserFuncs(readS16Value, writeS16Value); - registerParserFuncs(readU32Value, writeU32Value); - registerParserFuncs(readS32Value, writeS32Value); - registerParserFuncs(readF32Value, writeF32Value); - registerParserFuncs(readF64Value, writeF64Value); - registerParserFuncs(readColor4Value, writeColor4Value); - registerParserFuncs(readUIColorValue, writeUIColorValue); - registerParserFuncs(readUUIDValue, writeUUIDValue); - registerParserFuncs(readSDValue, writeSDValue); - } -} - -static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing"); -const LLXMLNodePtr DUMMY_NODE = new LLXMLNode(); - -void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent) -{ - LLFastTimer timer(FTM_PARSE_XUI); - mNameStack.clear(); - mRootNodeName = node->getName()->mString; - mCurFileName = filename; - mCurReadDepth = 0; - setParseSilently(silent); - - if (node.isNull()) - { - parserWarning("Invalid node"); - } - else - { - readXUIImpl(node, block); - } -} - -bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) -{ - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("."); - - bool values_parsed = false; - bool silent = mCurReadDepth > 0; - - if (nodep->getFirstChild().isNull() - && nodep->mAttributes.empty() - && nodep->getSanitizedValue().empty()) - { - // empty node, just parse as flag - mCurReadNode = DUMMY_NODE; - return block.submitValue(mNameStack, *this, silent); - } - - // submit attributes for current node - values_parsed |= readAttributes(nodep, block); - - // treat text contents of xml node as "value" parameter - std::string text_contents = nodep->getSanitizedValue(); - if (!text_contents.empty()) - { - mCurReadNode = nodep; - mNameStack.push_back(std::make_pair(std::string("value"), true)); - // child nodes are not necessarily valid parameters (could be a child widget) - // so don't complain once we've recursed - if (!block.submitValue(mNameStack, *this, true)) - { - mNameStack.pop_back(); - block.submitValue(mNameStack, *this, silent); - } - else - { - mNameStack.pop_back(); - } - } - - // then traverse children - // child node must start with last name of parent node (our "scope") - // for example: "" - // which equates to the following nesting: - // button - // param - // nested_param1 - // nested_param2 - // nested_param3 - mCurReadDepth++; - for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();) - { - std::string child_name(childp->getName()->mString); - S32 num_tokens_pushed = 0; - - // for non "dotted" child nodes check to see if child node maps to another widget type - // and if not, treat as a child element of the current node - // e.g. will interpret as "button.rect" - // since there is no widget named "rect" - if (child_name.find(".") == std::string::npos) - { - mNameStack.push_back(std::make_pair(child_name, true)); - num_tokens_pushed++; - } - else - { - // parse out "dotted" name into individual tokens - tokenizer name_tokens(child_name, sep); - - tokenizer::iterator name_token_it = name_tokens.begin(); - if(name_token_it == name_tokens.end()) - { - childp = childp->getNextSibling(); - continue; - } - - // check for proper nesting - if (mNameStack.empty()) - { - if (*name_token_it != mRootNodeName) - { - childp = childp->getNextSibling(); - continue; - } - } - else if(mNameStack.back().first != *name_token_it) - { - childp = childp->getNextSibling(); - continue; - } - - // now ignore first token - ++name_token_it; - - // copy remaining tokens on to our running token list - for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) - { - mNameStack.push_back(std::make_pair(*token_to_push, true)); - num_tokens_pushed++; - } - } - - // recurse and visit children XML nodes - if(readXUIImpl(childp, block)) - { - // child node successfully parsed, remove from DOM - - values_parsed = true; - LLXMLNodePtr node_to_remove = childp; - childp = childp->getNextSibling(); - - nodep->deleteChild(node_to_remove); - } - else - { - childp = childp->getNextSibling(); - } - - while(num_tokens_pushed-- > 0) - { - mNameStack.pop_back(); - } - } - mCurReadDepth--; - return values_parsed; -} - -bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) -{ - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("."); - - bool any_parsed = false; - bool silent = mCurReadDepth > 0; - - for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin(); - attribute_it != nodep->mAttributes.end(); - ++attribute_it) - { - S32 num_tokens_pushed = 0; - std::string attribute_name(attribute_it->first->mString); - mCurReadNode = attribute_it->second; - - tokenizer name_tokens(attribute_name, sep); - // copy remaining tokens on to our running token list - for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) - { - mNameStack.push_back(std::make_pair(*token_to_push, true)); - num_tokens_pushed++; - } - - // child nodes are not necessarily valid attributes, so don't complain once we've recursed - any_parsed |= block.submitValue(mNameStack, *this, silent); - - while(num_tokens_pushed-- > 0) - { - mNameStack.pop_back(); - } - } - - return any_parsed; -} - -void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block) -{ - mWriteRootNode = node; - name_stack_t name_stack = Parser::name_stack_t(); - block.serializeBlock(*this, name_stack, diff_block); - mOutNodes.clear(); -} - -// go from a stack of names to a specific XML node -LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack) -{ - LLXMLNodePtr out_node = mWriteRootNode; - - name_stack_t::iterator next_it = stack.begin(); - for (name_stack_t::iterator it = stack.begin(); - it != stack.end(); - it = next_it) - { - ++next_it; - if (it->first.empty()) - { - it->second = false; - continue; - } - - out_nodes_t::iterator found_it = mOutNodes.find(it->first); - - // node with this name not yet written - if (found_it == mOutNodes.end() || it->second) - { - // make an attribute if we are the last element on the name stack - bool is_attribute = next_it == stack.end(); - LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute); - out_node->addChild(new_node); - mOutNodes[it->first] = new_node; - out_node = new_node; - it->second = false; - } - else - { - out_node = found_it->second; - } - } - - return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node); -} - -bool LLXUIParser::readFlag(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - return self.mCurReadNode == DUMMY_NODE; -} - -bool LLXUIParser::writeFlag(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - // just create node - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - return node.notNull(); -} - -bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr) -{ - S32 value; - LLXUIParser& self = static_cast(parser); - bool success = self.mCurReadNode->getBoolValue(1, &value); - *((bool*)val_ptr) = (value != FALSE); - return success; -} - -bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setBoolValue(*((bool*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - *((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue(); - return true; -} - -bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - const std::string* string_val = reinterpret_cast(val_ptr); - if (string_val->find('\n') != std::string::npos - || string_val->size() > MAX_STRING_ATTRIBUTE_SIZE) - { - // don't write strings with newlines into attributes - std::string attribute_name = node->getName()->mString; - LLXMLNodePtr parent_node = node->mParent; - parent_node->deleteChild(node); - // write results in text contents of node - if (attribute_name == "value") - { - // "value" is implicit, just write to parent - node = parent_node; - } - else - { - // create a child that is not an attribute, but with same name - node = parent_node->createChild(attribute_name.c_str(), false); - } - } - node->setStringValue(*string_val); - return true; - } - return false; -} - -bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - return self.mCurReadNode->getByteValue(1, (U8*)val_ptr); -} - -bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setUnsignedValue(*((U8*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - S32 value; - if(self.mCurReadNode->getIntValue(1, &value)) - { - *((S8*)val_ptr) = value; - return true; - } - return false; -} - -bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setIntValue(*((S8*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - U32 value; - if(self.mCurReadNode->getUnsignedValue(1, &value)) - { - *((U16*)val_ptr) = value; - return true; - } - return false; -} - -bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setUnsignedValue(*((U16*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - S32 value; - if(self.mCurReadNode->getIntValue(1, &value)) - { - *((S16*)val_ptr) = value; - return true; - } - return false; -} - -bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setIntValue(*((S16*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr); -} - -bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setUnsignedValue(*((U32*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - return self.mCurReadNode->getIntValue(1, (S32*)val_ptr); -} - -bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setIntValue(*((S32*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr); -} - -bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setFloatValue(*((F32*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr); -} - -bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setDoubleValue(*((F64*)val_ptr)); - return true; - } - return false; -} - -bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - LLColor4* colorp = (LLColor4*)val_ptr; - if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3) - { - return true; - } - - return false; -} - -bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - LLColor4 color = *((LLColor4*)val_ptr); - node->setFloatValue(4, color.mV); - return true; - } - return false; -} - -bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - LLUIColor* param = (LLUIColor*)val_ptr; - LLColor4 color; - bool success = self.mCurReadNode->getFloatValue(4, color.mV) >= 3; - if (success) - { - param->set(color); - return true; - } - return false; -} - -bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - LLUIColor color = *((LLUIColor*)val_ptr); - //RN: don't write out the color that is represented by a function - // rely on param block exporting to get the reference to the color settings - if (color.isReference()) return false; - node->setFloatValue(4, color.get().mV); - return true; - } - return false; -} - -bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - LLUUID temp_id; - // LLUUID::set is destructive, so use temporary value - if (temp_id.set(self.mCurReadNode->getSanitizedValue())) - { - *(LLUUID*)(val_ptr) = temp_id; - return true; - } - return false; -} - -bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - node->setStringValue(((LLUUID*)val_ptr)->asString()); - return true; - } - return false; -} - -bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr) -{ - LLXUIParser& self = static_cast(parser); - *((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue()); - return true; -} - -bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, name_stack_t& stack) -{ - LLXUIParser& self = static_cast(parser); - - LLXMLNodePtr node = self.getNode(stack); - if (node.notNull()) - { - std::string string_val = ((LLSD*)val_ptr)->asString(); - if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE) - { - // don't write strings with newlines into attributes - std::string attribute_name = node->getName()->mString; - LLXMLNodePtr parent_node = node->mParent; - parent_node->deleteChild(node); - // write results in text contents of node - if (attribute_name == "value") - { - // "value" is implicit, just write to parent - node = parent_node; - } - else - { - node = parent_node->createChild(attribute_name.c_str(), false); - } - } - - node->setStringValue(string_val); - return true; - } - return false; -} - -/*virtual*/ std::string LLXUIParser::getCurrentElementName() -{ - std::string full_name; - for (name_stack_t::iterator it = mNameStack.begin(); - it != mNameStack.end(); - ++it) - { - full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." - } - - return full_name; -} - -void LLXUIParser::parserWarning(const std::string& message) -{ -#ifdef LL_WINDOWS - // use Visual Studo friendly formatting of output message for easy access to originating xml - llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); - utf16str += '\n'; - OutputDebugString(utf16str.c_str()); -#else - Parser::parserWarning(message); -#endif -} - -void LLXUIParser::parserError(const std::string& message) -{ -#ifdef LL_WINDOWS - llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); - utf16str += '\n'; - OutputDebugString(utf16str.c_str()); -#else - Parser::parserError(message); -#endif -} - - -// -// LLSimpleXUIParser -// - -struct ScopedFile -{ - ScopedFile( const std::string& filename, const char* accessmode ) - { - mFile = LLFile::fopen(filename, accessmode); - } - - ~ScopedFile() - { - fclose(mFile); - mFile = NULL; - } - - S32 getRemainingBytes() - { - if (!isOpen()) return 0; - - S32 cur_pos = ftell(mFile); - fseek(mFile, 0L, SEEK_END); - S32 file_size = ftell(mFile); - fseek(mFile, cur_pos, SEEK_SET); - return file_size - cur_pos; - } - - bool isOpen() { return mFile != NULL; } - - LLFILE* mFile; -}; -LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb) -: Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs), - mCurReadDepth(0), - mElementCB(element_cb) -{ - if (sSimpleXUIReadFuncs.empty()) - { - registerParserFuncs(readFlag); - registerParserFuncs(readBoolValue); - registerParserFuncs(readStringValue); - registerParserFuncs(readU8Value); - registerParserFuncs(readS8Value); - registerParserFuncs(readU16Value); - registerParserFuncs(readS16Value); - registerParserFuncs(readU32Value); - registerParserFuncs(readS32Value); - registerParserFuncs(readF32Value); - registerParserFuncs(readF64Value); - registerParserFuncs(readColor4Value); - registerParserFuncs(readUIColorValue); - registerParserFuncs(readUUIDValue); - registerParserFuncs(readSDValue); - } -} - -LLSimpleXUIParser::~LLSimpleXUIParser() -{ -} - - -bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent) -{ - LLFastTimer timer(FTM_PARSE_XUI); - - mParser = XML_ParserCreate(NULL); - XML_SetUserData(mParser, this); - XML_SetElementHandler( mParser, startElementHandler, endElementHandler); - XML_SetCharacterDataHandler( mParser, characterDataHandler); - - mOutputStack.push_back(std::make_pair(&block, 0)); - mNameStack.clear(); - mCurFileName = filename; - mCurReadDepth = 0; - setParseSilently(silent); - - ScopedFile file(filename, "rb"); - if( !file.isOpen() ) - { - LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL; - XML_ParserFree( mParser ); - return false; - } - - S32 bytes_read = 0; - - S32 buffer_size = file.getRemainingBytes(); - void* buffer = XML_GetBuffer(mParser, buffer_size); - if( !buffer ) - { - LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL; - XML_ParserFree( mParser ); - return false; - } - - bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile); - if( bytes_read <= 0 ) - { - LL_WARNS("ReadXUI") << "Error while reading file " << filename << LL_ENDL; - XML_ParserFree( mParser ); - return false; - } - - mEmptyLeafNode.push_back(false); - - if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) ) - { - LL_WARNS("ReadXUI") << "Error while parsing file " << filename << LL_ENDL; - XML_ParserFree( mParser ); - return false; - } - - mEmptyLeafNode.pop_back(); - - XML_ParserFree( mParser ); - return true; -} - -void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts) -{ - LLSimpleXUIParser* self = reinterpret_cast(userData); - self->startElement(name, atts); -} - -void LLSimpleXUIParser::endElementHandler(void *userData, const char *name) -{ - LLSimpleXUIParser* self = reinterpret_cast(userData); - self->endElement(name); -} - -void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len) -{ - LLSimpleXUIParser* self = reinterpret_cast(userData); - self->characterData(s, len); -} - -void LLSimpleXUIParser::characterData(const char *s, int len) -{ - mTextContents += std::string(s, len); -} - -void LLSimpleXUIParser::startElement(const char *name, const char **atts) -{ - processText(); - - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("."); - - if (mElementCB) - { - LLInitParam::BaseBlock* blockp = mElementCB(*this, name); - if (blockp) - { - mOutputStack.push_back(std::make_pair(blockp, 0)); - } - } - - mOutputStack.back().second++; - S32 num_tokens_pushed = 0; - std::string child_name(name); - - if (mOutputStack.back().second == 1) - { // root node for this block - mScope.push_back(child_name); - } - else - { // compound attribute - if (child_name.find(".") == std::string::npos) - { - mNameStack.push_back(std::make_pair(child_name, true)); - num_tokens_pushed++; - mScope.push_back(child_name); - } - else - { - // parse out "dotted" name into individual tokens - tokenizer name_tokens(child_name, sep); - - tokenizer::iterator name_token_it = name_tokens.begin(); - if(name_token_it == name_tokens.end()) - { - return; - } - - // check for proper nesting - if(!mScope.empty() && *name_token_it != mScope.back()) - { - return; - } - - // now ignore first token - ++name_token_it; - - // copy remaining tokens on to our running token list - for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) - { - mNameStack.push_back(std::make_pair(*token_to_push, true)); - num_tokens_pushed++; - } - mScope.push_back(mNameStack.back().first); - } - } - - // parent node is not empty - mEmptyLeafNode.back() = false; - // we are empty if we have no attributes - mEmptyLeafNode.push_back(atts[0] == NULL); - - mTokenSizeStack.push_back(num_tokens_pushed); - readAttributes(atts); - -} - -void LLSimpleXUIParser::endElement(const char *name) -{ - bool has_text = processText(); - - // no text, attributes, or children - if (!has_text && mEmptyLeafNode.back()) - { - // submit this as a valueless name (even though there might be text contents we haven't seen yet) - mCurAttributeValueBegin = NO_VALUE_MARKER; - mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); - } - - if (--mOutputStack.back().second == 0) - { - if (mOutputStack.empty()) - { - LL_ERRS("ReadXUI") << "Parameter block output stack popped while empty." << LL_ENDL; - } - mOutputStack.pop_back(); - } - - S32 num_tokens_to_pop = mTokenSizeStack.back(); - mTokenSizeStack.pop_back(); - while(num_tokens_to_pop-- > 0) - { - mNameStack.pop_back(); - } - mScope.pop_back(); - mEmptyLeafNode.pop_back(); -} - -bool LLSimpleXUIParser::readAttributes(const char **atts) -{ - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("."); - - bool any_parsed = false; - for(S32 i = 0; atts[i] && atts[i+1]; i += 2 ) - { - std::string attribute_name(atts[i]); - mCurAttributeValueBegin = atts[i+1]; - - S32 num_tokens_pushed = 0; - tokenizer name_tokens(attribute_name, sep); - // copy remaining tokens on to our running token list - for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) - { - mNameStack.push_back(std::make_pair(*token_to_push, true)); - num_tokens_pushed++; - } - - // child nodes are not necessarily valid attributes, so don't complain once we've recursed - any_parsed |= mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); - - while(num_tokens_pushed-- > 0) - { - mNameStack.pop_back(); - } - } - return any_parsed; -} - -bool LLSimpleXUIParser::processText() -{ - if (!mTextContents.empty()) - { - LLStringUtil::trim(mTextContents); - if (!mTextContents.empty()) - { - mNameStack.push_back(std::make_pair(std::string("value"), true)); - mCurAttributeValueBegin = mTextContents.c_str(); - mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); - mNameStack.pop_back(); - } - mTextContents.clear(); - return true; - } - return false; -} - -/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName() -{ - std::string full_name; - for (name_stack_t::iterator it = mNameStack.begin(); - it != mNameStack.end(); - ++it) - { - full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." - } - - return full_name; -} - -void LLSimpleXUIParser::parserWarning(const std::string& message) -{ -#ifdef LL_WINDOWS - // use Visual Studo friendly formatting of output message for easy access to originating xml - llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str()); - utf16str += '\n'; - OutputDebugString(utf16str.c_str()); -#else - Parser::parserWarning(message); -#endif -} - -void LLSimpleXUIParser::parserError(const std::string& message) -{ -#ifdef LL_WINDOWS - llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str()); - utf16str += '\n'; - OutputDebugString(utf16str.c_str()); -#else - Parser::parserError(message); -#endif -} - -bool LLSimpleXUIParser::readFlag(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return self.mCurAttributeValueBegin == NO_VALUE_MARKER; -} - -bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - if (!strcmp(self.mCurAttributeValueBegin, "true")) - { - *((bool*)val_ptr) = true; - return true; - } - else if (!strcmp(self.mCurAttributeValueBegin, "false")) - { - *((bool*)val_ptr) = false; - return true; - } - - return false; -} - -bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - *((std::string*)val_ptr) = self.mCurAttributeValueBegin; - return true; -} - -bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full; -} - -bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full; -} - -bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full; -} - -bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full; -} - -bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full; -} - -bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full; -} - -bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full; -} - -bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full; -} - -bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - LLColor4 value; - - if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) - { - *(LLColor4*)(val_ptr) = value; - return true; - } - return false; -} - -bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - LLColor4 value; - LLUIColor* colorp = (LLUIColor*)val_ptr; - - if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) - { - colorp->set(value); - return true; - } - return false; -} - -bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - LLUUID temp_id; - // LLUUID::set is destructive, so use temporary value - if (temp_id.set(std::string(self.mCurAttributeValueBegin))) - { - *(LLUUID*)(val_ptr) = temp_id; - return true; - } - return false; -} - -bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr) -{ - LLSimpleXUIParser& self = static_cast(parser); - *((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin); - return true; -} diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h deleted file mode 100644 index d7cd256967..0000000000 --- a/indra/llxuixml/llxuiparser.h +++ /dev/null @@ -1,242 +0,0 @@ -/** - * @file llxuiparser.h - * @brief Utility functions for handling XUI structures in XML - * - * $LicenseInfo:firstyear=2003&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 LLXUIPARSER_H -#define LLXUIPARSER_H - -#include "llinitparam.h" -#include "llregistry.h" -#include "llpointer.h" - -#include -#include -#include -#include - - - -class LLView; - - -typedef LLPointer LLXMLNodePtr; - - -// lookup widget type by name -class LLWidgetTypeRegistry -: public LLRegistrySingleton -{}; - - -// global static instance for registering all widget types -typedef boost::function LLWidgetCreatorFunc; - -typedef LLRegistry widget_registry_t; - -class LLChildRegistryRegistry -: public LLRegistrySingleton -{}; - - - -class LLXSDWriter : public LLInitParam::Parser -{ - LOG_CLASS(LLXSDWriter); -public: - void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); - - /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } - - LLXSDWriter(); - -protected: - void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector* possible_values); - void addAttributeToSchema(LLXMLNodePtr nodep, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector* possible_values); - LLXMLNodePtr mAttributeNode; - LLXMLNodePtr mElementNode; - LLXMLNodePtr mSchemaNode; - - typedef std::set string_set_t; - typedef std::map attributes_map_t; - attributes_map_t mAttributesWritten; -}; - - - -// NOTE: DOES NOT WORK YET -// should support child widgets for XUI -class LLXUIXSDWriter : public LLXSDWriter -{ -public: - void writeXSD(const std::string& name, const std::string& path, const LLInitParam::BaseBlock& block); -}; - - -class LLXUIParserImpl; - -class LLXUIParser : public LLInitParam::Parser -{ -LOG_CLASS(LLXUIParser); - -public: - LLXUIParser(); - typedef LLInitParam::Parser::name_stack_t name_stack_t; - - /*virtual*/ std::string getCurrentElementName(); - /*virtual*/ void parserWarning(const std::string& message); - /*virtual*/ void parserError(const std::string& message); - - void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false); - void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL); - -private: - bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block); - bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block); - - //reader helper functions - static bool readFlag(Parser& parser, void* val_ptr); - static bool readBoolValue(Parser& parser, void* val_ptr); - static bool readStringValue(Parser& parser, void* val_ptr); - static bool readU8Value(Parser& parser, void* val_ptr); - static bool readS8Value(Parser& parser, void* val_ptr); - static bool readU16Value(Parser& parser, void* val_ptr); - static bool readS16Value(Parser& parser, void* val_ptr); - static bool readU32Value(Parser& parser, void* val_ptr); - static bool readS32Value(Parser& parser, void* val_ptr); - static bool readF32Value(Parser& parser, void* val_ptr); - static bool readF64Value(Parser& parser, void* val_ptr); - static bool readColor4Value(Parser& parser, void* val_ptr); - static bool readUIColorValue(Parser& parser, void* val_ptr); - static bool readUUIDValue(Parser& parser, void* val_ptr); - static bool readSDValue(Parser& parser, void* val_ptr); - - //writer helper functions - static bool writeFlag(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeStringValue(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeU8Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeS8Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeU16Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeS16Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeU32Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&); - static bool writeSDValue(Parser& parser, const void* val_ptr, name_stack_t&); - - LLXMLNodePtr getNode(name_stack_t& stack); - -private: - Parser::name_stack_t mNameStack; - LLXMLNodePtr mCurReadNode; - // Root of the widget XML sub-tree, for example, "line_editor" - LLXMLNodePtr mWriteRootNode; - - typedef std::map out_nodes_t; - out_nodes_t mOutNodes; - LLXMLNodePtr mLastWrittenChild; - S32 mCurReadDepth; - std::string mCurFileName; - std::string mRootNodeName; -}; - -// LLSimpleXUIParser is a streamlined SAX-based XUI parser that does not support localization -// or parsing of a tree of independent param blocks, such as child widgets. -// Use this for reading non-localized files that only need a single param block as a result. -// -// NOTE: In order to support nested block parsing, we need callbacks for start element that -// push new blocks contexts on the mScope stack. -// NOTE: To support localization without building a DOM, we need to enforce consistent -// ordering of child elements from base file to localized diff file. Then we can use a pair -// of coroutines to perform matching of xml nodes during parsing. Not sure if the overhead -// of coroutines would offset the gain from SAX parsing -class LLSimpleXUIParserImpl; - -class LLSimpleXUIParser : public LLInitParam::Parser -{ -LOG_CLASS(LLSimpleXUIParser); -public: - typedef LLInitParam::Parser::name_stack_t name_stack_t; - typedef LLInitParam::BaseBlock* (*element_start_callback_t)(LLSimpleXUIParser&, const char* block_name); - - LLSimpleXUIParser(element_start_callback_t element_cb = NULL); - virtual ~LLSimpleXUIParser(); - - /*virtual*/ std::string getCurrentElementName(); - /*virtual*/ void parserWarning(const std::string& message); - /*virtual*/ void parserError(const std::string& message); - - bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false); - - -private: - //reader helper functions - static bool readFlag(Parser&, void* val_ptr); - static bool readBoolValue(Parser&, void* val_ptr); - static bool readStringValue(Parser&, void* val_ptr); - static bool readU8Value(Parser&, void* val_ptr); - static bool readS8Value(Parser&, void* val_ptr); - static bool readU16Value(Parser&, void* val_ptr); - static bool readS16Value(Parser&, void* val_ptr); - static bool readU32Value(Parser&, void* val_ptr); - static bool readS32Value(Parser&, void* val_ptr); - static bool readF32Value(Parser&, void* val_ptr); - static bool readF64Value(Parser&, void* val_ptr); - static bool readColor4Value(Parser&, void* val_ptr); - static bool readUIColorValue(Parser&, void* val_ptr); - static bool readUUIDValue(Parser&, void* val_ptr); - static bool readSDValue(Parser&, void* val_ptr); - -private: - static void startElementHandler(void *userData, const char *name, const char **atts); - static void endElementHandler(void *userData, const char *name); - static void characterDataHandler(void *userData, const char *s, int len); - - void startElement(const char *name, const char **atts); - void endElement(const char *name); - void characterData(const char *s, int len); - bool readAttributes(const char **atts); - bool processText(); - - Parser::name_stack_t mNameStack; - struct XML_ParserStruct* mParser; - LLXMLNodePtr mLastWrittenChild; - S32 mCurReadDepth; - std::string mCurFileName; - std::string mTextContents; - const char* mCurAttributeValueBegin; - std::vector mTokenSizeStack; - std::vector mScope; - std::vector mEmptyLeafNode; - element_start_callback_t mElementCB; - - std::vector > mOutputStack; -}; - - -#endif //LLXUIPARSER_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6b2fe1e45a..baf7627f06 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -30,7 +30,6 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) -include(LLXUIXML) include(LScript) include(Linking) include(NDOF) @@ -65,7 +64,6 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLXUIXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS}/lscript_compile ${LLLOGIN_INCLUDE_DIRS} @@ -1740,7 +1738,6 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLVFS_LIBRARIES} ${LLWINDOW_LIBRARIES} ${LLXML_LIBRARIES} - ${LLXUIXML_LIBRARIES} ${LSCRIPT_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index f738b84bb9..6c8a827ba3 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -57,6 +57,8 @@ #include "lldeleteutils.h" #include "imageids.h" #include "indra_constants.h" +#include "llinitparam.h" + //#include "linden_common.h" //#include "llpreprocessor.h" #include "llallocator.h" @@ -124,7 +126,5 @@ // Library includes from llmessage project #include "llcachename.h" -// Library includes from llxuixml -#include "llinitparam.h" #endif -- cgit v1.3 From 4287dcaacf0804a5a73dbf37c629471e2855733c Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 20 Jan 2012 14:55:39 -0800 Subject: moved LLSDParam to llcommon so that LLSD<->Param Block conversion are usable by everyone --- indra/llcommon/CMakeLists.txt | 2 + indra/llcommon/llinitparam.h | 4 +- indra/llcommon/llsdparam.cpp | 342 ++++++++++++++++++++++++++++++++++++++++++ indra/llcommon/llsdparam.h | 126 ++++++++++++++++ indra/llui/CMakeLists.txt | 2 - indra/llui/llsdparam.cpp | 342 ------------------------------------------ indra/llui/llsdparam.h | 126 ---------------- 7 files changed, 472 insertions(+), 472 deletions(-) create mode 100644 indra/llcommon/llsdparam.cpp create mode 100644 indra/llcommon/llsdparam.h delete mode 100644 indra/llui/llsdparam.cpp delete mode 100644 indra/llui/llsdparam.h (limited to 'indra/llui') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 72b1d363b0..a1aa887d3a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -82,6 +82,7 @@ set(llcommon_SOURCE_FILES llrefcount.cpp llrun.cpp llsd.cpp + llsdparam.cpp llsdserialize.cpp llsdserialize_xml.cpp llsdutil.cpp @@ -211,6 +212,7 @@ set(llcommon_HEADER_FILES llrefcount.h llsafehandle.h llsd.h + llsdparam.h llsdserialize.h llsdserialize_xml.h llsdutil.h diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 550e1608cc..beaf07e56b 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -2057,8 +2057,8 @@ namespace LLInitParam // block param interface - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; + LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); + LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { //TODO: implement LLSD params as schema type Any diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp new file mode 100644 index 0000000000..0e29873bb0 --- /dev/null +++ b/indra/llcommon/llsdparam.cpp @@ -0,0 +1,342 @@ +/** + * @file llsdparam.cpp + * @brief parameter block abstraction for creating complex objects and + * parsing construction parameters from xml and LLSD + * + * $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$ + */ + +#include "linden_common.h" + +// 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; +static const LLSD NO_VALUE_MARKER; + +LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion"); + +// +// LLParamSDParser +// +LLParamSDParser::LLParamSDParser() +: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs) +{ + using boost::bind; + + if (sReadFuncs.empty()) + { + registerParserFuncs(readFlag, &LLParamSDParser::writeFlag); + registerParserFuncs(readS32, &LLParamSDParser::writeTypedValue); + registerParserFuncs(readU32, &LLParamSDParser::writeU32Param); + registerParserFuncs(readF32, &LLParamSDParser::writeTypedValue); + registerParserFuncs(readF64, &LLParamSDParser::writeTypedValue); + registerParserFuncs(readBool, &LLParamSDParser::writeTypedValue); + registerParserFuncs(readString, &LLParamSDParser::writeTypedValue); + registerParserFuncs(readUUID, &LLParamSDParser::writeTypedValue); + registerParserFuncs(readDate, &LLParamSDParser::writeTypedValue); + registerParserFuncs(readURI, &LLParamSDParser::writeTypedValue); + registerParserFuncs(readSD, &LLParamSDParser::writeTypedValue); + } +} + +// special case handling of U32 due to ambiguous LLSD::assign overload +bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack) +{ + LLParamSDParser& sdparser = static_cast(parser); + if (!sdparser.mWriteRootSD) return false; + + parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end()); + LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range); + sd_to_write.assign((S32)*((const U32*)val_ptr)); + + return true; +} + +bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack) +{ + LLParamSDParser& sdparser = static_cast(parser); + if (!sdparser.mWriteRootSD) return false; + + parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end()); + LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range); + + return true; +} + +void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack) +{ + mCurReadSD = &sd; + block.submitValue(name_stack, *this); +} + +void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent) +{ + mCurReadSD = NULL; + mNameStack.clear(); + setParseSilently(silent); + + LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack); + //readSDValues(sd, block); +} + +void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block) +{ + mNameStack.clear(); + mWriteRootSD = &sd; + + name_stack_t name_stack; + block.serializeBlock(*this, name_stack); +} + +/*virtual*/ std::string LLParamSDParser::getCurrentElementName() +{ + std::string full_name = "sd"; + for (name_stack_t::iterator it = mNameStack.begin(); + it != mNameStack.end(); + ++it) + { + full_name += llformat("[%s]", it->first.c_str()); + } + + return full_name; +} + + +bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + return self.mCurReadSD == &NO_VALUE_MARKER; +} + + +bool LLParamSDParser::readS32(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((S32*)val_ptr) = self.mCurReadSD->asInteger(); + return true; +} + +bool LLParamSDParser::readU32(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((U32*)val_ptr) = self.mCurReadSD->asInteger(); + return true; +} + +bool LLParamSDParser::readF32(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((F32*)val_ptr) = self.mCurReadSD->asReal(); + return true; +} + +bool LLParamSDParser::readF64(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((F64*)val_ptr) = self.mCurReadSD->asReal(); + return true; +} + +bool LLParamSDParser::readBool(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((bool*)val_ptr) = self.mCurReadSD->asBoolean(); + return true; +} + +bool LLParamSDParser::readString(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((std::string*)val_ptr) = self.mCurReadSD->asString(); + return true; +} + +bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((LLUUID*)val_ptr) = self.mCurReadSD->asUUID(); + return true; +} + +bool LLParamSDParser::readDate(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((LLDate*)val_ptr) = self.mCurReadSD->asDate(); + return true; +} + +bool LLParamSDParser::readURI(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((LLURI*)val_ptr) = self.mCurReadSD->asURI(); + return true; +} + +bool LLParamSDParser::readSD(Parser& parser, void* val_ptr) +{ + LLParamSDParser& self = static_cast(parser); + + *((LLSD*)val_ptr) = *self.mCurReadSD; + return true; +} + +// static +LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range) +{ + LLSD* sd_to_write = &input; + + for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first; + it != name_stack_range.second; + ++it) + { + bool new_traversal = it->second; + + LLSD* child_sd = it->first.empty() ? sd_to_write : &(*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_traversal + && child_sd->isDefined() + && !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; + } + } + it->second = false; + } + + return *sd_to_write; +} + +//static +void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack) +{ + if (sd.isMap()) + { + for (LLSD::map_const_iterator it = sd.beginMap(); + it != sd.endMap(); + ++it) + { + stack.push_back(make_pair(it->first, true)); + readSDValues(cb, it->second, stack); + stack.pop_back(); + } + } + else if (sd.isArray()) + { + for (LLSD::array_const_iterator it = sd.beginArray(); + it != sd.endArray(); + ++it) + { + stack.back().second = true; + readSDValues(cb, *it, stack); + } + } + else if (sd.isUndefined()) + { + if (!cb.empty()) + { + cb(NO_VALUE_MARKER, stack); + } + } + else + { + if (!cb.empty()) + { + cb(sd, stack); + } + } +} + +//static +void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd) +{ + LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t(); + readSDValues(cb, sd, stack); +} +namespace LLInitParam +{ + // LLSD specialization + // block param interface + bool ParamValue, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) + { + LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); + + LLSD::String string; + + if (p.readValue(string)) + { + sd = string; + return true; + } + return false; + } + + //static + void ParamValue, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) + { + p.writeValue(sd.asString(), name_stack); + } + + void ParamValue, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const + { + // read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) + Parser::name_stack_t stack; + LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack); + } +} diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h new file mode 100644 index 0000000000..6ef5debd7b --- /dev/null +++ b/indra/llcommon/llsdparam.h @@ -0,0 +1,126 @@ +/** + * @file llsdparam.h + * @brief parameter block abstraction for creating complex objects and + * parsing construction parameters from xml and LLSD + * + * $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_LLSDPARAM_H +#define LL_LLSDPARAM_H + +#include "llinitparam.h" +#include "boost/function.hpp" + +struct LL_COMMON_API LLParamSDParserUtilities +{ + static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range); + + typedef boost::function read_sd_cb_t; + static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack); + static void readSDValues(read_sd_cb_t cb, const LLSD& sd); +}; + +class LL_COMMON_API LLParamSDParser +: public LLInitParam::Parser +{ +LOG_CLASS(LLParamSDParser); + +typedef LLInitParam::Parser parser_t; + +public: + LLParamSDParser(); + void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false); + void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block); + + /*virtual*/ std::string getCurrentElementName(); + +private: + void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack); + + template + static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack) + { + LLParamSDParser& sdparser = static_cast(parser); + if (!sdparser.mWriteRootSD) return false; + + LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end()); + LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range); + + sd_to_write.assign(*((const T*)val_ptr)); + return true; + } + + static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack); + static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack); + + static bool readFlag(Parser& parser, void* val_ptr); + 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* mWriteRootSD; + LLSD* mCurWriteSD; +}; + + +extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR; +template +class LLSDParamAdapter : public T +{ +public: + LLSDParamAdapter() {} + LLSDParamAdapter(const LLSD& sd) + { + LLFastTimer _(FTM_SD_PARAM_ADAPTOR); + LLParamSDParser parser; + // don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it + bool parse_silently = true; + parser.readSD(sd, *this, parse_silently); + } + + operator LLSD() const + { + LLParamSDParser parser; + LLSD sd; + parser.writeSD(sd, *this); + return sd; + } + + LLSDParamAdapter(const T& val) + : T(val) + { + T::operator=(val); + } +}; + +#endif // LL_LLSDPARAM_H + diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 9226f36e73..20c3456a56 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -81,7 +81,6 @@ set(llui_SOURCE_FILES llscrolllistcolumn.cpp llscrolllistctrl.cpp llscrolllistitem.cpp - llsdparam.cpp llsearcheditor.cpp llslider.cpp llsliderctrl.cpp @@ -190,7 +189,6 @@ set(llui_HEADER_FILES llscrolllistcolumn.h llscrolllistctrl.h llscrolllistitem.h - llsdparam.h llsliderctrl.h llslider.h llspinctrl.h diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp deleted file mode 100644 index 0e29873bb0..0000000000 --- a/indra/llui/llsdparam.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/** - * @file llsdparam.cpp - * @brief parameter block abstraction for creating complex objects and - * parsing construction parameters from xml and LLSD - * - * $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$ - */ - -#include "linden_common.h" - -// 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; -static const LLSD NO_VALUE_MARKER; - -LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion"); - -// -// LLParamSDParser -// -LLParamSDParser::LLParamSDParser() -: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs) -{ - using boost::bind; - - if (sReadFuncs.empty()) - { - registerParserFuncs(readFlag, &LLParamSDParser::writeFlag); - registerParserFuncs(readS32, &LLParamSDParser::writeTypedValue); - registerParserFuncs(readU32, &LLParamSDParser::writeU32Param); - registerParserFuncs(readF32, &LLParamSDParser::writeTypedValue); - registerParserFuncs(readF64, &LLParamSDParser::writeTypedValue); - registerParserFuncs(readBool, &LLParamSDParser::writeTypedValue); - registerParserFuncs(readString, &LLParamSDParser::writeTypedValue); - registerParserFuncs(readUUID, &LLParamSDParser::writeTypedValue); - registerParserFuncs(readDate, &LLParamSDParser::writeTypedValue); - registerParserFuncs(readURI, &LLParamSDParser::writeTypedValue); - registerParserFuncs(readSD, &LLParamSDParser::writeTypedValue); - } -} - -// special case handling of U32 due to ambiguous LLSD::assign overload -bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack) -{ - LLParamSDParser& sdparser = static_cast(parser); - if (!sdparser.mWriteRootSD) return false; - - parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end()); - LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range); - sd_to_write.assign((S32)*((const U32*)val_ptr)); - - return true; -} - -bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack) -{ - LLParamSDParser& sdparser = static_cast(parser); - if (!sdparser.mWriteRootSD) return false; - - parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end()); - LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range); - - return true; -} - -void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack) -{ - mCurReadSD = &sd; - block.submitValue(name_stack, *this); -} - -void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent) -{ - mCurReadSD = NULL; - mNameStack.clear(); - setParseSilently(silent); - - LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack); - //readSDValues(sd, block); -} - -void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block) -{ - mNameStack.clear(); - mWriteRootSD = &sd; - - name_stack_t name_stack; - block.serializeBlock(*this, name_stack); -} - -/*virtual*/ std::string LLParamSDParser::getCurrentElementName() -{ - std::string full_name = "sd"; - for (name_stack_t::iterator it = mNameStack.begin(); - it != mNameStack.end(); - ++it) - { - full_name += llformat("[%s]", it->first.c_str()); - } - - return full_name; -} - - -bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - return self.mCurReadSD == &NO_VALUE_MARKER; -} - - -bool LLParamSDParser::readS32(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((S32*)val_ptr) = self.mCurReadSD->asInteger(); - return true; -} - -bool LLParamSDParser::readU32(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((U32*)val_ptr) = self.mCurReadSD->asInteger(); - return true; -} - -bool LLParamSDParser::readF32(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((F32*)val_ptr) = self.mCurReadSD->asReal(); - return true; -} - -bool LLParamSDParser::readF64(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((F64*)val_ptr) = self.mCurReadSD->asReal(); - return true; -} - -bool LLParamSDParser::readBool(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((bool*)val_ptr) = self.mCurReadSD->asBoolean(); - return true; -} - -bool LLParamSDParser::readString(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((std::string*)val_ptr) = self.mCurReadSD->asString(); - return true; -} - -bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((LLUUID*)val_ptr) = self.mCurReadSD->asUUID(); - return true; -} - -bool LLParamSDParser::readDate(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((LLDate*)val_ptr) = self.mCurReadSD->asDate(); - return true; -} - -bool LLParamSDParser::readURI(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((LLURI*)val_ptr) = self.mCurReadSD->asURI(); - return true; -} - -bool LLParamSDParser::readSD(Parser& parser, void* val_ptr) -{ - LLParamSDParser& self = static_cast(parser); - - *((LLSD*)val_ptr) = *self.mCurReadSD; - return true; -} - -// static -LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range) -{ - LLSD* sd_to_write = &input; - - for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first; - it != name_stack_range.second; - ++it) - { - bool new_traversal = it->second; - - LLSD* child_sd = it->first.empty() ? sd_to_write : &(*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_traversal - && child_sd->isDefined() - && !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; - } - } - it->second = false; - } - - return *sd_to_write; -} - -//static -void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack) -{ - if (sd.isMap()) - { - for (LLSD::map_const_iterator it = sd.beginMap(); - it != sd.endMap(); - ++it) - { - stack.push_back(make_pair(it->first, true)); - readSDValues(cb, it->second, stack); - stack.pop_back(); - } - } - else if (sd.isArray()) - { - for (LLSD::array_const_iterator it = sd.beginArray(); - it != sd.endArray(); - ++it) - { - stack.back().second = true; - readSDValues(cb, *it, stack); - } - } - else if (sd.isUndefined()) - { - if (!cb.empty()) - { - cb(NO_VALUE_MARKER, stack); - } - } - else - { - if (!cb.empty()) - { - cb(sd, stack); - } - } -} - -//static -void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd) -{ - LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t(); - readSDValues(cb, sd, stack); -} -namespace LLInitParam -{ - // LLSD specialization - // block param interface - bool ParamValue, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) - { - LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); - - LLSD::String string; - - if (p.readValue(string)) - { - sd = string; - return true; - } - return false; - } - - //static - void ParamValue, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) - { - p.writeValue(sd.asString(), name_stack); - } - - void ParamValue, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const - { - // read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) - Parser::name_stack_t stack; - LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack); - } -} diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h deleted file mode 100644 index 3dfc6d020e..0000000000 --- a/indra/llui/llsdparam.h +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @file llsdparam.h - * @brief parameter block abstraction for creating complex objects and - * parsing construction parameters from xml and LLSD - * - * $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_LLSDPARAM_H -#define LL_LLSDPARAM_H - -#include "llinitparam.h" -#include "boost/function.hpp" - -struct LLParamSDParserUtilities -{ - static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range); - - typedef boost::function read_sd_cb_t; - static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack); - static void readSDValues(read_sd_cb_t cb, const LLSD& sd); -}; - -class LLParamSDParser -: public LLInitParam::Parser -{ -LOG_CLASS(LLParamSDParser); - -typedef LLInitParam::Parser parser_t; - -public: - LLParamSDParser(); - void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false); - void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block); - - /*virtual*/ std::string getCurrentElementName(); - -private: - void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack); - - template - static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack) - { - LLParamSDParser& sdparser = static_cast(parser); - if (!sdparser.mWriteRootSD) return false; - - LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end()); - LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range); - - sd_to_write.assign(*((const T*)val_ptr)); - return true; - } - - static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack); - static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack); - - static bool readFlag(Parser& parser, void* val_ptr); - 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* mWriteRootSD; - LLSD* mCurWriteSD; -}; - - -extern LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR; -template -class LLSDParamAdapter : public T -{ -public: - LLSDParamAdapter() {} - LLSDParamAdapter(const LLSD& sd) - { - LLFastTimer _(FTM_SD_PARAM_ADAPTOR); - LLParamSDParser parser; - // don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it - bool parse_silently = true; - parser.readSD(sd, *this, parse_silently); - } - - operator LLSD() const - { - LLParamSDParser parser; - LLSD sd; - parser.writeSD(sd, *this); - return sd; - } - - LLSDParamAdapter(const T& val) - : T(val) - { - T::operator=(val); - } -}; - -#endif // LL_LLSDPARAM_H - -- cgit v1.3