diff options
Diffstat (limited to 'indra/llui')
33 files changed, 306 insertions, 62 deletions
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index edcbc3fbb7..809d72208f 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -55,6 +55,7 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) , mTabComparator( NULL ) , mNoVisibleTabsHelpText(NULL) , mNoVisibleTabsOrigString(params.no_visible_tabs_text.initial_value().asString()) + , mSkipScrollToChild(false) { initNoTabsWidget(params.no_matched_tabs_text); @@ -655,6 +656,37 @@ void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) { updateLayout(getRect().getWidth(),getRect().getHeight()); } + +// virtual +void LLAccordionCtrl::onUpdateScrollToChild(const LLUICtrl *cntrl) +{ + if (mScrollbar && mScrollbar->getVisible() && !mSkipScrollToChild) + { + // same as scrollToShowRect + LLRect rect; + cntrl->localRectToOtherView(cntrl->getLocalRect(), &rect, this); + + // Translate to parent coordinatess to check if we are in visible rectangle + rect.translate(getRect().mLeft, getRect().mBottom); + + if (!getRect().contains(rect)) + { + // for accordition's scroll, height is in pixels + // Back to local coords and calculate position for scroller + S32 bottom = mScrollbar->getDocPos() - rect.mBottom + getRect().mBottom; + S32 top = mScrollbar->getDocPos() - rect.mTop + getRect().mTop; + + S32 scroll_pos = llclamp(mScrollbar->getDocPos(), + bottom, // min vertical scroll + top); // max vertical scroll + + mScrollbar->setDocPos(scroll_pos); + } + } + + LLUICtrl::onUpdateScrollToChild(cntrl); +} + void LLAccordionCtrl::onOpen (const LLSD& key) { for(size_t i=0;i<mAccordionTabs.size();++i) diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index 1fe64c472e..2828254472 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -111,6 +111,7 @@ public: void draw(); void onScrollPosChangeCallback(S32, LLScrollbar*); + virtual void onUpdateScrollToChild(const LLUICtrl * cntrl); void onOpen (const LLSD& key); S32 notifyParent(const LLSD& info); @@ -137,6 +138,8 @@ public: bool getFitParent() const {return mFitParent;} + void setSkipScrollToChild(bool skip) { mSkipScrollToChild = skip; } + private: void initNoTabsWidget(const LLTextBox::Params& tb_params); void updateNoTabsHelpTextVisibility(); @@ -182,6 +185,8 @@ private: F32 mAutoScrollRate; LLTextBox* mNoVisibleTabsHelpText; + bool mSkipScrollToChild; + std::string mNoMatchedTabsOrigString; std::string mNoVisibleTabsOrigString; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 1034a21905..098621b543 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -452,6 +452,35 @@ void LLAccordionCtrlTab::onVisibilityChange(BOOL new_visibility) notifyParent(LLSD().with("child_visibility_change", new_visibility)); } +// virtual +void LLAccordionCtrlTab::onUpdateScrollToChild(const LLUICtrl *cntrl) +{ + if (mScrollbar && mScrollbar->getVisible()) + { + LLRect rect; + cntrl->localRectToOtherView(cntrl->getLocalRect(), &rect, this); + + // Translate to parent coordinatess to check if we are in visible rectangle + rect.translate(getRect().mLeft, getRect().mBottom); + + if (!getRect().contains(rect)) + { + // for accordition's scroll, height is in pixels + // Back to local coords and calculate position for scroller + S32 bottom = mScrollbar->getDocPos() - rect.mBottom + getRect().mBottom; + S32 top = mScrollbar->getDocPos() - rect.mTop + getRect().mTop; + + S32 scroll_pos = llclamp(mScrollbar->getDocPos(), + bottom, // min vertical scroll + top); // max vertical scroll + + mScrollbar->setDocPos(scroll_pos); + } + } + + LLUICtrl::onUpdateScrollToChild(cntrl); +} + BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask) { if(mCollapsible && mHeaderVisible && mCanOpenClose) diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 0263bce4be..2c72e8c036 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -159,6 +159,7 @@ public: * Raises notifyParent event with "child_visibility_change" = new_visibility */ void onVisibilityChange(BOOL new_visibility); + virtual void onUpdateScrollToChild(const LLUICtrl * cntrl); // Changes expand/collapse state and triggers expand/collapse callbacks virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp index 0557cd4375..5f11c383ef 100644 --- a/indra/llui/llbadgeowner.cpp +++ b/indra/llui/llbadgeowner.cpp @@ -56,6 +56,14 @@ void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p) } } +void LLBadgeOwner::reshapeBadge(const LLRect& new_rect) +{ + if (mBadge) + { + mBadge->setShape(new_rect); + } +} + void LLBadgeOwner::setBadgeVisibility(bool visible) { if (mBadge) diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h index 01ed95f3a3..4ce208fa0d 100644 --- a/indra/llui/llbadgeowner.h +++ b/indra/llui/llbadgeowner.h @@ -46,6 +46,7 @@ public: bool hasBadgeHolderParent() const { return mHasBadgeHolderParent; }; void setBadgeVisibility(bool visible); void setDrawBadgeAtTop(bool draw_at_top); + void reshapeBadge(const LLRect& new_rect); private: diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 27444b7f5b..9682c3bc10 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -643,7 +643,8 @@ void LLButton::draw() LLColor4 highlighting_color = LLColor4::white; LLColor4 glow_color = LLColor4::white; LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA; - LLUIImage* imagep = NULL; + LLUIImage* imagep = NULL; + LLUIImage* image_glow = NULL; // Cancel sticking of color, if the button is pressed, // or when a flashing of the previously selected button is ended @@ -710,17 +711,18 @@ void LLButton::draw() imagep = mImageDisabled; } + image_glow = imagep; + if (mFlashing) { - // if button should flash and we have icon for flashing, use it as image for button - if(flash && mImageFlash) + if (flash && mImageFlash) { - // setting flash to false to avoid its further influence on glow - flash = false; - imagep = mImageFlash; + // if button should flash and we have icon for flashing, use it as image for button + image_glow = mImageFlash; } - // else use usual flashing via flash_color - else if (mFlashingTimer) + + // provide fade-in and fade-out via flash_color + if (mFlashingTimer) { LLColor4 flash_color = mFlashBgColor.get(); use_glow_effect = TRUE; @@ -734,6 +736,11 @@ void LLButton::draw() { glow_color = highlighting_color; } + else + { + // will fade from highlight color + glow_color = flash_color; + } } } @@ -806,7 +813,7 @@ void LLButton::draw() if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); - imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha)); + image_glow->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha)); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } @@ -817,7 +824,7 @@ void LLButton::draw() if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); - imagep->drawSolid(0, y, glow_color % (mCurGlowStrength * alpha)); + image_glow->drawSolid(0, y, glow_color % (mCurGlowStrength * alpha)); gGL.setSceneBlendType(LLRender::BT_ALPHA); } } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 7629ed1fea..572d36996c 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -205,6 +205,7 @@ public: void setFlashing( bool b, bool force_flashing = false ); BOOL getFlashing() const { return mFlashing; } LLFlashTimer* getFlashTimer() {return mFlashingTimer;} + void setFlashColor(const LLUIColor &color) { mFlashBgColor = color; }; void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } LLFontGL::HAlign getHAlign() const { return mHAlign; } diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index c7f0326ed4..52dc908655 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -514,6 +514,14 @@ S32 LLComboBox::getCurrentIndex() const return -1; } +void LLComboBox::setEnabledByValue(const LLSD& value, BOOL enabled) +{ + LLScrollListItem *found = mList->getItem(value); + if (found) + { + found->setEnabled(enabled); + } +} void LLComboBox::createLineEditor(const LLComboBox::Params& p) { diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 7d38c051a5..4af3313162 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -158,6 +158,8 @@ public: BOOL setCurrentByIndex( S32 index ); S32 getCurrentIndex() const; + void setEnabledByValue(const LLSD& value, BOOL enabled); + void createLineEditor(const Params&); //======================================================================== diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index e718fcec46..0c1dcc301b 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -342,7 +342,9 @@ static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View"); void LLFolderView::filter( LLFolderViewFilter& filter ) { LL_RECORD_BLOCK_TIME(FTM_FILTER); - filter.resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32(mParentPanel.get()->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100)); + static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); + static LLCachedControl<S32> filter_hidden(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1); + filter.resetTime(llclamp(mParentPanel.get()->getVisible() ? filter_visible() : filter_hidden(), 1, 100)); // Note: we filter the model, not the view getViewModelItem()->filter(filter); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9a1f7de73b..1c6c7b1b35 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -122,6 +122,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) : LLView(p), mLabelWidth(0), mLabelWidthDirty(false), + mSuffixNeedsRefresh(false), mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), mParentFolder( NULL ), mIsSelected( FALSE ), @@ -181,11 +182,25 @@ LLFolderViewItem::~LLFolderViewItem() BOOL LLFolderViewItem::postBuild() { - refresh(); + LLFolderViewModelItem& vmi = *getViewModelItem(); + // getDisplayName() is expensive (due to internal getLabelSuffix() and name building) + // it also sets search strings so it requires a filter reset + mLabel = vmi.getDisplayName(); + setToolTip(vmi.getName()); + + // Dirty the filter flag of the model from the view (CHUI-849) + vmi.dirtyFilter(); + + // Don't do full refresh on constructor if it is possible to avoid + // it significantly slows down bulk view creation. + // Todo: Ideally we need to move getDisplayName() out of constructor as well. + // Like: make a logic that will let filter update search string, + // while LLFolderViewItem::arrange() updates visual part + mSuffixNeedsRefresh = true; + mLabelWidthDirty = true; return TRUE; } - LLFolderView* LLFolderViewItem::getRoot() { return mRoot; @@ -280,24 +295,51 @@ BOOL LLFolderViewItem::isPotentiallyVisible(S32 filter_generation) void LLFolderViewItem::refresh() { - LLFolderViewModelItem& vmi = *getViewModelItem(); + LLFolderViewModelItem& vmi = *getViewModelItem(); + + mLabel = vmi.getDisplayName(); + setToolTip(vmi.getName()); + // icons are slightly expensive to get, can be optimized + // see LLInventoryIcon::getIcon() + mIcon = vmi.getIcon(); + mIconOpen = vmi.getIconOpen(); + mIconOverlay = vmi.getIconOverlay(); - mLabel = vmi.getDisplayName(); + if (mRoot->useLabelSuffix()) + { + // Very Expensive! + // Can do a number of expensive checks, like checking active motions, wearables or friend list + mLabelStyle = vmi.getLabelStyle(); + mLabelSuffix = vmi.getLabelSuffix(); + } - setToolTip(vmi.getName()); - mIcon = vmi.getIcon(); - mIconOpen = vmi.getIconOpen(); - mIconOverlay = vmi.getIconOverlay(); + // Dirty the filter flag of the model from the view (CHUI-849) + vmi.dirtyFilter(); + + mLabelWidthDirty = true; + mSuffixNeedsRefresh = false; +} + +void LLFolderViewItem::refreshSuffix() +{ + LLFolderViewModelItem const* vmi = getViewModelItem(); + + // icons are slightly expensive to get, can be optimized + // see LLInventoryIcon::getIcon() + mIcon = vmi->getIcon(); + mIconOpen = vmi->getIconOpen(); + mIconOverlay = vmi->getIconOverlay(); if (mRoot->useLabelSuffix()) { - mLabelStyle = vmi.getLabelStyle(); - mLabelSuffix = vmi.getLabelSuffix(); + // Very Expensive! + // Can do a number of expensive checks, like checking active motions, wearables or friend list + mLabelStyle = vmi->getLabelStyle(); + mLabelSuffix = vmi->getLabelSuffix(); } - mLabelWidthDirty = true; - // Dirty the filter flag of the model from the view (CHUI-849) - vmi.dirtyFilter(); + mLabelWidthDirty = true; + mSuffixNeedsRefresh = false; } // Utility function for LLFolderView @@ -348,6 +390,12 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) : 0; if (mLabelWidthDirty) { + if (mSuffixNeedsRefresh) + { + // Expensive. But despite refreshing label, + // it is purely visual, so it is fine to do at our laisure + refreshSuffix(); + } mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; mLabelWidthDirty = false; } diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 61c39e0175..da09d139e9 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -95,6 +95,7 @@ protected: LLPointer<LLFolderViewModelItem> mViewModelItem; LLFontGL::StyleFlags mLabelStyle; std::string mLabelSuffix; + bool mSuffixNeedsRefresh; //suffix and icons LLUIImagePtr mIcon, mIconOpen, mIconOverlay; @@ -266,8 +267,13 @@ public: virtual BOOL passedFilter(S32 filter_generation = -1); virtual BOOL isPotentiallyVisible(S32 filter_generation = -1); - // refresh information from the object being viewed. - virtual void refresh(); + // refresh information from the object being viewed. + // refreshes label, suffixes and sets icons. Expensive! + // Causes filter update + virtual void refresh(); + // refreshes suffixes and sets icons. Expensive! + // Does not need filter update + virtual void refreshSuffix(); // LLView functionality virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 3b45fb53a2..ea106b5fae 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -48,7 +48,8 @@ std::string LLFolderViewModelCommon::getStatusText() void LLFolderViewModelCommon::filter() { - getFilter().resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100)); + static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); + getFilter().resetTime(llclamp(filter_visible(), 1, 100)); mFolderView->getViewModelItem()->filter(getFilter()); } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index f71a88c56e..84a1539094 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -285,17 +285,7 @@ public: typedef std::list<LLFolderViewModelItem*> child_list_t; virtual void addChild(LLFolderViewModelItem* child) - { - // Avoid duplicates: bail out if that child is already present in the list - // Note: this happens when models are created before views - child_list_t::const_iterator iter; - for (iter = mChildren.begin(); iter != mChildren.end(); iter++) - { - if (child == *iter) - { - return; - } - } + { mChildren.push_back(child); child->setParent(this); dirtyFilter(); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 70304cdfd2..1badd54fca 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -2151,6 +2151,7 @@ void LLLineEditor::clear() void LLLineEditor::onTabInto() { selectAll(); + LLUICtrl::onTabInto(); } //virtual diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index 20e2b569f1..b3df7c154b 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -509,6 +509,7 @@ void LLMultiSliderCtrl::onTabInto() { mEditor->onTabInto(); } + LLF32UICtrl::onTabInto(); } void LLMultiSliderCtrl::reportInvalidData() diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 6a7075301b..06ec648178 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -255,7 +255,7 @@ LLNotificationForm::LLNotificationForm(const LLSD& sd) } else { - LL_WARNS() << "Invalid form data " << sd << LL_ENDL; + LL_WARNS("Notifications") << "Invalid form data " << sd << LL_ENDL; mFormData = LLSD::emptyArray(); } } @@ -448,11 +448,11 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mUniqueContext.push_back(context.value); } - LL_DEBUGS() << "notification \"" << mName << "\": tag count is " << p.tags.size() << LL_ENDL; + LL_DEBUGS("Notifications") << "notification \"" << mName << "\": tag count is " << p.tags.size() << LL_ENDL; BOOST_FOREACH(const LLNotificationTemplate::Tag& tag, p.tags) { - LL_DEBUGS() << " tag \"" << std::string(tag.value) << "\"" << LL_ENDL; + LL_DEBUGS("Notifications") << " tag \"" << std::string(tag.value) << "\"" << LL_ENDL; mTags.push_back(tag.value); } @@ -1398,8 +1398,14 @@ void LLNotifications::initSingleton() createDefaultChannels(); } +void LLNotifications::cleanupSingleton() +{ + clear(); +} + void LLNotifications::createDefaultChannels() { + LL_INFOS("Notifications") << "Generating default notification channels" << LL_ENDL; // now construct the various channels AFTER loading the notifications, // because the history channel is going to rewrite the stored notifications file mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "", @@ -1455,7 +1461,7 @@ void LLNotifications::forceResponse(const LLNotification::Params& params, S32 op if (selected_item.isUndefined()) { - LL_WARNS() << "Invalid option" << option << " for notification " << (std::string)params.name << LL_ENDL; + LL_WARNS("Notifications") << "Invalid option" << option << " for notification " << (std::string)params.name << LL_ENDL; return; } response[selected_item["name"].asString()] = true; @@ -1489,12 +1495,12 @@ void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements) if (found != replacements.end()) { replacement = found->second; - LL_DEBUGS() << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << LL_ENDL; + LL_DEBUGS("Notifications") << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << LL_ENDL; it->second->setValue(replacement); } else { - LL_WARNS() << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << LL_ENDL; + LL_WARNS("Notifications") << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << LL_ENDL; } } } @@ -1533,7 +1539,7 @@ void addPathIfExists(const std::string& new_path, std::vector<std::string>& path bool LLNotifications::loadTemplates() { - LL_INFOS() << "Reading notifications template" << LL_ENDL; + LL_INFOS("Notifications") << "Reading notifications template" << LL_ENDL; // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it // output all relevant pathnames instead of just the ones from the most // specific skin. @@ -1604,7 +1610,7 @@ bool LLNotifications::loadTemplates() mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification)); } - LL_INFOS() << "...done" << LL_ENDL; + LL_INFOS("Notifications") << "...done" << LL_ENDL; return true; } @@ -1832,7 +1838,7 @@ 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. - LL_DEBUGS() + LL_DEBUGS("Notifications") << "notification \"" << n->getName() << "\" " << "testing against " << ((*it)->mVisible?"show":"hide") << " rule, " << "name = \"" << (*it)->mName << "\" " @@ -1877,7 +1883,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n) if((*it)->mResponse.empty()) { // Response property is empty. Cancel this notification. - LL_DEBUGS() << "cancelling notification " << n->getName() << LL_ENDL; + LL_DEBUGS("Notifications") << "cancelling notification " << n->getName() << LL_ENDL; cancel(n); } @@ -1888,7 +1894,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n) // TODO: verify that the response template has an item with the correct name response[(*it)->mResponse] = true; - LL_DEBUGS() << "responding to notification " << n->getName() << " with response = " << response << LL_ENDL; + LL_DEBUGS("Notifications") << "responding to notification " << n->getName() << " with response = " << response << LL_ENDL; n->respond(response); } @@ -1900,7 +1906,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n) break; } - LL_DEBUGS() << "allowing notification " << n->getName() << LL_ENDL; + LL_DEBUGS("Notifications") << "allowing notification " << n->getName() << LL_ENDL; return true; } @@ -1961,7 +1967,7 @@ void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id, // from PE merge - we should figure out if this is the right thing to do if (name.empty()) { - LL_WARNS() << "Empty name received for Id: " << agent_id << LL_ENDL; + LL_WARNS("Notifications") << "Empty name received for Id: " << agent_id << LL_ENDL; name = SYSTEM_FROM; } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index cac687f53d..2f4578da17 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -957,6 +957,7 @@ public: private: /*virtual*/ void initSingleton(); + /*virtual*/ void cleanupSingleton(); void loadPersistentNotifications(); @@ -1069,6 +1070,7 @@ public: LLPersistentNotificationChannel() : LLNotificationChannel("Persistent", "Visible", ¬ificationFilter) {} + virtual ~LLPersistentNotificationChannel() {} typedef std::vector<LLNotificationPtr> history_list_t; history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 763c3aeb81..367c6c3c5b 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -132,6 +132,7 @@ LLScrollListCtrl::Params::Params() sort_ascending("sort_ascending", true), mouse_wheel_opaque("mouse_wheel_opaque", false), commit_on_keyboard_movement("commit_on_keyboard_movement", true), + commit_on_selection_change("commit_on_selection_change", false), heading_height("heading_height"), page_lines("page_lines", 0), background_visible("background_visible"), @@ -162,7 +163,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mMaxSelectable(0), mAllowKeyboardMovement(true), mCommitOnKeyboardMovement(p.commit_on_keyboard_movement), - mCommitOnSelectionChange(false), + mCommitOnSelectionChange(p.commit_on_selection_change), mSelectionChanged(false), mNeedsScroll(false), mCanSelect(true), diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 43e1c0d707..8d00296183 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -97,6 +97,7 @@ public: // behavioral flags Optional<bool> multi_select, commit_on_keyboard_movement, + commit_on_selection_change, mouse_wheel_opaque; // display flags diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index 3b89a8ca63..d80a434f22 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -479,6 +479,7 @@ void LLSliderCtrl::onTabInto() { mEditor->onTabInto(); } + LLF32UICtrl::onTabInto(); } void LLSliderCtrl::reportInvalidData() diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp index 296ea09079..ebd8ca0923 100644 --- a/indra/llui/llspellcheck.cpp +++ b/indra/llui/llspellcheck.cpp @@ -49,8 +49,6 @@ LLSpellChecker::settings_change_signal_t LLSpellChecker::sSettingsChangeSignal; LLSpellChecker::LLSpellChecker() : mHunspell(NULL) { - // Load initial dictionary information - refreshDictionaryMap(); } LLSpellChecker::~LLSpellChecker() @@ -58,6 +56,12 @@ LLSpellChecker::~LLSpellChecker() delete mHunspell; } +void LLSpellChecker::initSingleton() +{ + // Load initial dictionary information + refreshDictionaryMap(); +} + bool LLSpellChecker::checkSpelling(const std::string& word) const { if ( (!mHunspell) || (word.length() < 3) || (0 != mHunspell->spell(word.c_str())) ) diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index f1964cc091..3da5e30955 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -47,6 +47,7 @@ public: protected: void addToDictFile(const std::string& dict_path, const std::string& word); void initHunspell(const std::string& dict_language); + void initSingleton(); public: typedef std::list<std::string> dict_list_t; diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index ce3fc29d32..ee78b82429 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -442,7 +442,8 @@ void LLSpinCtrl::setAllowEdit(BOOL allow_edit) void LLSpinCtrl::onTabInto() { - mEditor->onTabInto(); + mEditor->onTabInto(); + LLF32UICtrl::onTabInto(); } diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 6521b883f8..e6b43da8e5 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -220,6 +220,8 @@ LLTabContainer::Params::Params() last_tab("last_tab"), use_custom_icon_ctrl("use_custom_icon_ctrl", false), open_tabs_on_drag_and_drop("open_tabs_on_drag_and_drop", false), + enable_tabs_flashing("enable_tabs_flashing", false), + tabs_flashing_color("tabs_flashing_color"), tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0), use_ellipses("use_ellipses"), font_halign("halign") @@ -259,6 +261,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) mCustomIconCtrlUsed(p.use_custom_icon_ctrl), mOpenTabsOnDragAndDrop(p.open_tabs_on_drag_and_drop), mTabIconCtrlPad(p.tab_icon_ctrl_pad), + mEnableTabsFlashing(p.enable_tabs_flashing), + mTabsFlashingColor(p.tabs_flashing_color), mUseTabEllipses(p.use_ellipses) { static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0); @@ -280,6 +284,11 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) mMinTabWidth = tabcntr_vert_tab_min_width; } + if (p.tabs_flashing_color.isProvided()) + { + mEnableTabsFlashing = true; + } + initButtons( ); } @@ -1102,6 +1111,10 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) p.pad_left( mLabelPadLeft ); p.pad_right(2); } + + // inits flash timer + p.button_flash_enable = mEnableTabsFlashing; + p.flash_color = mTabsFlashingColor; // *TODO : It seems wrong not to use p in both cases considering the way p is initialized if (mCustomIconCtrlUsed) diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 6bf963313c..8f8cedb1b9 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -109,6 +109,12 @@ public: * Open tabs on hover in drag and drop situations */ Optional<bool> open_tabs_on_drag_and_drop; + + /** + * Enable tab flashing + */ + Optional<bool> enable_tabs_flashing; + Optional<LLUIColor> tabs_flashing_color; /** * Paddings for LLIconCtrl in case of LLCustomButtonIconCtrl usage(use_custom_icon_ctrl = true) @@ -310,6 +316,8 @@ private: bool mCustomIconCtrlUsed; bool mOpenTabsOnDragAndDrop; + bool mEnableTabsFlashing; + LLUIColor mTabsFlashingColor; S32 mTabIconCtrlPad; bool mUseTabEllipses; }; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 83b851eed2..ff72417867 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1017,7 +1017,38 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask) // handle triple click if (!mTripleClickTimer.hasExpired()) { - selectAll(); + S32 real_line = getLineNumFromDocIndex(mCursorPos, false); + S32 line_start = -1; + S32 line_end = -1; + for (line_list_t::const_iterator it = mLineInfoList.begin(), end_it = mLineInfoList.end(); + it != end_it; + ++it) + { + if (it->mLineNum < real_line) + { + continue; + } + if (it->mLineNum > real_line) + { + break; + } + if (line_start == -1) + { + line_start = it->mDocIndexStart; + } + line_end = it->mDocIndexEnd; + line_end = llclamp(line_end, 0, getLength()); + } + + if (line_start == -1) + { + return TRUE; + } + + mSelectionEnd = line_start; + mSelectionStart = line_end; + setCursorPos(line_start); + return TRUE; } @@ -2228,6 +2259,18 @@ void LLTextBase::needsReflow(S32 index) mReflowIndex = llmin(mReflowIndex, index); } +S32 LLTextBase::removeFirstLine() +{ + if (!mLineInfoList.empty()) + { + S32 length = getLineEnd(0); + deselect(); + removeStringNoUndo(0, length); + return length; + } + return 0; +} + void LLTextBase::appendLineBreakSegment(const LLStyle::Params& style_params) { segment_vec_t segments; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 8687e7aa2a..4e966b7cef 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -404,6 +404,7 @@ public: virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style virtual std::string getText() const; void setMaxTextLength(S32 length) { mMaxTextByteLength = length; } + S32 getMaxTextLength() { return mMaxTextByteLength; } // wide-char versions void setWText(const LLWString& text); @@ -432,6 +433,7 @@ public: S32 getLength() const { return getWText().length(); } S32 getLineCount() const { return mLineInfoList.size(); } + S32 removeFirstLine(); // returns removed length void addDocumentChild(LLView* view); void removeDocumentChild(LLView* view); diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index c98da0d410..544a76e8d5 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -721,8 +721,9 @@ void LLUICtrl::resetDirty() } // virtual -void LLUICtrl::onTabInto() +void LLUICtrl::onTabInto() { + onUpdateScrollToChild(this); } // virtual diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 333d03f208..e6835f73fb 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -454,13 +454,17 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const } // -// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link +// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ *secondlifegrid.net/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link // LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL() { mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com)" "|" - "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?))" + "(http://([-\\w\\.]*\\.)?secondlifegrid\\.net)" + "|" + "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?)" + "|" + "(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?))" "\\/\\S*", boost::regex::perl|boost::regex::icase); @@ -495,12 +499,14 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const } // -// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com and *tilia-inc.com urls to substitute icon 'hand.png' before link +// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com *secondlifegrid.net and *tilia-inc.com urls to substitute icon 'hand.png' before link // LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL() { - mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)", - boost::regex::perl|boost::regex::icase); + mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)" + "|" + "https?://([-\\w\\.]*\\.)?secondlifegrid\\.net(?!\\S)", + boost::regex::perl|boost::regex::icase); mIcon = "Hand"; mMenuName = "menu_url_http.xml"; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index bd213d594a..e3a6a98a9f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -646,6 +646,16 @@ void LLView::onVisibilityChange ( BOOL new_visibility ) } // virtual +void LLView::onUpdateScrollToChild(const LLUICtrl * cntrl) +{ + LLView* parent_view = getParent(); + if (parent_view) + { + parent_view->onUpdateScrollToChild(cntrl); + } +} + +// virtual void LLView::translate(S32 x, S32 y) { mRect.translate(x, y); diff --git a/indra/llui/llview.h b/indra/llui/llview.h index db81900aaf..5c91c37d3c 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -301,6 +301,7 @@ public: virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); virtual void onVisibilityChange ( BOOL new_visibility ); + virtual void onUpdateScrollToChild(const LLUICtrl * cntrl); void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); } void popVisible() { setVisible(mLastVisible); } |