summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llaccordionctrl.cpp36
-rw-r--r--indra/llui/llaccordionctrl.h1
-rw-r--r--indra/llui/llaccordionctrltab.cpp18
-rw-r--r--indra/llui/llaccordionctrltab.h3
-rw-r--r--indra/llui/llcheckboxctrl.cpp30
-rw-r--r--indra/llui/lldraghandle.cpp2
-rw-r--r--indra/llui/llflatlistview.cpp22
-rw-r--r--indra/llui/llflatlistview.h1
-rw-r--r--indra/llui/llfloater.cpp8
-rw-r--r--indra/llui/llfloater.h2
-rw-r--r--indra/llui/lllocalcliprect.cpp42
-rw-r--r--indra/llui/lllocalcliprect.h26
-rw-r--r--indra/llui/llmenugl.cpp6
-rw-r--r--indra/llui/llmenugl.h1
-rw-r--r--indra/llui/llnotifications.cpp1
-rw-r--r--indra/llui/llnotifications.h2
-rw-r--r--indra/llui/llresmgr.cpp4
-rw-r--r--indra/llui/llstyle.cpp12
-rw-r--r--indra/llui/llstyle.h37
-rw-r--r--indra/llui/lltextbase.cpp118
-rw-r--r--indra/llui/lltextbase.h27
-rw-r--r--indra/llui/lltextbox.cpp11
-rw-r--r--indra/llui/lltextbox.h2
-rw-r--r--indra/llui/lltexteditor.cpp3
-rw-r--r--indra/llui/lltextvalidate.cpp18
-rw-r--r--indra/llui/lltextvalidate.h1
-rw-r--r--indra/llui/lltooltip.cpp2
-rw-r--r--indra/llui/llurlentry.cpp19
-rw-r--r--indra/llui/llurlentry.h5
-rw-r--r--indra/llui/llurlmatch.cpp6
-rw-r--r--indra/llui/llurlmatch.h6
-rw-r--r--indra/llui/llurlregistry.cpp6
32 files changed, 341 insertions, 137 deletions
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index 673631f99a..c3ef734823 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -765,6 +765,17 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
}
return 0;
}
+ else if(str_action == "deselect_current")
+ {
+ // Reset selection to the currently selected tab.
+ if (mSelectedTab)
+ {
+ mSelectedTab->setSelected(false);
+ mSelectedTab = NULL;
+ return 1;
+ }
+ return 0;
+ }
}
else if (info.has("scrollToShowRect"))
{
@@ -811,6 +822,31 @@ void LLAccordionCtrl::reset ()
mScrollbar->setDocPos(0);
}
+void LLAccordionCtrl::expandDefaultTab()
+{
+ if (mAccordionTabs.size() > 0)
+ {
+ LLAccordionCtrlTab* tab = mAccordionTabs.front();
+
+ if (!tab->getDisplayChildren())
+ {
+ tab->setDisplayChildren(true);
+ }
+
+ for (size_t i = 1; i < mAccordionTabs.size(); ++i)
+ {
+ tab = mAccordionTabs[i];
+
+ if (tab->getDisplayChildren())
+ {
+ tab->setDisplayChildren(false);
+ }
+ }
+
+ arrange();
+ }
+}
+
void LLAccordionCtrl::sort()
{
if (!mTabComparator)
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
index b5fdf796cd..8241ee1518 100644
--- a/indra/llui/llaccordionctrl.h
+++ b/indra/llui/llaccordionctrl.h
@@ -122,6 +122,7 @@ public:
S32 notifyParent(const LLSD& info);
void reset ();
+ void expandDefaultTab();
void setComparator(const LLTabComparator* comp) { mTabComparator = comp; }
void sort();
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 37fc571bbd..87ff39575a 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -358,6 +358,7 @@ LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)
,mPaddingBottom(p.padding_bottom)
,mCanOpenClose(true)
,mFitPanel(p.fit_panel)
+ ,mSelectionEnabled(p.selection_enabled)
,mContainerPanel(NULL)
,mScrollbar(NULL)
{
@@ -371,9 +372,11 @@ LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)
mHeader = LLUICtrlFactory::create<LLAccordionCtrlTabHeader>(headerParams);
addChild(mHeader, 1);
- if (p.selection_enabled)
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this));
+
+ if (!p.selection_enabled)
{
- LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this));
+ LLFocusableElement::setFocusLostCallback(boost::bind(&LLAccordionCtrlTab::deselectOnFocusLost, this));
}
reshape(100, 200,FALSE);
@@ -598,6 +601,15 @@ void LLAccordionCtrlTab::selectOnFocusReceived()
getParent()->notifyParent(LLSD().with("action", "select_current"));
}
+void LLAccordionCtrlTab::deselectOnFocusLost()
+{
+ if(getParent()) // A parent may not be set if tabs are added dynamically.
+ {
+ getParent()->notifyParent(LLSD().with("action", "deselect_current"));
+ }
+
+}
+
S32 LLAccordionCtrlTab::getHeaderHeight()
{
return mHeaderVisible?HEADER_HEIGHT:0;
@@ -797,7 +809,7 @@ void LLAccordionCtrlTab::showAndFocusHeader()
{
LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
header->setFocus(true);
- header->setSelected(true);
+ header->setSelected(mSelectionEnabled);
LLRect screen_rc;
LLRect selected_rc = header->getRect();
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index 5646a355d0..00fb276f19 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -220,6 +220,7 @@ protected:
LLView* findContainerView ();
void selectOnFocusReceived();
+ void deselectOnFocusLost();
private:
@@ -241,6 +242,8 @@ private:
bool mStoredOpenCloseState;
bool mWasStateStored;
+ bool mSelectionEnabled;
+
LLScrollbar* mScrollbar;
LLView* mContainerPanel;
diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp
index 3d32157406..0c524cd470 100644
--- a/indra/llui/llcheckboxctrl.cpp
+++ b/indra/llui/llcheckboxctrl.cpp
@@ -81,17 +81,6 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
// must be big enough to hold all children
setUseBoundingRect(TRUE);
- // Label (add a little space to make sure text actually renders)
- const S32 FUDGE = 10;
- S32 text_width = mFont->getWidth( p.label ) + FUDGE;
- S32 text_height = llround(mFont->getLineHeight());
- LLRect label_rect;
- label_rect.setOriginAndSize(
- llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing,
- llcheckboxctrl_vpad + 1, // padding to get better alignment
- text_width + llcheckboxctrl_hpad,
- text_height );
-
// *HACK Get rid of this with SL-55508...
// this allows blank check boxes and radio boxes for now
std::string local_label = p.label;
@@ -101,7 +90,6 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
}
LLTextBox::Params tbparams = p.label_text;
- tbparams.rect(label_rect);
tbparams.initial_value(local_label);
if (p.font.isProvided())
{
@@ -111,6 +99,17 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
mLabel = LLUICtrlFactory::create<LLTextBox> (tbparams);
addChild(mLabel);
+ S32 text_width = mLabel->getTextBoundingRect().getWidth();
+ S32 text_height = llround(mFont->getLineHeight());
+ LLRect label_rect;
+ label_rect.setOriginAndSize(
+ llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing,
+ llcheckboxctrl_vpad + 1, // padding to get better alignment
+ text_width + llcheckboxctrl_hpad,
+ text_height );
+ mLabel->setShape(label_rect);
+
+
// Button
// Note: button cover the label by extending all the way to the right.
LLRect btn_rect;
@@ -190,8 +189,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
static LLUICachedControl<S32> llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0);
static LLUICachedControl<S32> llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0);
- const S32 FUDGE = 10;
- S32 text_width = mFont->getWidth( mLabel->getText() ) + FUDGE;
+ S32 text_width = mLabel->getTextBoundingRect().getWidth();
S32 text_height = llround(mFont->getLineHeight());
LLRect label_rect;
label_rect.setOriginAndSize(
@@ -199,7 +197,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
llcheckboxctrl_vpad,
text_width,
text_height );
- mLabel->setRect(label_rect);
+ mLabel->setShape(label_rect);
LLRect btn_rect;
btn_rect.setOriginAndSize(
@@ -207,7 +205,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
llcheckboxctrl_vpad,
llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width,
llmax( text_height, llcheckboxctrl_btn_size() ) );
- mButton->setRect( btn_rect );
+ mButton->setShape( btn_rect );
LLUICtrl::reshape(width, height, called_from_parent);
}
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index 9f83fcca35..b52cb2b751 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -113,7 +113,7 @@ void LLDragHandleTop::setTitle(const std::string& title)
params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
params.font_shadow(LLFontGL::DROP_SHADOW_SOFT);
params.use_ellipses = true;
- params.allow_html = false; //cancel URL replacement in floater title
+ params.parse_urls = false; //cancel URL replacement in floater title
mTitleBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild( mTitleBox );
}
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 3c79da64f9..0fa7949be2 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -610,8 +610,14 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
return;
}
- if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection();
+ //no need to do additional commit on selection reset
+ if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(true);
+
+ //only CTRL usage allows to deselect an item, usual clicking on an item cannot deselect it
+ if (mask & MASK_CONTROL)
selectItemPair(item_pair, select_item);
+ else
+ selectItemPair(item_pair, true);
}
void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask)
@@ -778,6 +784,18 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)
return true;
}
+void LLFlatListView::scrollToShowFirstSelectedItem()
+{
+ if (!mSelectedItemPairs.size()) return;
+
+ LLRect selected_rc = mSelectedItemPairs.front()->first->getRect();
+
+ if (selected_rc.isValid())
+ {
+ scrollToShowRect(selected_rc);
+ }
+}
+
LLRect LLFlatListView::getLastSelectedItemRect()
{
if (!mSelectedItemPairs.size())
@@ -1079,7 +1097,7 @@ void LLFlatListView::setNoItemsCommentVisible(bool visible) const
mNoItemsCommentTextbox->setRect(comment_rect);
*/
}
- mSelectedItemsBorder->setVisible(FALSE);
+ mSelectedItemsBorder->setVisible(!visible);
mNoItemsCommentTextbox->setVisible(visible);
}
}
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index 50d06fbc94..2c391fdf91 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -297,6 +297,7 @@ public:
bool updateValue(const LLSD& old_value, const LLSD& new_value);
+ void scrollToShowFirstSelectedItem();
void selectFirstItem ();
void selectLastItem ();
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 39a6855273..22d6f6ca52 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -451,6 +451,14 @@ void LLFloater::enableResizeCtrls(bool enable)
}
}
+void LLFloater::destroy()
+{
+ // LLFloaterReg should be synchronized with "dead" floater to avoid returning dead instance before
+ // it was deleted via LLMortician::updateClass(). See EXT-8458.
+ LLFloaterReg::removeInstance(mInstanceName, mKey);
+ die();
+}
+
// virtual
LLFloater::~LLFloater()
{
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 3ea035777c..42f422f91c 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -308,7 +308,7 @@ protected:
BOOL getAutoFocus() const { return mAutoFocus; }
LLDragHandle* getDragHandle() const { return mDragHandle; }
- void destroy() { die(); } // Don't call this directly. You probably want to call closeFloater()
+ void destroy(); // Don't call this directly. You probably want to call closeFloater()
virtual void onClickCloseBtn();
diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp
index 43c21e250c..55329f64e4 100644
--- a/indra/llui/lllocalcliprect.cpp
+++ b/indra/llui/lllocalcliprect.cpp
@@ -33,33 +33,8 @@
#include "lllocalcliprect.h"
#include "llfontgl.h"
-#include "llgl.h"
#include "llui.h"
-#include <stack>
-
-//---------------------------------------------------------------------------
-// LLScreenClipRect
-// implementation class in screen space
-//---------------------------------------------------------------------------
-class LLScreenClipRect
-{
-public:
- LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
- virtual ~LLScreenClipRect();
-
-private:
- static void pushClipRect(const LLRect& rect);
- static void popClipRect();
- static void updateScissorRegion();
-
-private:
- LLGLState mScissorState;
- BOOL mEnabled;
-
- static std::stack<LLRect> sClipRectStack;
-};
-
/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack;
@@ -131,16 +106,11 @@ void LLScreenClipRect::updateScissorRegion()
// LLLocalClipRect
//---------------------------------------------------------------------------
LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */)
-{
- LLRect screen(rect.mLeft + LLFontGL::sCurOrigin.mX,
- rect.mTop + LLFontGL::sCurOrigin.mY,
- rect.mRight + LLFontGL::sCurOrigin.mX,
- rect.mBottom + LLFontGL::sCurOrigin.mY);
- mScreenClipRect = new LLScreenClipRect(screen, enabled);
-}
+: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
+ rect.mTop + LLFontGL::sCurOrigin.mY,
+ rect.mRight + LLFontGL::sCurOrigin.mX,
+ rect.mBottom + LLFontGL::sCurOrigin.mY), enabled)
+{}
LLLocalClipRect::~LLLocalClipRect()
-{
- delete mScreenClipRect;
- mScreenClipRect = NULL;
-}
+{}
diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h
index cd0c55ca72..36413f1496 100644
--- a/indra/llui/lllocalcliprect.h
+++ b/indra/llui/lllocalcliprect.h
@@ -31,7 +31,9 @@
#ifndef LLLOCALCLIPRECT_H
#define LLLOCALCLIPRECT_H
+#include "llgl.h"
#include "llrect.h" // can't forward declare, it's templated
+#include <stack>
// Clip rendering to a specific rectangle using GL scissor
// Just create one of these on the stack:
@@ -39,15 +41,29 @@
// LLLocalClipRect(rect);
// draw();
// }
-class LLLocalClipRect
+class LLScreenClipRect
{
public:
- LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
- ~LLLocalClipRect();
+ LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLScreenClipRect();
+
+private:
+ static void pushClipRect(const LLRect& rect);
+ static void popClipRect();
+ static void updateScissorRegion();
private:
- // implementation class
- class LLScreenClipRect* mScreenClipRect;
+ LLGLState mScissorState;
+ BOOL mEnabled;
+
+ static std::stack<LLRect> sClipRectStack;
+};
+
+class LLLocalClipRect : public LLScreenClipRect
+{
+public:
+ LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ ~LLLocalClipRect();
};
#endif
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index b4a1bcb7c5..8610d79142 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -218,6 +218,12 @@ void LLMenuItemGL::setValue(const LLSD& value)
}
//virtual
+LLSD LLMenuItemGL::getValue() const
+{
+ return getLabel();
+}
+
+//virtual
BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
{
if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) )
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 7668f301ea..a484405eaa 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -95,6 +95,7 @@ public:
// LLUICtrl overrides
/*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ LLSD getValue() const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 9e272a0949..7fa3c2cf65 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -375,6 +375,7 @@ LLNotification::LLNotification(const LLSD& sd) :
LLSD LLNotification::asLLSD()
{
LLSD output;
+ output["id"] = mId;
output["name"] = mTemplatep->mName;
output["form"] = getForm()->asLLSD();
output["substitutions"] = mSubstitutions;
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 8bfada0e71..1cdd744a68 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -353,6 +353,8 @@ public:
}
};
+ LLNotificationResponderPtr getResponderPtr() { return mResponder; }
+
private:
LLUUID mId;
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index ed870d46d5..9158bc70f5 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -298,11 +298,11 @@ void LLResMgr::getIntegerString( std::string& output, S32 input ) const
{
if (fraction == remaining_count)
{
- fraction_string = llformat("%d%c", fraction, getThousandsSeparator());
+ fraction_string = llformat_to_utf8("%d%c", fraction, getThousandsSeparator());
}
else
{
- fraction_string = llformat("%3.3d%c", fraction, getThousandsSeparator());
+ fraction_string = llformat_to_utf8("%3.3d%c", fraction, getThousandsSeparator());
}
output = fraction_string + output;
}
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index b8f93b6a0e..d63f67b4c1 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -42,6 +42,8 @@ LLStyle::Params::Params()
: visible("visible", true),
drop_shadow("drop_shadow", LLFontGL::NO_SHADOW),
color("color", LLColor4::black),
+ readonly_color("readonly_color", LLColor4::black),
+ selected_color("selected_color", LLColor4::black),
font("font", LLFontGL::getFontMonospace()),
image("image"),
link_href("href")
@@ -49,12 +51,10 @@ LLStyle::Params::Params()
LLStyle::LLStyle(const LLStyle::Params& p)
-: mItalic(FALSE),
- mBold(FALSE),
- mUnderline(FALSE),
- mVisible(p.visible),
- mColor(p.color()),
- mReadOnlyColor(p.readonly_color()),
+: mVisible(p.visible),
+ mColor(p.color),
+ mReadOnlyColor(p.readonly_color),
+ mSelectedColor(p.selected_color),
mFont(p.font()),
mLink(p.link_href),
mDropShadow(p.drop_shadow),
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index 2067e8e8be..44d9da7a1e 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -47,7 +47,8 @@ public:
Optional<bool> visible;
Optional<LLFontGL::ShadowType> drop_shadow;
Optional<LLUIColor> color,
- readonly_color;
+ readonly_color,
+ selected_color;
Optional<const LLFontGL*> font;
Optional<LLUIImage*> image;
Optional<std::string> link_href;
@@ -55,11 +56,14 @@ public:
};
LLStyle(const Params& p = Params());
public:
- const LLColor4& getColor() const { return mColor; }
- void setColor(const LLColor4 &color) { mColor = color; }
+ const LLUIColor& getColor() const { return mColor; }
+ void setColor(const LLUIColor &color) { mColor = color; }
- const LLColor4& getReadOnlyColor() const { return mReadOnlyColor; }
- void setReadOnlyColor(const LLColor4& color) { mReadOnlyColor = color; }
+ const LLUIColor& getReadOnlyColor() const { return mReadOnlyColor; }
+ void setReadOnlyColor(const LLUIColor& color) { mReadOnlyColor = color; }
+
+ const LLUIColor& getSelectedColor() const { return mSelectedColor; }
+ void setSelectedColor(const LLUIColor& color) { mSelectedColor = color; }
BOOL isVisible() const;
void setVisible(BOOL is_visible);
@@ -79,41 +83,36 @@ public:
BOOL isImage() const { return mImagep.notNull(); }
- // inlined here to make it easier to compare to member data below. -MG
bool operator==(const LLStyle &rhs) const
{
return
mVisible == rhs.mVisible
&& mColor == rhs.mColor
&& mReadOnlyColor == rhs.mReadOnlyColor
+ && mSelectedColor == rhs.mSelectedColor
&& mFont == rhs.mFont
&& mLink == rhs.mLink
&& mImagep == rhs.mImagep
- && mItalic == rhs.mItalic
- && mBold == rhs.mBold
- && mUnderline == rhs.mUnderline
&& mDropShadow == rhs.mDropShadow;
}
bool operator!=(const LLStyle& rhs) const { return !(*this == rhs); }
public:
- BOOL mItalic;
- BOOL mBold;
- BOOL mUnderline;
LLFontGL::ShadowType mDropShadow;
protected:
~LLStyle() { }
private:
- BOOL mVisible;
- LLUIColor mColor;
- LLUIColor mReadOnlyColor;
- std::string mFontName;
- const LLFontGL* mFont; // cached for performance
- std::string mLink;
- LLUIImagePtr mImagep;
+ BOOL mVisible;
+ LLUIColor mColor;
+ LLUIColor mReadOnlyColor;
+ LLUIColor mSelectedColor;
+ std::string mFontName;
+ const LLFontGL* mFont;
+ std::string mLink;
+ LLUIImagePtr mImagep;
};
typedef LLPointer<LLStyle> LLStyleSP;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index ed03645944..a580345b6c 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -155,6 +155,8 @@ LLTextBase::Params::Params()
bg_readonly_color("bg_readonly_color"),
bg_writeable_color("bg_writeable_color"),
bg_focus_color("bg_focus_color"),
+ text_selected_color("text_selected_color"),
+ bg_selected_color("bg_selected_color"),
allow_scroll("allow_scroll", true),
plain_text("plain_text",false),
track_end("track_end", false),
@@ -167,11 +169,12 @@ LLTextBase::Params::Params()
font_shadow("font_shadow"),
wrap("wrap"),
use_ellipses("use_ellipses", false),
- allow_html("allow_html", false),
+ parse_urls("parse_urls", false),
parse_highlights("parse_highlights", false)
{
addSynonym(track_end, "track_bottom");
addSynonym(wrap, "word_wrap");
+ addSynonym(parse_urls, "allow_html");
}
@@ -190,6 +193,8 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mWriteableBgColor(p.bg_writeable_color),
mReadOnlyBgColor(p.bg_readonly_color),
mFocusBgColor(p.bg_focus_color),
+ mTextSelectedColor(p.text_selected_color),
+ mSelectedBGColor(p.bg_selected_color),
mReflowIndex(S32_MAX),
mCursorPos( 0 ),
mScrollNeeded(FALSE),
@@ -209,7 +214,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mPlainText ( p.plain_text ),
mWordWrap(p.wrap),
mUseEllipses( p.use_ellipses ),
- mParseHTML(p.allow_html),
+ mParseHTML(p.parse_urls),
mParseHighlights(p.parse_highlights),
mBGVisible(p.bg_visible),
mScroller(NULL),
@@ -269,9 +274,6 @@ void LLTextBase::initFromParams(const LLTextBase::Params& p)
{
mReadOnly = p.read_only;
}
-
- // HACK: text editors always need to be enabled so that we can scroll
- LLView::setEnabled(true);
}
bool LLTextBase::truncate()
@@ -301,11 +303,14 @@ bool LLTextBase::truncate()
const LLStyle::Params& LLTextBase::getDefaultStyleParams()
{
+ //FIXME: convert mDefaultStyle to a flyweight http://www.boost.org/doc/libs/1_40_0/libs/flyweight/doc/index.html
+ //and eliminate color member values
if (mStyleDirty)
{
mDefaultStyle
- .color(LLUIColor(&mFgColor))
+ .color(LLUIColor(&mFgColor)) // pass linked color instead of copy of mFGColor
.readonly_color(LLUIColor(&mReadOnlyFgColor))
+ .selected_color(LLUIColor(&mTextSelectedColor))
.font(mDefaultFont)
.drop_shadow(mFontShadow);
mStyleDirty = false;
@@ -403,7 +408,7 @@ void LLTextBase::drawSelectionBackground()
// Draw the selection box (we're using a box instead of reversing the colors on the selected text).
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- const LLColor4& color = mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get();
+ const LLColor4& color = mSelectedBGColor;
F32 alpha = hasFocus() ? 0.7f : 0.3f;
alpha *= getDrawContext().mAlpha;
LLColor4 selection_color(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], alpha);
@@ -443,7 +448,6 @@ void LLTextBase::drawCursor()
}
else
{
- //segmentp = mSegments.back();
return;
}
@@ -477,21 +481,8 @@ void LLTextBase::drawCursor()
{
LLColor4 text_color;
const LLFontGL* fontp;
- if (segmentp)
- {
text_color = segmentp->getColor();
fontp = segmentp->getStyle()->getFont();
- }
- else if (mReadOnly)
- {
- text_color = mReadOnlyFgColor.get();
- fontp = mDefaultFont;
- }
- else
- {
- text_color = mFgColor.get();
- fontp = mDefaultFont;
- }
fontp->render(text, mCursorPos, cursor_rect,
LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
LLFontGL::LEFT, mVAlign,
@@ -1021,22 +1012,25 @@ void LLTextBase::draw()
if (mBGVisible)
{
// clip background rect against extents, if we support scrolling
- LLLocalClipRect clip(doc_rect, mScroller != NULL);
-
+ LLRect bg_rect = mVisibleTextRect;
+ if (mScroller)
+ {
+ bg_rect.intersectWith(doc_rect);
+ }
LLColor4 bg_color = mReadOnly
? mReadOnlyBgColor.get()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
- gl_rect_2d(mVisibleTextRect, bg_color, TRUE);
+ gl_rect_2d(doc_rect, bg_color, TRUE);
}
// draw document view
LLUICtrl::draw();
{
- // only clip if we support scrolling (mScroller != NULL)
- LLLocalClipRect clip(doc_rect, mScroller != NULL);
+ // only clip if we support scrolling or have word wrap turned off
+ LLLocalClipRect clip(doc_rect, !getWordWrap() || mScroller != NULL);
drawSelectionBackground();
drawText();
drawCursor();
@@ -1504,6 +1498,7 @@ LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
+ //FIXME: avoid operator new somehow (without running into refcount problems)
segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index));
return it;
}
@@ -1651,7 +1646,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
}
else
{
- appendAndHighlightText(match.getLabel(), part, link_params);
+ appendAndHighlightText(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
// set the tooltip for the Url label
if (! match.getTooltip().empty())
@@ -1734,7 +1729,7 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s
insertStringNoUndo(getLength(), widget_wide_text, &segments);
}
-void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params)
+void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)
{
// Save old state
S32 selection_start = mSelectionStart;
@@ -1765,7 +1760,17 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
S32 cur_length = getLength();
LLStyleConstSP sp(new LLStyle(highlight_params));
- LLTextSegmentPtr segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this);
+ LLTextSegmentPtr segmentp;
+ if(underline_on_hover_only)
+ {
+ highlight_params.font.style("NORMAL");
+ LLStyleConstSP normal_sp(new LLStyle(highlight_params));
+ segmentp = new LLOnHoverChangeableTextSegment(sp, normal_sp, cur_length, cur_length + wide_text.size(), *this);
+ }
+ else
+ {
+ segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this);
+ }
segment_vec_t segments;
segments.push_back(segmentp);
insertStringNoUndo(cur_length, wide_text, &segments);
@@ -1780,7 +1785,17 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
S32 segment_start = old_length;
S32 segment_end = old_length + wide_text.size();
LLStyleConstSP sp(new LLStyle(style_params));
+ if (underline_on_hover_only)
+ {
+ LLStyle::Params normal_style_params(style_params);
+ normal_style_params.font.style("NORMAL");
+ LLStyleConstSP normal_sp(new LLStyle(normal_style_params));
+ segments.push_back(new LLOnHoverChangeableTextSegment(sp, normal_sp, segment_start, segment_end, *this ));
+ }
+ else
+ {
segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this ));
+ }
insertStringNoUndo(getLength(), wide_text, &segments);
}
@@ -1804,7 +1819,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
}
}
-void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params)
+void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)
{
if (new_text.empty()) return;
@@ -1816,7 +1831,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
if(pos!=start)
{
std::string str = std::string(new_text,start,pos-start);
- appendAndHighlightTextImpl(str,highlight_part, style_params);
+ appendAndHighlightTextImpl(str,highlight_part, style_params, underline_on_hover_only);
}
appendLineBreakSegment(style_params);
start = pos+1;
@@ -1824,7 +1839,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
}
std::string str = std::string(new_text,start,new_text.length()-start);
- appendAndHighlightTextImpl(str,highlight_part, style_params);
+ appendAndHighlightTextImpl(str,highlight_part, style_params, underline_on_hover_only);
}
@@ -2278,10 +2293,17 @@ void LLTextBase::updateRects()
// allow horizontal scrolling?
// if so, use entire width of text contents
// otherwise, stop at width of mVisibleTextRect
+ //FIXME: consider use of getWordWrap() instead
doc_rect.mRight = mScroller
? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
: mVisibleTextRect.getWidth();
+ if (!mScroller)
+ {
+ // push doc rect to top of text widget
+ doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop);
+ }
+
mDocumentView->setShape(doc_rect);
//update mVisibleTextRect *after* mDocumentView has been resized
@@ -2481,7 +2503,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
font->render(text, start,
rect,
- LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
+ mStyle->getSelectedColor().get(),
LLFontGL::LEFT, mEditor.mVAlign,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
@@ -2678,6 +2700,30 @@ void LLNormalTextSegment::dump() const
llendl;
}
+//
+// LLOnHoverChangeableTextSegment
+//
+
+LLOnHoverChangeableTextSegment::LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor ):
+ LLNormalTextSegment(normal_style, start, end, editor),
+ mHoveredStyle(style),
+ mNormalStyle(normal_style){}
+
+/*virtual*/
+F32 LLOnHoverChangeableTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+{
+ F32 result = LLNormalTextSegment::draw(start, end, selection_start, selection_end, draw_rect);
+ mStyle = mNormalStyle;
+ return result;
+}
+
+/*virtual*/
+BOOL LLOnHoverChangeableTextSegment::handleHover(S32 x, S32 y, MASK mask)
+{
+ mStyle = mHoveredStyle;
+ return LLNormalTextSegment::handleHover(x, y, mask);
+}
+
//
// LLInlineViewSegment
@@ -2786,9 +2832,9 @@ F32 LLLineBreakTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 se
}
LLImageTextSegment::LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor)
- :LLTextSegment(pos,pos+1)
- ,mStyle( style )
- ,mEditor(editor)
+: LLTextSegment(pos,pos+1),
+ mStyle( style ),
+ mEditor(editor)
{
}
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 4b0eeeb7d6..4b83d5effb 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -145,6 +145,21 @@ protected:
boost::signals2::connection mImageLoadedConnection;
};
+// Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment)
+class LLOnHoverChangeableTextSegment : public LLNormalTextSegment
+{
+public:
+ LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor );
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+protected:
+ // Style used for text when mouse pointer is over segment
+ LLStyleConstSP mHoveredStyle;
+ // Style used for text when mouse pointer is outside segment
+ LLStyleConstSP mNormalStyle;
+
+};
+
class LLIndexSegment : public LLTextSegment
{
public:
@@ -241,7 +256,9 @@ public:
text_readonly_color,
bg_readonly_color,
bg_writeable_color,
- bg_focus_color;
+ bg_focus_color,
+ text_selected_color,
+ bg_selected_color;
Optional<bool> bg_visible,
border_visible,
@@ -251,7 +268,7 @@ public:
plain_text,
wrap,
use_ellipses,
- allow_html,
+ parse_urls,
parse_highlights,
clip_partial;
@@ -441,7 +458,7 @@ protected:
S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted
S32 removeStringNoUndo(S32 pos, S32 length);
S32 overwriteCharNoUndo(S32 pos, llwchar wc);
- void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep);
+ void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, bool underline_on_hover_only = false);
// manage segments
@@ -484,7 +501,7 @@ protected:
void replaceUrlLabel(const std::string &url, const std::string &label);
void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
- void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params);
+ void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);
protected:
@@ -507,6 +524,8 @@ protected:
LLUIColor mWriteableBgColor;
LLUIColor mReadOnlyBgColor;
LLUIColor mFocusBgColor;
+ LLUIColor mTextSelectedColor;
+ LLUIColor mSelectedBGColor;
// cursor
S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index a1f5b5726b..686179b94e 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -119,6 +119,17 @@ BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)
return handled;
}
+void LLTextBox::setEnabled(BOOL enabled)
+{
+ // just treat enabled as read-only flag
+ bool read_only = !enabled;
+ if (read_only != mReadOnly)
+ {
+ LLTextBase::setReadOnly(read_only);
+ updateSegments();
+ }
+}
+
void LLTextBox::setText(const LLStringExplicit& text , const LLStyle::Params& input_params )
{
// does string argument insertion
diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h
index 3a045534d3..b2ccde94c6 100644
--- a/indra/llui/lltextbox.h
+++ b/indra/llui/lltextbox.h
@@ -58,6 +58,8 @@ public:
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ void setEnabled(BOOL enabled);
+
/*virtual*/ void setText( const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params() );
void setRightAlign() { mHAlign = LLFontGL::RIGHT; }
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 130cda3784..6781c23416 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -289,6 +289,9 @@ void LLTextEditor::initFromParams( const LLTextEditor::Params& p)
{
LLTextBase::initFromParams(p);
+ // HACK: text editors always need to be enabled so that we can scroll
+ LLView::setEnabled(true);
+
if (p.commit_on_focus_lost.isProvided())
{
mCommitOnFocusLost = p.commit_on_focus_lost;
diff --git a/indra/llui/lltextvalidate.cpp b/indra/llui/lltextvalidate.cpp
index 8b6bc5bd7d..53c4d21151 100644
--- a/indra/llui/lltextvalidate.cpp
+++ b/indra/llui/lltextvalidate.cpp
@@ -50,6 +50,7 @@ namespace LLTextValidate
declare("alpha_num_space", validateAlphaNumSpace);
declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe);
declare("ascii_printable_no_space", validateASCIIPrintableNoSpace);
+ declare("ascii_with_newline", validateASCIIWithNewLine);
}
// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
@@ -299,4 +300,21 @@ namespace LLTextValidate
}
return rv;
}
+
+ // Used for multiline text stored on the server.
+ // Example is landmark description in Places SP.
+ bool validateASCIIWithNewLine(const LLWString &str)
+ {
+ bool rv = TRUE;
+ S32 len = str.length();
+ while(len--)
+ {
+ if (str[len] < 0x20 && str[len] != 0xA || str[len] > 0x7f)
+ {
+ rv = FALSE;
+ break;
+ }
+ }
+ return rv;
+ }
}
diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h
index ffb4e85e7c..c033f5045b 100644
--- a/indra/llui/lltextvalidate.h
+++ b/indra/llui/lltextvalidate.h
@@ -57,6 +57,7 @@ namespace LLTextValidate
bool validateASCIIPrintableNoPipe(const LLWString &str);
bool validateASCIIPrintableNoSpace(const LLWString &str);
bool validateASCII(const LLWString &str);
+ bool validateASCIIWithNewLine(const LLWString &str);
}
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index ed7fd02e14..025725476e 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -186,7 +186,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
params.font = p.font;
params.use_ellipses = true;
params.wrap = p.wrap;
- params.allow_html = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips
+ params.parse_urls = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips
mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mTextBox);
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e075699a6e..17d211fb36 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -363,6 +363,12 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
return LLTrans::getString("TooltipAgentUrl");
}
+bool LLUrlEntryAgent::underlineOnHoverOnly(const std::string &string) const
+{
+ std::string url = getUrl(string);
+ return LLStringUtil::endsWith(url, "/about");
+}
+
std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
if (!gCacheName)
@@ -730,6 +736,19 @@ std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const
return LLUrlEntryBase::getTooltip(string);
}
+bool LLUrlEntrySLLabel::underlineOnHoverOnly(const std::string &string) const
+{
+ std::string url = getUrl(string);
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ return match.underlineOnHoverOnly();
+ }
+
+ // unrecognized URL? should not happen
+ return LLUrlEntryBase::underlineOnHoverOnly(string);
+}
+
//
// LLUrlEntryWorldMap Describes secondlife:///<location> URLs
//
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 7d718b67a9..f8588dd760 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -94,6 +94,9 @@ public:
/// is this a match for a URL that should not be hyperlinked?
bool isLinkDisabled() const { return mDisabledLink; }
+ /// Should this link text be underlined only when mouse is hovered over it?
+ virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
+
virtual LLUUID getID(const std::string &string) const { return LLUUID::null; }
protected:
@@ -173,6 +176,7 @@ public:
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getTooltip(const std::string &string) const;
/*virtual*/ LLUUID getID(const std::string &string) const;
+ /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
private:
void onAgentNameReceived(const LLUUID& id, const std::string& first,
const std::string& last, BOOL is_group);
@@ -275,6 +279,7 @@ public:
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
/*virtual*/ std::string getTooltip(const std::string &string) const;
+ /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
};
///
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index 7c96665ce4..a6d3dcb40f 100644
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -43,7 +43,8 @@ LLUrlMatch::LLUrlMatch() :
mIcon(""),
mMenuName(""),
mLocation(""),
- mDisabledLink(false)
+ mDisabledLink(false),
+ mUnderlineOnHoverOnly(false)
{
}
@@ -51,7 +52,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
const std::string &icon, const LLUIColor& color,
const std::string &menu, const std::string &location,
- bool disabled_link, const LLUUID& id)
+ bool disabled_link, const LLUUID& id, bool underline_on_hover_only)
{
mStart = start;
mEnd = end;
@@ -64,4 +65,5 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mLocation = location;
mDisabledLink = disabled_link;
mID = id;
+ mUnderlineOnHoverOnly = underline_on_hover_only;
}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index 78dd2c528f..7090dd3f93 100644
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -86,12 +86,15 @@ public:
/// is this a match for a URL that should not be hyperlinked?
bool isLinkDisabled() const { return mDisabledLink; }
+ /// Should this link text be underlined only when mouse is hovered over it?
+ bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
+
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
const LLUIColor& color, const std::string &menu,
const std::string &location, bool disabled_link
- , const LLUUID& id );
+ , const LLUUID& id, bool underline_on_hover_only = false );
const LLUUID& getID() const { return mID;}
@@ -108,6 +111,7 @@ private:
LLUUID mID;
LLUIColor mColor;
bool mDisabledLink;
+ bool mUnderlineOnHoverOnly;
};
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 1f86f72faa..b37a52cad2 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -184,7 +184,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getMenuName(),
match_entry->getLocation(url),
match_entry->isLinkDisabled(),
- match_entry->getID(url));
+ match_entry->getID(url),
+ match_entry->underlineOnHoverOnly(url));
return true;
}
@@ -219,7 +220,8 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
match.getMenuName(),
match.getLocation(),
match.isLinkDisabled(),
- match.getID());
+ match.getID(),
+ match.underlineOnHoverOnly());
return true;
}
return false;