summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llaccordionctrl.cpp32
-rw-r--r--indra/llui/llaccordionctrl.h5
-rw-r--r--indra/llui/llaccordionctrltab.cpp29
-rw-r--r--indra/llui/llaccordionctrltab.h1
-rw-r--r--indra/llui/llbadgeowner.cpp8
-rw-r--r--indra/llui/llbadgeowner.h1
-rw-r--r--indra/llui/llbutton.cpp27
-rw-r--r--indra/llui/llbutton.h1
-rw-r--r--indra/llui/llcombobox.cpp8
-rw-r--r--indra/llui/llcombobox.h2
-rw-r--r--indra/llui/llfolderview.cpp4
-rw-r--r--indra/llui/llfolderviewitem.cpp74
-rw-r--r--indra/llui/llfolderviewitem.h10
-rw-r--r--indra/llui/llfolderviewmodel.cpp3
-rw-r--r--indra/llui/llfolderviewmodel.h12
-rw-r--r--indra/llui/lllineeditor.cpp1
-rw-r--r--indra/llui/llmultisliderctrl.cpp1
-rw-r--r--indra/llui/llnotifications.cpp32
-rw-r--r--indra/llui/llnotifications.h2
-rw-r--r--indra/llui/llscrolllistctrl.cpp3
-rw-r--r--indra/llui/llscrolllistctrl.h1
-rw-r--r--indra/llui/llsliderctrl.cpp1
-rw-r--r--indra/llui/llspellcheck.cpp8
-rw-r--r--indra/llui/llspellcheck.h1
-rw-r--r--indra/llui/llspinctrl.cpp3
-rw-r--r--indra/llui/lltabcontainer.cpp13
-rw-r--r--indra/llui/lltabcontainer.h8
-rw-r--r--indra/llui/lltextbase.cpp45
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/llui/lluictrl.cpp3
-rw-r--r--indra/llui/llurlentry.cpp16
-rw-r--r--indra/llui/llview.cpp10
-rw-r--r--indra/llui/llview.h1
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", &notificationFilter)
{}
+ 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); }