diff options
Diffstat (limited to 'indra/llui')
29 files changed, 516 insertions, 312 deletions
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 8b6a73af56..6f9893b07a 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -316,7 +316,7 @@ void LLComboBox::setValue(const LLSD& value) LLScrollListItem* item = mList->getFirstSelected(); if (item) { - setLabel(getSelectedItemLabel()); + updateLabel(); } mLastSelectedIndex = mList->getFirstSelectedIndex(); } @@ -384,6 +384,23 @@ void LLComboBox::setLabel(const LLStringExplicit& name) } } +void LLComboBox::updateLabel() +{ + // Update the combo editor with the selected + // item label. + if (mTextEntry) + { + mTextEntry->setText(getSelectedItemLabel()); + mTextEntry->setTentative(FALSE); + } + + // If combo box doesn't allow text entry update + // the combo button label. + if (!mAllowTextEntry) + { + mButton->setLabel(getSelectedItemLabel()); + } +} BOOL LLComboBox::remove(const std::string& name) { @@ -701,13 +718,13 @@ void LLComboBox::onItemSelected(const LLSD& data) mLastSelectedIndex = getCurrentIndex(); if (mLastSelectedIndex != -1) { - setLabel(getSelectedItemLabel()); + updateLabel(); if (mAllowTextEntry) - { - gFocusMgr.setKeyboardFocus(mTextEntry); - mTextEntry->selectAll(); - } + { + gFocusMgr.setKeyboardFocus(mTextEntry); + mTextEntry->selectAll(); + } } // hiding the list reasserts the old value stored in the text editor/dropdown button hideList(); diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 74d64269bd..e9ef9d07e4 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -148,6 +148,9 @@ public: // This is probably a UI abuse. void setLabel(const LLStringExplicit& name); + // Updates the combobox label to match the selected list item. + void updateLabel(); + BOOL remove(const std::string& name); // remove item "name", return TRUE if found and removed BOOL setCurrentByIndex( S32 index ); diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index f6f5a0beb3..b1c27126d9 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -160,8 +160,10 @@ bool LLDockControl::isDockVisible() case TOP: { // check is dock inside parent rect + // assume that parent for all dockable flaoters + // is the root view LLRect dockParentRect = - mDockWidget->getParent()->calcScreenRect(); + mDockWidget->getRootView()->calcScreenRect(); if (dockRect.mRight <= dockParentRect.mLeft || dockRect.mLeft >= dockParentRect.mRight) { @@ -297,7 +299,7 @@ void LLDockControl::moveDockable() break; } - S32 max_available_height = rootRect.getHeight() - mDockTongueY - mDockTongue->getHeight(); + S32 max_available_height = rootRect.getHeight() - (rootRect.mBottom - mDockTongueY) - mDockTongue->getHeight(); // A floater should be shrunk so it doesn't cover a part of its docking tongue and // there is a space between a dockable floater and a control to which it is docked. diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index c425782715..d19e33ea55 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2590,9 +2590,13 @@ void LLFloaterView::draw() LLRect LLFloaterView::getSnapRect() const { - LLRect snap_rect = getRect(); - snap_rect.mBottom += mSnapOffsetBottom; - snap_rect.mRight -= mSnapOffsetRight; + LLRect snap_rect = getLocalRect(); + + LLView* snap_view = mSnapView.get(); + if (snap_view) + { + snap_view->localRectToOtherView(snap_view->getLocalRect(), &snap_rect, this); + } return snap_rect; } @@ -2865,7 +2869,7 @@ void LLFloater::initFromParams(const LLFloater::Params& p) // close callback if (p.close_callback.isProvided()) { - mCloseSignal.connect(initCommitCallback(p.close_callback)); + setCloseCallback(initCommitCallback(p.close_callback)); } } @@ -2875,6 +2879,11 @@ boost::signals2::connection LLFloater::setMinimizeCallback( const commit_signal_ return mMinimizeSignal->connect(cb); } +boost::signals2::connection LLFloater::setCloseCallback( const commit_signal_t::slot_type& cb ) +{ + return mCloseSignal.connect(cb); +} + LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build"); bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index bb96272d02..5b7b020881 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -144,6 +144,7 @@ public: bool buildFromFile(const std::string &filename, LLXMLNodePtr output_node = NULL); boost::signals2::connection setMinimizeCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setCloseCallback( const commit_signal_t::slot_type& cb ); void initFromParams(const LLFloater::Params& p); bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL); @@ -495,10 +496,10 @@ public: // value is not defined. S32 getZOrder(LLFloater* child); - void setSnapOffsetBottom(S32 offset) { mSnapOffsetBottom = offset; } - void setSnapOffsetRight(S32 offset) { mSnapOffsetRight = offset; } + void setFloaterSnapView(LLHandle<LLView> snap_view) {mSnapView = snap_view; } private: + LLHandle<LLView> mSnapView; BOOL mFocusCycleMode; S32 mSnapOffsetBottom; S32 mSnapOffsetRight; diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp index 821d4543ae..7525b8cab3 100644 --- a/indra/llui/llfloaterreglistener.cpp +++ b/indra/llui/llfloaterreglistener.cpp @@ -60,6 +60,11 @@ LLFloaterRegListener::LLFloaterRegListener(): "Ask to toggle the state of the floater specified in [\"name\"]", &LLFloaterRegListener::toggleInstance, requiredName); + add("instanceVisible", + "Return on [\"reply\"] an event whose [\"visible\"] indicates the visibility " + "of the floater specified in [\"name\"]", + &LLFloaterRegListener::instanceVisible, + requiredName); LLSD requiredNameButton; requiredNameButton["name"] = LLSD(); requiredNameButton["button"] = LLSD(); @@ -71,9 +76,7 @@ LLFloaterRegListener::LLFloaterRegListener(): void LLFloaterRegListener::getBuildMap(const LLSD& event) const { - // Honor the "reqid" convention by echoing event["reqid"] in our reply packet. - LLReqID reqID(event); - LLSD reply(reqID.makeResponse()); + LLSD reply; // Build an LLSD map that mirrors sBuildMap. Since we have no good way to // represent a C++ callable in LLSD, the only part of BuildData we can // store is the filename. For each LLSD map entry, it would be more @@ -86,7 +89,7 @@ void LLFloaterRegListener::getBuildMap(const LLSD& event) const reply[mi->first] = mi->second.mFile; } // Send the reply to the LLEventPump named in event["reply"]. - LLEventPumps::instance().obtain(event["reply"]).post(reply); + sendReply(reply, event); } void LLFloaterRegListener::showInstance(const LLSD& event) const @@ -104,6 +107,12 @@ void LLFloaterRegListener::toggleInstance(const LLSD& event) const LLFloaterReg::toggleInstance(event["name"], event["key"]); } +void LLFloaterRegListener::instanceVisible(const LLSD& event) const +{ + sendReply(LLSDMap("visible", LLFloaterReg::instanceVisible(event["name"], event["key"])), + event); +} + void LLFloaterRegListener::clickButton(const LLSD& event) const { // If the caller requests a reply, build the reply. diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h index 586656667c..24311a2dfa 100644 --- a/indra/llui/llfloaterreglistener.h +++ b/indra/llui/llfloaterreglistener.h @@ -47,6 +47,7 @@ private: void showInstance(const LLSD& event) const; void hideInstance(const LLSD& event) const; void toggleInstance(const LLSD& event) const; + void instanceVisible(const LLSD& event) const; void clickButton(const LLSD& event) const; }; diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index e9bdab2d47..669e126266 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -69,6 +69,7 @@ public: void setColor(const LLColor4& color) { mColor = color; } void setImage(LLPointer<LLUIImage> image) { mImagep = image; } + const LLPointer<LLUIImage> getImage() { return mImagep; } private: void setIconImageDrawSize() ; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 19ac4c58a8..9b6830a816 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -563,7 +563,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize) } // update resize bars with new limits - LLResizeBar* last_resize_bar = NULL; + LLLayoutPanel* last_resizeable_panel = NULL; for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) { LLPanel* panelp = (*panel_it); @@ -585,17 +585,17 @@ void LLLayoutStack::updateLayout(BOOL force_resize) BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize; (*panel_it)->mResizeBar->setVisible(resize_bar_enabled); - if (resize_bar_enabled) + if ((*panel_it)->mUserResize || (*panel_it)->mAutoResize) { - last_resize_bar = (*panel_it)->mResizeBar; + last_resizeable_panel = (*panel_it); } } // hide last resize bar as there is nothing past it // resize bars need to be in between two resizable panels - if (last_resize_bar) + if (last_resizeable_panel) { - last_resize_bar->setVisible(FALSE); + last_resizeable_panel->mResizeBar->setVisible(FALSE); } // not enough room to fit existing contents diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 7e348656a9..d99ee5a545 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -2290,3 +2290,8 @@ void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu) else mContextMenuHandle.markDead(); } + +void LLLineEditor::setFont(const LLFontGL* font) +{ + mGLFont = font; +} diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 723423a5b9..7b5fa218f2 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -201,6 +201,7 @@ public: const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); } const LLFontGL* getFont() const { return mGLFont; } + void setFont(const LLFontGL* font); void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; } void setIgnoreTab(BOOL b) { mIgnoreTab = b; } diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index 7b29d92ea0..c4eec1835c 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -39,56 +39,24 @@ //static LLDefaultChildRegistry::Register<LLLoadingIndicator> r("loading_indicator"); /////////////////////////////////////////////////////////////////////////////// -// LLLoadingIndicator::Data class +// LLLoadingIndicator class /////////////////////////////////////////////////////////////////////////////// -/** - * Pre-loaded images shared by all instances of the widget - */ -class LLLoadingIndicator::Data: public LLSingleton<LLLoadingIndicator::Data> +LLLoadingIndicator::LLLoadingIndicator(const Params& p) +: LLUICtrl(p), + mImagesPerSec(p.images_per_sec > 0 ? p.images_per_sec : 1.0f), + mCurImageIdx(0) { -public: - /*virtual*/ void initSingleton(); // from LLSingleton - - LLPointer<LLUIImage> getNextImage(S8& idx) const; - U8 getImagesCount() const { return NIMAGES; } -private: - - static const U8 NIMAGES = 12; - LLPointer<LLUIImage> mImages[NIMAGES]; -}; +} -// virtual -// Called right after the instance gets constructed. -void LLLoadingIndicator::Data::initSingleton() +void LLLoadingIndicator::initFromParams(const Params& p) { - // Load images. - for (U8 i = 0; i < NIMAGES; ++i) + for (LLInitParam::ParamIterator<LLUIImage*>::const_iterator it = p.images().image.begin(), end_it = p.images().image.end(); + it != end_it; + ++it) { - std::string img_name = llformat("Progress_%d", i+1); - mImages[i] = LLUI::getUIImage(img_name, 0); - llassert(mImages[i]); + mImages.push_back(it->getValue()); } -} - -LLPointer<LLUIImage> LLLoadingIndicator::Data::getNextImage(S8& idx) const -{ - // Calculate next index, performing array bounds checking. - idx = (idx >= NIMAGES || idx < 0) ? 0 : (idx + 1) % NIMAGES; - return mImages[idx]; -} - -/////////////////////////////////////////////////////////////////////////////// -// LLLoadingIndicator class -/////////////////////////////////////////////////////////////////////////////// - -LLLoadingIndicator::LLLoadingIndicator(const Params& p) -: LLUICtrl(p) - , mRotationsPerSec(p.rotations_per_sec > 0 ? p.rotations_per_sec : 1.0f) - , mCurImageIdx(-1) -{ - // Select initial image. - mCurImagep = Data::instance().getNextImage(mCurImageIdx); // Start timer for switching images. start(); @@ -100,16 +68,21 @@ void LLLoadingIndicator::draw() if (mImageSwitchTimer.getStarted() && mImageSwitchTimer.hasExpired()) { // Switch to the next image. - mCurImagep = Data::instance().getNextImage(mCurImageIdx); + if (!mImages.empty()) + { + mCurImageIdx = (mCurImageIdx + 1) % mImages.size(); + } // Restart timer. start(); } + LLUIImagePtr cur_image = mImages.empty() ? LLUIImagePtr(NULL) : mImages[mCurImageIdx]; + // Draw current image. - if( mCurImagep.notNull() ) + if( cur_image.notNull() ) { - mCurImagep->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha); + cur_image->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha); } LLUICtrl::draw(); @@ -123,6 +96,6 @@ void LLLoadingIndicator::stop() void LLLoadingIndicator::start() { mImageSwitchTimer.start(); - F32 period = 1.0f / (Data::instance().getImagesCount() * mRotationsPerSec); + F32 period = 1.0f / (mImages.size() * mImagesPerSec); mImageSwitchTimer.setTimerExpirySec(period); } diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index 4e4a224ef6..c0cb1cc74a 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -36,8 +36,8 @@ /** * Perpetual loading indicator (a la MacOSX or YouTube) * - * Number of rotations per second can be overriden - * with the "roations_per_sec" parameter. + * Number of rotations per second can be overridden + * with the "images_per_sec" parameter. * * Can start/stop spinning. * @@ -49,11 +49,24 @@ class LLLoadingIndicator { LOG_CLASS(LLLoadingIndicator); public: + + struct Images : public LLInitParam::Block<Images> + { + Multiple<LLUIImage*> image; + + Images() + : image("image") + {} + }; + struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { - Optional<F32> rotations_per_sec; + Optional<F32> images_per_sec; + Batch<Images> images; + Params() - : rotations_per_sec("rotations_per_sec", 1.0f) + : images_per_sec("images_per_sec", 1.0f), + images("images") {} }; @@ -74,14 +87,15 @@ public: private: LLLoadingIndicator(const Params&); - friend class LLUICtrlFactory; + void initFromParams(const Params&); - class Data; + friend class LLUICtrlFactory; - F32 mRotationsPerSec; + F32 mImagesPerSec; S8 mCurImageIdx; - LLPointer<LLUIImage> mCurImagep; LLFrameTimer mImageSwitchTimer; + + std::vector<LLUIImagePtr> mImages; }; #endif // LL_LLLOADINGINDICATOR_H diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 32d7be377a..8de9c769e2 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1936,9 +1936,15 @@ bool LLMenuGL::scrollItems(EScrollingDirection direction) { item_list_t::reverse_iterator first_visible_item_iter = mItems.rend(); + // Need to scroll through number of actual existing items in menu. + // Otherwise viewer will hang for a time needed to scroll U32_MAX + // times in std::advance(). STORM-659. + size_t nitems = mItems.size(); + U32 scrollable_items = nitems < mMaxScrollableItems ? nitems : mMaxScrollableItems; + // Advance by mMaxScrollableItems back from the end of the list // to make the last item visible. - std::advance(first_visible_item_iter, mMaxScrollableItems); + std::advance(first_visible_item_iter, scrollable_items); mFirstVisibleItem = *first_visible_item_iter; break; } @@ -3099,9 +3105,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2); menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect, FALSE ); menu->getParent()->sendChildToFront(menu); - - - } ///============================================================================ diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index cc9edfcdea..bdac125eb0 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1195,16 +1195,18 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif) bool LLNotifications::uniqueHandler(const LLSD& payload) { + std::string cmd = payload["sigtype"]; + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); if (pNotif && pNotif->hasUniquenessConstraints()) { - if (payload["sigtype"].asString() == "add") + if (cmd == "add") { // not a duplicate according to uniqueness criteria, so we keep it // and store it for future uniqueness checks mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif)); } - else if (payload["sigtype"].asString() == "delete") + else if (cmd == "delete") { mUniqueNotifications.erase(pNotif->getName()); } @@ -1217,12 +1219,16 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload) { LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); - if (!pNotif || !pNotif->hasUniquenessConstraints()) + std::string cmd = payload["sigtype"]; + + if (!pNotif || cmd != "add") { return false; } - // checks against existing unique notifications + // Update the existing unique notification with the data from this particular instance... + // This guarantees that duplicate notifications will be collapsed to the one + // most recently triggered for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); existing_it != mUniqueNotifications.end(); ++existing_it) @@ -1235,7 +1241,7 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload) // of this unique notification and update it existing_notification->updateFrom(pNotif); // then delete the new one - pNotif->cancel(); + cancel(pNotif); } } @@ -1300,26 +1306,14 @@ void LLNotifications::createDefaultChannels() // usage LLStopWhenHandled combiner in LLStandardSignal LLNotifications::instance().getChannel("Unique")-> connectAtFrontChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1)); -// failedUniquenessTest slot isn't necessary -// LLNotifications::instance().getChannel("Unique")-> -// connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1)); + LLNotifications::instance().getChannel("Unique")-> + connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1)); LLNotifications::instance().getChannel("Ignore")-> connectFailedFilter(&handleIgnoredNotification); LLNotifications::instance().getChannel("VisibilityRules")-> connectFailedFilter(&visibilityRuleMached); } -bool LLNotifications::addTemplate(const std::string &name, - LLNotificationTemplatePtr theTemplate) -{ - if (mTemplates.count(name)) - { - llwarns << "LLNotifications -- attempted to add template '" << name << "' twice." << llendl; - return false; - } - mTemplates[name] = theTemplate; - return true; -} LLNotificationTemplatePtr LLNotifications::getTemplate(const std::string& name) { @@ -1416,27 +1410,45 @@ void replaceFormText(LLNotificationForm::Params& form, const std::string& patter } } +void addPathIfExists(const std::string& new_path, std::vector<std::string>& paths) +{ + if (gDirUtilp->fileExists(new_path)) + { + paths.push_back(new_path); + } +} + bool LLNotifications::loadTemplates() { - const std::string xml_filename = "notifications.xml"; - std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), xml_filename); + std::vector<std::string> search_paths; + + std::string skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml"; + std::string localized_skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml"; + + addPathIfExists(gDirUtilp->getDefaultSkinDir() + skin_relative_path, search_paths); + addPathIfExists(gDirUtilp->getDefaultSkinDir() + localized_skin_relative_path, search_paths); + addPathIfExists(gDirUtilp->getSkinDir() + skin_relative_path, search_paths); + addPathIfExists(gDirUtilp->getSkinDir() + localized_skin_relative_path, search_paths); + addPathIfExists(gDirUtilp->getUserSkinDir() + skin_relative_path, search_paths); + addPathIfExists(gDirUtilp->getUserSkinDir() + localized_skin_relative_path, search_paths); + std::string base_filename = search_paths.front(); LLXMLNodePtr root; - BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); if (!success || root.isNull() || !root->hasName( "notifications" )) { - llerrs << "Problem reading UI Notifications file: " << full_filename << llendl; + llerrs << "Problem reading UI Notifications file: " << base_filename << llendl; return false; } LLNotificationTemplate::Notifications params; LLXUIParser parser; - parser.readXUI(root, params, full_filename); + parser.readXUI(root, params, base_filename); if(!params.validateBlock()) { - llerrs << "Problem reading UI Notifications file: " << full_filename << llendl; + llerrs << "Problem reading UI Notifications file: " << base_filename << llendl; return false; } @@ -1483,7 +1495,7 @@ bool LLNotifications::loadTemplates() replaceFormText(it->form_ref.form, "$ignoretext", it->form_ref.form_template.ignore_text); } } - addTemplate(it->name, LLNotificationTemplatePtr(new LLNotificationTemplate(*it))); + mTemplates[it->name] = LLNotificationTemplatePtr(new LLNotificationTemplate(*it)); } return true; @@ -1578,7 +1590,7 @@ void LLNotifications::add(const LLNotificationPtr pNotif) void LLNotifications::cancel(LLNotificationPtr pNotif) { - if (pNotif == NULL) return; + if (pNotif == NULL || pNotif->isCancelled()) return; LLNotificationSet::iterator it=mItems.find(pNotif); if (it == mItems.end()) @@ -1680,7 +1692,6 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n) for(it = mVisibilityRules.begin(); it != mVisibilityRules.end(); it++) { // An empty type/tag/name string will match any notification, so only do the comparison when the string is non-empty in the rule. - lldebugs << "notification \"" << n->getName() << "\" " << "testing against " << ((*it)->mVisible?"show":"hide") << " rule, " @@ -1728,7 +1739,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n) // Response property is empty. Cancel this notification. lldebugs << "cancelling notification " << n->getName() << llendl; - n->cancel(); + cancel(n); } else { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 34d3537781..0c4d4fc897 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -863,10 +863,11 @@ class LLNotifications : friend class LLSingleton<LLNotifications>; public: - // load notification descriptions from file; - // OK to call more than once because it will reload - bool loadTemplates(); - + // load all notification descriptions from file + // calling more than once will overwrite existing templates + // but never delete a template + bool loadTemplates(); + // load visibility rules from file; // OK to call more than once because it will reload bool loadVisibilityRules(); @@ -950,8 +951,6 @@ private: LLNotificationChannelPtr pHistoryChannel; LLNotificationChannelPtr pExpirationChannel; - // put your template in - bool addTemplate(const std::string& name, LLNotificationTemplatePtr theTemplate); TemplateMap mTemplates; VisibilityRuleList mVisibilityRules; diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index 6e9586369f..3a12debf7e 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -346,7 +346,7 @@ void LLRadioGroup::setValue( const LLSD& value ) } else { - llwarns << "LLRadioGroup::setValue: value not found: " << value.asString() << llendl; + setSelectedIndex(-1, TRUE); } } } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 49537ef78f..fd7bb699f8 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -157,6 +157,7 @@ LLTextBase::Params::Params() read_only("read_only", false), v_pad("v_pad", 0), h_pad("h_pad", 0), + clip("clip", true), clip_partial("clip_partial", true), line_spacing("line_spacing"), max_text_length("max_length", 255), @@ -199,6 +200,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mVAlign(p.font_valign), mLineSpacingMult(p.line_spacing.multiple), mLineSpacingPixels(p.line_spacing.pixels), + mClip(p.clip), mClipPartial(p.clip_partial && !p.allow_scroll), mTrackEnd( p.track_end ), mScrollIndex(-1), @@ -334,7 +336,7 @@ void LLTextBase::drawSelectionBackground() // binary search for line that starts before top of visible buffer line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom()); - line_list_t::const_iterator end_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top()); + line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top()); bool done = false; @@ -512,7 +514,6 @@ void LLTextBase::drawText() selection_right = llmax( mSelectionStart, mSelectionEnd ); } - LLRect scrolled_view_rect = getVisibleDocumentRect(); std::pair<S32, S32> line_range = getVisibleLines(mClipPartial); S32 first_line = line_range.first; S32 last_line = line_range.second; @@ -545,10 +546,10 @@ void LLTextBase::drawText() line_end = next_start; } - LLRect text_rect(line.mRect.mLeft + mVisibleTextRect.mLeft - scrolled_view_rect.mLeft, - line.mRect.mTop - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom, - llmin(mDocumentView->getRect().getWidth(), line.mRect.mRight) - scrolled_view_rect.mLeft, - line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom); + LLRect text_rect(line.mRect); + text_rect.mRight = llmin(mDocumentView->getRect().getWidth(), text_rect.mRight); // clamp right edge to document extents + text_rect.translate(mVisibleTextRect.mLeft, mVisibleTextRect.mBottom); // translate into display region of text widget + text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position // draw a single line of text S32 seg_start = line_start; @@ -993,14 +994,28 @@ void LLTextBase::draw() updateScrollFromCursor(); } - LLRect doc_rect; + LLRect text_rect; if (mScroller) { - mScroller->localRectToOtherView(mScroller->getContentWindowRect(), &doc_rect, this); + mScroller->localRectToOtherView(mScroller->getContentWindowRect(), &text_rect, this); } else { - doc_rect = getLocalRect(); + LLRect visible_lines_rect; + std::pair<S32, S32> line_range = getVisibleLines(mClipPartial); + for (S32 i = line_range.first; i < line_range.second; i++) + { + if (visible_lines_rect.isEmpty()) + { + visible_lines_rect = mLineInfoList[i].mRect; + } + else + { + visible_lines_rect.unionWith(mLineInfoList[i].mRect); + } + } + text_rect = visible_lines_rect; + text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); } if (mBGVisible) @@ -1010,28 +1025,37 @@ void LLTextBase::draw() LLRect bg_rect = mVisibleTextRect; if (mScroller) { - bg_rect.intersectWith(doc_rect); + bg_rect.intersectWith(text_rect); } LLColor4 bg_color = mReadOnly ? mReadOnlyBgColor.get() : hasFocus() ? mFocusBgColor.get() : mWriteableBgColor.get(); - gl_rect_2d(doc_rect, bg_color % alpha, TRUE); + gl_rect_2d(text_rect, bg_color % alpha, TRUE); } - // draw document view - LLUICtrl::draw(); - - { - // only clip if we support scrolling... - // since convention is that text boxes never vertically truncate their contents - // regardless of rect bounds - LLLocalClipRect clip(doc_rect, mScroller != NULL); + bool should_clip = mClip || mScroller != NULL; + { LLLocalClipRect clip(text_rect, should_clip); + + // draw document view + if (mScroller) + { + drawChild(mScroller); + } + else + { + drawChild(mDocumentView); + } + drawSelectionBackground(); drawText(); drawCursor(); } + + mDocumentView->setVisible(FALSE); + LLUICtrl::draw(); + mDocumentView->setVisible(TRUE); } @@ -1415,7 +1439,7 @@ S32 LLTextBase::getFirstVisibleLine() const return iter - mLineInfoList.begin(); } -std::pair<S32, S32> LLTextBase::getVisibleLines(bool fully_visible) +std::pair<S32, S32> LLTextBase::getVisibleLines(bool require_fully_visible) { LLRect visible_region = getVisibleDocumentRect(); line_list_t::const_iterator first_iter; @@ -1424,14 +1448,14 @@ std::pair<S32, S32> LLTextBase::getVisibleLines(bool fully_visible) // make sure we have an up-to-date mLineInfoList reflow(); - if (fully_visible) + if (require_fully_visible) { first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_top()); - last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_bottom()); + last_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_bottom()); } else { - first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom()); + first_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom()); last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_top()); } return std::pair<S32, S32>(first_iter - mLineInfoList.begin(), last_iter - mLineInfoList.begin()); @@ -1998,11 +2022,10 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, pos = segment_line_start + offset; break; } - else if (hit_past_end_of_line && segmentp->getEnd() > line_iter->mDocIndexEnd - 1) + else if (hit_past_end_of_line && segmentp->getEnd() >= line_iter->mDocIndexEnd) { // segment wraps to next line, so just set doc pos to the end of the line - // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd) - pos = llmin(getLength(), line_iter->mDocIndexEnd); + pos = llclamp(line_iter->mDocIndexEnd - 1, 0, getLength()); break; } start_x += text_width; @@ -2405,14 +2428,41 @@ LLRect LLTextBase::getVisibleDocumentRect() const { return mScroller->getVisibleContentRect(); } - else + else if (mClip) { - // entire document rect is visible when not scrolling + LLRect visible_text_rect = getVisibleTextRect(); + LLRect doc_rect = mDocumentView->getRect(); + visible_text_rect.translate(-doc_rect.mLeft, -doc_rect.mBottom); + + // reject partially visible lines + LLRect visible_lines_rect; + for (line_list_t::const_iterator it = mLineInfoList.begin(), end_it = mLineInfoList.end(); + it != end_it; + ++it) + { + bool line_visible = mClipPartial ? visible_text_rect.contains(it->mRect) : visible_text_rect.overlaps(it->mRect); + if (line_visible) + { + if (visible_lines_rect.isEmpty()) + { + visible_lines_rect = it->mRect; + } + else + { + visible_lines_rect.unionWith(it->mRect); + } + } + } + return visible_lines_rect; + } + else + { // entire document rect is visible // but offset according to height of widget + LLRect doc_rect = mDocumentView->getLocalRect(); doc_rect.mLeft -= mDocumentView->getRect().mLeft; // adjust for height of text above widget baseline - doc_rect.mBottom = doc_rect.getHeight() - mVisibleTextRect.getHeight(); + doc_rect.mBottom = llmin(0, doc_rect.getHeight() - mVisibleTextRect.getHeight()); return doc_rect; } } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index aafcf8ceb0..7d545a1ba6 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -265,6 +265,7 @@ public: use_ellipses, parse_urls, parse_highlights, + clip, clip_partial; Optional<S32> v_pad, @@ -338,7 +339,7 @@ public: void addDocumentChild(LLView* view); void removeDocumentChild(LLView* view); const LLView* getDocumentView() const { return mDocumentView; } - LLRect getVisibleTextRect() { return mVisibleTextRect; } + LLRect getVisibleTextRect() const { return mVisibleTextRect; } LLRect getTextBoundingRect(); LLRect getVisibleDocumentRect() const; @@ -552,6 +553,7 @@ protected: bool mTrackEnd; // if true, keeps scroll position at end of document during resize bool mReadOnly; bool mBGVisible; // render background? + bool mClip; // clip text to widget rect bool mClipPartial; // false if we show lines that are partially inside bounding rect bool mPlainText; // didn't use Image or Icon segments S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index c300fe55d9..8020ca802b 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -61,6 +61,8 @@ // for XUIParse #include "llquaternion.h" #include <boost/tokenizer.hpp> +#include <boost/algorithm/string/find_iterator.hpp> +#include <boost/algorithm/string/finder.hpp> // // Globals @@ -1624,8 +1626,8 @@ void LLUI::cleanupClass() { if(sImageProvider) { - sImageProvider->cleanUp(); - } + sImageProvider->cleanUp(); +} } void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups) @@ -2020,37 +2022,84 @@ void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y) view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE ); } +LLView* LLUI::resolvePath(LLView* context, const std::string& path) +{ + // Nothing about resolvePath() should require non-const LLView*. If caller + // wants non-const, call the const flavor and then cast away const-ness. + return const_cast<LLView*>(resolvePath(const_cast<const LLView*>(context), path)); +} + +const LLView* LLUI::resolvePath(const LLView* context, const std::string& path) +{ + // Create an iterator over slash-separated parts of 'path'. Dereferencing + // this iterator returns an iterator_range over the substring. Unlike + // LLStringUtil::getTokens(), this split_iterator doesn't combine adjacent + // delimiters: leading/trailing slash produces an empty substring, double + // slash produces an empty substring. That's what we need. + boost::split_iterator<std::string::const_iterator> ti(path, boost::first_finder("/")), tend; + + if (ti == tend) + { + // 'path' is completely empty, no navigation + return context; + } + + // leading / means "start at root" + if (ti->empty()) + { + context = getRootView(); + ++ti; + } + + bool recurse = false; + for (; ti != tend && context; ++ti) + { + if (ti->empty()) + { + recurse = true; + } + else + { + std::string part(ti->begin(), ti->end()); + context = context->findChildView(part, recurse); + recurse = false; + } + } + + return context; +} + // LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp namespace LLInitParam { - TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count), + ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + : super_t(color), red("red"), green("green"), blue("blue"), alpha("alpha"), control("") { - setBlockFromValue(); + updateBlockFromValue(); } - void TypedParam<LLUIColor>::setValueFromBlock() const + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() { if (control.isProvided()) { - mData.mValue = LLUIColorTable::instance().getColor(control); + updateValue(LLUIColorTable::instance().getColor(control)); } else { - mData.mValue = LLColor4(red, green, blue, alpha); + updateValue(LLColor4(red, green, blue, alpha)); } } - void TypedParam<LLUIColor>::setBlockFromValue() + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue() { - LLColor4 color = mData.mValue.get(); + LLColor4 color = getValue(); red.set(color.mV[VRED], false); green.set(color.mV[VGREEN], false); blue.set(color.mV[VBLUE], false); @@ -2058,38 +2107,32 @@ namespace LLInitParam control.set("", false); } - void TypeValues<LLUIColor>::declareValues() - { - declare("white", LLColor4::white); - declare("black", LLColor4::black); - declare("red", LLColor4::red); - declare("green", LLColor4::green); - declare("blue", LLColor4::blue); - } - bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) { return !(a->getFontDesc() < b->getFontDesc()) && !(b->getFontDesc() < a->getFontDesc()); } - TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, _name, value, func, min_count, max_count), + ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + : super_t(fontp), name("name"), size("size"), style("style") { - setBlockFromValue(); + if (!fontp) + { + updateValue(LLFontGL::getFontDefault()); + } addSynonym(name, ""); - setBlockFromValue(); + updateBlockFromValue(); } - void TypedParam<const LLFontGL*>::setValueFromBlock() const + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() { const LLFontGL* res_fontp = LLFontGL::getFontByName(name); if (res_fontp) { - mData.mValue = res_fontp; + updateValue(res_fontp); return; } @@ -2099,22 +2142,26 @@ namespace LLInitParam const LLFontGL* fontp = LLFontGL::getFont(desc); if (fontp) { - mData.mValue = fontp; - } + updateValue(fontp); + } + else + { + updateValue(LLFontGL::getFontDefault()); + } } - void TypedParam<const LLFontGL*>::setBlockFromValue() + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue() { - if (mData.mValue) + if (getValue()) { - name.set(LLFontGL::nameFromFont(mData.mValue), false); - size.set(LLFontGL::sizeFromFont(mData.mValue), false); - style.set(LLFontGL::getStringFromStyle(mData.mValue->getFontDesc().getStyle()), false); + name.set(LLFontGL::nameFromFont(getValue()), false); + size.set(LLFontGL::sizeFromFont(getValue()), false); + style.set(LLFontGL::getStringFromStyle(getValue()->getFontDesc().getStyle()), false); } } - TypedParam<LLRect>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count), + ParamValue<LLRect, TypeValues<LLRect> >::ParamValue(const LLRect& rect) + : super_t(rect), left("left"), top("top"), right("right"), @@ -2122,10 +2169,10 @@ namespace LLInitParam width("width"), height("height") { - setBlockFromValue(); + updateBlockFromValue(); } - void TypedParam<LLRect>::setValueFromBlock() const + void ParamValue<LLRect, TypeValues<LLRect> >::updateValueFromBlock() { LLRect rect; @@ -2186,40 +2233,41 @@ namespace LLInitParam rect.mBottom = bottom; rect.mTop = top; } - mData.mValue = rect; + updateValue(rect); } - void TypedParam<LLRect>::setBlockFromValue() + void ParamValue<LLRect, TypeValues<LLRect> >::updateBlockFromValue() { // because of the ambiguity in specifying a rect by position and/or dimensions // we clear the "provided" flag so that values from xui/etc have priority // over those calculated from the rect object - left.set(mData.mValue.mLeft, false); - right.set(mData.mValue.mRight, false); - bottom.set(mData.mValue.mBottom, false); - top.set(mData.mValue.mTop, false); - width.set(mData.mValue.getWidth(), false); - height.set(mData.mValue.getHeight(), false); + LLRect& value = getValue(); + left.set(value.mLeft, false); + right.set(value.mRight, false); + bottom.set(value.mBottom, false); + top.set(value.mTop, false); + width.set(value.getWidth(), false); + height.set(value.getHeight(), false); } - TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count), + ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::ParamValue(const LLCoordGL& coord) + : super_t(coord), x("x"), y("y") { - setBlockFromValue(); + updateBlockFromValue(); } - void TypedParam<LLCoordGL>::setValueFromBlock() const + void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateValueFromBlock() { - mData.mValue.set(x, y); + updateValue(LLCoordGL(x, y)); } - void TypedParam<LLCoordGL>::setBlockFromValue() + void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateBlockFromValue() { - x.set(mData.mValue.mX, false); - y.set(mData.mValue.mY, false); + x.set(getValue().mX, false); + y.set(getValue().mY, false); } diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 62d10df8b2..6a43477693 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -185,6 +185,33 @@ public: //helper functions (should probably move free standing rendering helper functions here) static LLView* getRootView() { return sRootView; } static void setRootView(LLView* view) { sRootView = view; } + /** + * Walk the LLView tree to resolve a path + * Paths can be discovered using Develop > XUI > Show XUI Paths + * + * A leading "/" indicates the root of the tree is the starting + * position of the search, (otherwise the context node is used) + * + * Adjacent "//" mean that the next level of the search is done + * recursively ("descendant" rather than "child"). + * + * Return values: If no match is found, NULL is returned, + * otherwise the matching LLView* is returned. + * + * Examples: + * + * "/" -> return the root view + * "/foo" -> find "foo" as a direct child of the root + * "foo" -> find "foo" as a direct child of the context node + * "//foo" -> find the first "foo" child anywhere in the tree + * "/foo/bar" -> find "foo" as direct child of the root, and + * "bar" as a direct child of "foo" + * "//foo//bar/baz" -> find the first "foo" anywhere in the + * tree, the first "bar" anywhere under it, and "baz" + * as a direct child of that + */ + static const LLView* resolvePath(const LLView* context, const std::string& path); + static LLView* resolvePath(LLView* context, const std::string& path); static std::string locateSkin(const std::string& filename); static void setMousePositionScreen(S32 x, S32 y); static void getMousePositionScreen(S32 *x, S32 *y); @@ -371,10 +398,10 @@ public: namespace LLInitParam { template<> - class TypedParam<LLRect> - : public BlockValue<LLRect> + class ParamValue<LLRect, TypeValues<LLRect> > + : public CustomParamValue<LLRect> { - typedef BlockValue<LLRect> super_t; + typedef CustomParamValue<LLRect> super_t; public: Optional<S32> left, top, @@ -383,62 +410,43 @@ namespace LLInitParam width, height; - TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); + ParamValue(const LLRect& value); - void setValueFromBlock() const; - void setBlockFromValue(); + void updateValueFromBlock(); + void updateBlockFromValue(); }; template<> - struct TypeValues<LLUIColor> : public TypeValuesHelper<LLUIColor> + class ParamValue<LLUIColor, TypeValues<LLUIColor> > + : public CustomParamValue<LLUIColor> { - static void declareValues(); - }; + typedef CustomParamValue<LLUIColor> super_t; - template<> - class TypedParam<LLUIColor> - : public BlockValue<LLUIColor> - { - typedef BlockValue<LLUIColor> super_t; public: - Optional<F32> red, - green, - blue, - alpha; - Optional<std::string> control; - - TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); - void setValueFromBlock() const; - void setBlockFromValue(); + Optional<F32> red, + green, + blue, + alpha; + Optional<std::string> control; + + ParamValue(const LLUIColor& color); + void updateValueFromBlock(); + void updateBlockFromValue(); }; - // provide a better default for Optional<const LLFontGL*> than NULL - template <> - struct DefaultInitializer<const LLFontGL*> - { - // return reference to a single default instance of T - // built-in types will be initialized to zero, default constructor otherwise - static const LLFontGL* get() - { - static const LLFontGL* sDefaultFont = LLFontGL::getFontDefault(); - return sDefaultFont; - } - }; - - template<> - class TypedParam<const LLFontGL*> - : public BlockValue<const LLFontGL*> + class ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> > + : public CustomParamValue<const LLFontGL* > { - typedef BlockValue<const LLFontGL*> super_t; + typedef CustomParamValue<const LLFontGL*> super_t; public: Optional<std::string> name, size, style; - TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); - void setValueFromBlock() const; - void setBlockFromValue(); + ParamValue(const LLFontGL* value); + void updateValueFromBlock(); + void updateBlockFromValue(); }; template<> @@ -467,17 +475,17 @@ namespace LLInitParam template<> - class TypedParam<LLCoordGL> - : public BlockValue<LLCoordGL> + class ParamValue<LLCoordGL, TypeValues<LLCoordGL> > + : public CustomParamValue<LLCoordGL> { - typedef BlockValue<LLCoordGL> super_t; + typedef CustomParamValue<LLCoordGL> super_t; public: Optional<S32> x, y; - TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); - void setValueFromBlock() const; - void setBlockFromValue(); + ParamValue(const LLCoordGL& val); + void updateValueFromBlock(); + void updateBlockFromValue(); }; } diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 5de96f9d48..25e7a31e90 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -152,7 +152,27 @@ static LLFastTimer::DeclareTimer FTM_XML_PARSE("XML Reading/Parsing"); bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root) { LLFastTimer timer(FTM_XML_PARSE); - return LLXMLNode::getLayeredXMLNode(xui_filename, root, LLUI::getXUIPaths()); + + std::vector<std::string> paths; + std::string path = gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), xui_filename); + if (!path.empty()) + { + paths.push_back(path); + } + + std::string localize_path = gDirUtilp->findSkinnedFilename(LLUI::getLocalizedSkinPath(), xui_filename); + if (!localize_path.empty() && localize_path != path) + { + paths.push_back(localize_path); + } + + if (paths.empty()) + { + // sometimes whole path is passed in as filename + paths.push_back(xui_filename); + } + + return LLXMLNode::getLayeredXMLNode(root, paths); } @@ -214,7 +234,7 @@ LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string LLUICtrlFactory::getCurFileName() { - return mFileNames.empty() ? "" : gDirUtilp->getWorkingDir() + gDirUtilp->getDirDelimiter() + mFileNames.back(); + return mFileNames.empty() ? "" : mFileNames.back(); } diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 1ffad4806e..f37947a50b 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -155,32 +155,32 @@ void LLUIImage::onImageLoaded() namespace LLInitParam { - void TypedParam<LLUIImage*>::setValueFromBlock() const + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() { // The keyword "none" is specifically requesting a null image // do not default to current value. Used to overwrite template images. if (name() == "none") { - mData.mValue = NULL; + updateValue(NULL); return; } LLUIImage* imagep = LLUI::getUIImage(name()); if (imagep) { - mData.mValue = imagep; + updateValue(imagep); } } - void TypedParam<LLUIImage*>::setBlockFromValue() + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue() { - if (mData.mValue == NULL) + if (getValue() == NULL) { name.set("none", false); } else { - name.set(mData.mValue->getName(), false); + name.set(getValue()->getName(), false); } } diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index 38107c112d..139d88e0ac 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -92,22 +92,23 @@ protected: namespace LLInitParam { template<> - class TypedParam<LLUIImage*, TypeValues<LLUIImage*>, false> - : public BlockValue<LLUIImage*> + class ParamValue<LLUIImage*, TypeValues<LLUIImage*> > + : public CustomParamValue<LLUIImage*> { typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type T_const_ref; - typedef BlockValue<LLUIImage*> super_t; + typedef CustomParamValue<LLUIImage*> super_t; public: Optional<std::string> name; - TypedParam(BlockDescriptor& descriptor, const char* name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count) + ParamValue(LLUIImage* const& image) + : super_t(image) { - setBlockFromValue(); + updateBlockFromValue(); + addSynonym(name, "name"); } - void setValueFromBlock() const; - void setBlockFromValue(); + void updateValueFromBlock(); + void updateBlockFromValue(); }; // Need custom comparison function for our test app, which only loads diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 267640a226..d73e87129e 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -338,7 +338,7 @@ void LLView::removeChild(LLView* child) } else { - llerrs << "LLView::removeChild called with non-child" << llendl; + llwarns << child->getName() << "is not a child of " << getName() << llendl; } updateBoundingRect(); } @@ -1958,7 +1958,7 @@ void LLView::centerWithin(const LLRect& bounds) translate( left - getRect().mLeft, bottom - getRect().mBottom ); } -BOOL LLView::localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LLView* other_view) const +BOOL LLView::localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, const LLView* other_view) const { const LLView* cur_view = this; const LLView* root_view = NULL; @@ -2001,7 +2001,7 @@ BOOL LLView::localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LL return FALSE; } -BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, LLView* other_view ) const +BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, const LLView* other_view ) const { LLRect cur_rect = local; const LLView* cur_view = this; diff --git a/indra/llui/llview.h b/indra/llui/llview.h index d2bbd663b8..61dc4b8030 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -406,8 +406,8 @@ public: BOOL blockMouseEvent(S32 x, S32 y) const; // See LLMouseHandler virtuals for screenPointToLocal and localPointToScreen - BOOL localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LLView* other_view) const; - BOOL localRectToOtherView( const LLRect& local, LLRect* other, LLView* other_view ) const; + BOOL localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, const LLView* other_view) const; + BOOL localRectToOtherView( const LLRect& local, LLRect* other, const LLView* other_view ) const; void screenRectToLocal( const LLRect& screen, LLRect* local ) const; void localRectToScreen( const LLRect& local, LLRect* screen ) const; diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index 96ebe83826..26b3b17577 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -114,32 +114,30 @@ namespace LLInitParam const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); mEnclosingBlockOffset = (U16)(my_addr - block_addr); } - void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {} + void BaseBlock::paramChanged(const Param& last_param, bool user_provided) {} - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){} + 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){ return true; } - bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; } - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; } - bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ 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; } - TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count) + ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + : super_t(color) {} - void TypedParam<LLUIColor>::setValueFromBlock() const + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() {} - void TypedParam<LLUIColor>::setBlockFromValue() - {} - - void TypeValues<LLUIColor>::declareValues() + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue() {} bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -147,14 +145,14 @@ namespace LLInitParam return false; } - TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, _name, value, func, min_count, max_count) + ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + : super_t(fontp) {} - void TypedParam<const LLFontGL*>::setValueFromBlock() const + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() {} - void TypedParam<const LLFontGL*>::setBlockFromValue() + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue() {} void TypeValues<LLFontGL::HAlign>::declareValues() @@ -166,10 +164,10 @@ namespace LLInitParam void TypeValues<LLFontGL::ShadowType>::declareValues() {} - void TypedParam<LLUIImage*>::setValueFromBlock() const + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() {} - void TypedParam<LLUIImage*>::setBlockFromValue() + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue() {} @@ -193,8 +191,8 @@ LLFontGL* LLFontGL::getFontDefault() return NULL; } -char* _PREHASH_AgentData = "AgentData"; -char* _PREHASH_AgentID = "AgentID"; +char const* const _PREHASH_AgentData = (char *)"AgentData"; +char const* const _PREHASH_AgentID = (char *)"AgentID"; LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS); diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 8f0a48018f..2f814f4200 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -70,6 +70,22 @@ S32 LLUIImage::getHeight() const return 0; } +namespace LLInitParam +{ + S32 Parser::sNextParseGeneration = 0; + 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 fdaab00f18..e09ef33d49 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -66,11 +66,25 @@ namespace LLInitParam BaseBlock::BaseBlock() {} BaseBlock::~BaseBlock() {} - void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {} - - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){} + S32 Parser::sNextParseGeneration = 0; + + 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::paramChanged(const Param& last_param, bool user_provided) {} + + 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; @@ -84,23 +98,20 @@ namespace LLInitParam mEnclosingBlockOffset = (U16)(my_addr - block_addr); } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; } - bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; } - bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; } - bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; } + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ 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; } - TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, name, value, func, min_count, max_count) + ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) + : super_t(color) {} - void TypedParam<LLUIColor>::setValueFromBlock() const + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() {} - void TypedParam<LLUIColor>::setBlockFromValue() - {} - - void TypeValues<LLUIColor>::declareValues() + void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue() {} bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -108,14 +119,15 @@ namespace LLInitParam return false; } - TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) - : super_t(descriptor, _name, value, func, min_count, max_count) + + ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) + : super_t(fontp) {} - void TypedParam<const LLFontGL*>::setValueFromBlock() const + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() {} - void TypedParam<const LLFontGL*>::setBlockFromValue() + void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue() {} void TypeValues<LLFontGL::HAlign>::declareValues() @@ -127,10 +139,10 @@ namespace LLInitParam void TypeValues<LLFontGL::ShadowType>::declareValues() {} - void TypedParam<LLUIImage*>::setValueFromBlock() const + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() {} - void TypedParam<LLUIImage*>::setBlockFromValue() + void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue() {} bool ParamCompare<LLUIImage*, false>::equals( |