summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorAndreyL ProductEngine <alihatskiy@productengine.com>2019-11-27 23:20:03 +0200
committerAndreyL ProductEngine <alihatskiy@productengine.com>2019-11-27 23:20:03 +0200
commit56056aa198fc31a14cb4320762033958e96558cc (patch)
treed274000fb53dc1234cff8cddd8b3d3b756bf3681 /indra/llui
parent78bdf57ad6610b34389226bf941ba736ca0c2225 (diff)
parent191c1791f4f83fee1be6e71aa9e3f246206b2e80 (diff)
Upstream merge from viewer-neko
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llfloater.cpp69
-rw-r--r--indra/llui/llfloater.h13
-rw-r--r--indra/llui/llmenugl.cpp48
-rw-r--r--indra/llui/llmenugl.h18
-rw-r--r--indra/llui/llnotifications.cpp17
-rw-r--r--indra/llui/llnotifications.h4
-rw-r--r--indra/llui/llscrollbar.cpp10
-rw-r--r--indra/llui/llscrollbar.h1
-rw-r--r--indra/llui/llscrollcontainer.cpp19
-rw-r--r--indra/llui/llscrollcontainer.h1
-rw-r--r--indra/llui/llscrolllistcell.cpp149
-rw-r--r--indra/llui/llscrolllistcell.h31
-rw-r--r--indra/llui/llscrolllistctrl.cpp191
-rw-r--r--indra/llui/llscrolllistctrl.h22
-rw-r--r--indra/llui/llscrolllistitem.cpp56
-rw-r--r--indra/llui/llscrolllistitem.h21
-rw-r--r--indra/llui/lltextbase.cpp1
-rw-r--r--indra/llui/lltextbase.h1
-rw-r--r--indra/llui/lluictrl.cpp37
-rw-r--r--indra/llui/lluictrlfactory.h4
-rw-r--r--indra/llui/llurlentry.cpp10
-rw-r--r--indra/llui/llview.cpp24
-rw-r--r--indra/llui/llview.h2
-rw-r--r--indra/llui/tests/llurlentry_test.cpp5
24 files changed, 677 insertions, 77 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 42802cd339..e3bb36192c 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -37,6 +37,7 @@
#include "lluictrlfactory.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
+#include "llcriticaldamp.h" // LLSmoothInterpolation
#include "lldir.h"
#include "lldraghandle.h"
#include "llfloaterreg.h"
@@ -64,6 +65,10 @@
// use this to control "jumping" behavior when Ctrl-Tabbing
const S32 TABBED_FLOATER_OFFSET = 0;
+const F32 LLFloater::CONTEXT_CONE_IN_ALPHA = 0.0f;
+const F32 LLFloater::CONTEXT_CONE_OUT_ALPHA = 1.f;
+const F32 LLFloater::CONTEXT_CONE_FADE_TIME = 0.08f;
+
namespace LLInitParam
{
void TypeValues<LLFloaterEnums::EOpenPositioning>::declareValues()
@@ -2116,6 +2121,70 @@ void LLFloater::updateTitleButtons()
}
}
+void LLFloater::drawConeToOwner(F32 &context_cone_opacity,
+ F32 max_cone_opacity,
+ LLView *owner_view,
+ F32 fade_time,
+ F32 contex_cone_in_alpha,
+ F32 contex_cone_out_alpha)
+{
+ if (owner_view
+ && owner_view->isInVisibleChain()
+ && hasFocus()
+ && context_cone_opacity > 0.001f
+ && gFocusMgr.childHasKeyboardFocus(this))
+ {
+ // draw cone of context pointing back to owner (e.x. texture swatch)
+ LLRect owner_rect;
+ owner_view->localRectToOtherView(owner_view->getLocalRect(), &owner_rect, this);
+ LLRect local_rect = getLocalRect();
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ LLGLEnable(GL_CULL_FACE);
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+ gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
+ gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+ gGL.vertex2i(local_rect.mRight, local_rect.mTop);
+ gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
+
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+ gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
+ gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+ gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
+ gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
+
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+ gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
+ gGL.vertex2i(local_rect.mRight, local_rect.mTop);
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+ gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
+ gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
+
+
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+ gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
+ gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
+ gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+ gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
+ gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
+ }
+ gGL.end();
+ }
+
+ if (gFocusMgr.childHasMouseCapture(getDragHandle()))
+ {
+ context_cone_opacity = lerp(context_cone_opacity, max_cone_opacity, LLSmoothInterpolation::getInterpolant(fade_time));
+ }
+ else
+ {
+ context_cone_opacity = lerp(context_cone_opacity, 0.f, LLSmoothInterpolation::getInterpolant(fade_time));
+ }
+}
+
void LLFloater::buildButtons(const Params& floater_params)
{
static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 165f67499b..f8c04e8a2f 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -395,6 +395,15 @@ protected:
virtual void updateTitleButtons();
+ // Draws a cone from this floater to parent floater or view (owner)
+ // Modifies context_cone_opacity (interpolates according to fade time and returns new value)
+ void drawConeToOwner(F32 &context_cone_opacity,
+ F32 max_cone_opacity,
+ LLView *owner_view,
+ F32 context_fade_time = CONTEXT_CONE_FADE_TIME,
+ F32 contex_cone_in_alpha = CONTEXT_CONE_IN_ALPHA,
+ F32 contex_cone_out_alpha = CONTEXT_CONE_OUT_ALPHA);
+
private:
void setForeground(BOOL b); // called only by floaterview
void cleanupHandles(); // remove handles to dead floaters
@@ -424,6 +433,10 @@ private:
void updateTransparency(LLView* view, ETypeTransparency transparency_type);
public:
+ static const F32 CONTEXT_CONE_IN_ALPHA;
+ static const F32 CONTEXT_CONE_OUT_ALPHA;
+ static const F32 CONTEXT_CONE_FADE_TIME;
+
// Called when floater is opened, passes mKey
// Public so external views or floaters can watch for this floater opening
commit_signal_t mOpenSignal;
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 200dd2fdca..1e18396184 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -213,6 +213,12 @@ LLSD LLMenuItemGL::getValue() const
}
//virtual
+bool LLMenuItemGL::hasAccelerator(const KEY &key, const MASK &mask) const
+{
+ return (mAcceleratorKey == key) && (mAcceleratorMask == mask);
+}
+
+//virtual
BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
{
if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) )
@@ -263,13 +269,13 @@ BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)
// This function checks to see if the accelerator key is already in use;
// if not, it will be added to the list
-BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
+BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp)
{
- LLKeyBinding *accelerator = NULL;
+ LLMenuKeyboardBinding *accelerator = NULL;
if (mAcceleratorKey != KEY_NONE)
{
- std::list<LLKeyBinding*>::iterator list_it;
+ std::list<LLMenuKeyboardBinding*>::iterator list_it;
for (list_it = listp->begin(); list_it != listp->end(); ++list_it)
{
accelerator = *list_it;
@@ -293,7 +299,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
}
if (!accelerator)
{
- accelerator = new LLKeyBinding;
+ accelerator = new LLMenuKeyboardBinding;
if (accelerator)
{
accelerator->mKey = mAcceleratorKey;
@@ -788,6 +794,12 @@ void LLMenuItemCallGL::initFromParams(const Params& p)
{
setEnabledControlVariable(control);
}
+ else
+ {
+ LL_WARNS() << "Failed to assign 'enabled' control variable to menu " << getName()
+ << ": control " << p.on_enable.control_name()
+ << " does not exist." << LL_ENDL;
+ }
}
}
if (p.on_click.isProvided())
@@ -1011,6 +1023,11 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask)
return TRUE;
}
+bool LLMenuItemBranchGL::hasAccelerator(const KEY &key, const MASK &mask) const
+{
+ return getBranch() && getBranch()->hasAccelerator(key, mask);
+}
+
BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
{
return getBranch() && getBranch()->handleAcceleratorKey(key, mask);
@@ -1018,7 +1035,7 @@ BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
// This function checks to see if the accelerator key is already in use;
// if not, it will be added to the list
-BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLKeyBinding*> *listp)
+BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp)
{
LLMenuGL* branch = getBranch();
if (!branch)
@@ -2995,6 +3012,27 @@ void LLMenuGL::updateParent(LLView* parentp)
}
}
+bool LLMenuGL::hasAccelerator(const KEY &key, const MASK &mask) const
+{
+ if (key == KEY_NONE)
+ {
+ return false;
+ }
+ // Note: checking this way because mAccelerators seems to be broken
+ // mAccelerators probably needs to be cleaned up or fixed
+ // It was used for dupplicate accelerator avoidance.
+ item_list_t::const_iterator item_iter;
+ for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
+ {
+ LLMenuItemGL* itemp = *item_iter;
+ if (itemp->hasAccelerator(key, mask))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask)
{
// don't handle if not enabled
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 78f688642e..f3844af507 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -42,6 +42,13 @@
extern S32 MENU_BAR_HEIGHT;
extern S32 MENU_BAR_WIDTH;
+class LLMenuKeyboardBinding
+{
+public:
+ KEY mKey;
+ MASK mMask;
+};
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemGL
//
@@ -91,6 +98,7 @@ public:
/*virtual*/ void setValue(const LLSD& value);
/*virtual*/ LLSD getValue() const;
+ virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); }
@@ -109,7 +117,7 @@ public:
virtual void setBriefItem(BOOL brief);
virtual BOOL isBriefItem() const;
- virtual BOOL addToAcceleratorList(std::list<LLKeyBinding*> *listp);
+ virtual BOOL addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp);
void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; }
BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; }
@@ -436,7 +444,8 @@ public:
/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
/*virtual*/ void removeChild( LLView* ctrl);
/*virtual*/ BOOL postBuild();
-
+
+ virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const;
@@ -625,10 +634,11 @@ public:
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
// check if we've used these accelerators already
- virtual BOOL addToAcceleratorList(std::list <LLKeyBinding*> *listp);
+ virtual BOOL addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp);
// called to rebuild the draw label
virtual void buildDrawLabel( void );
@@ -794,7 +804,7 @@ private:
void checkMenuTrigger();
- std::list <LLKeyBinding*> mAccelerators;
+ std::list <LLMenuKeyboardBinding*> mAccelerators;
BOOL mAltKeyTrigger;
};
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 9fc6c05ead..6a7075301b 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -68,7 +68,8 @@ LLNotificationForm::FormIgnore::FormIgnore()
control("control"),
invert_control("invert_control", false),
save_option("save_option", false),
- session_only("session_only", false)
+ session_only("session_only", false),
+ checkbox_only("checkbox_only", false)
{}
LLNotificationForm::FormButton::FormButton()
@@ -195,10 +196,15 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
{
if (p.ignore.isProvided())
{
+ // For all cases but IGNORE_CHECKBOX_ONLY this is name for use in preferences
mIgnoreMsg = p.ignore.text;
LLUI *ui_inst = LLUI::getInstance();
- if (!p.ignore.save_option)
+ if (p.ignore.checkbox_only)
+ {
+ mIgnore = IGNORE_CHECKBOX_ONLY;
+ }
+ else if (!p.ignore.save_option)
{
mIgnore = p.ignore.session_only ? IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY : IGNORE_WITH_DEFAULT_RESPONSE;
}
@@ -215,7 +221,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
mIgnoreSetting = ui_inst->mSettingGroups["config"]->getControl(p.ignore.control);
mInvertSetting = p.ignore.invert_control;
}
- else
+ else if (mIgnore > IGNORE_NO)
{
ui_inst->mSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", LLControlVariable::PERSIST_NONDFT);
mIgnoreSetting = ui_inst->mSettingGroups["ignores"]->getControl(name);
@@ -389,13 +395,12 @@ LLControlVariablePtr LLNotificationForm::getIgnoreSetting()
bool LLNotificationForm::getIgnored()
{
bool show = true;
- if (mIgnore != LLNotificationForm::IGNORE_NO
+ if (mIgnore > LLNotificationForm::IGNORE_NO
&& mIgnoreSetting)
{
show = mIgnoreSetting->getValue().asBoolean();
if (mInvertSetting) show = !show;
}
-
return !show;
}
@@ -696,7 +701,7 @@ void LLNotification::respond(const LLSD& response)
mTemporaryResponder = false;
}
- if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+ if (mForm->getIgnoreType() > LLNotificationForm::IGNORE_NO)
{
mForm->setIgnored(mIgnored);
if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 1509446920..62cf41256b 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -180,6 +180,7 @@ public:
Optional<std::string> control;
Optional<bool> invert_control;
Optional<bool> session_only;
+ Optional<bool> checkbox_only;
FormIgnore();
};
@@ -232,7 +233,8 @@ public:
typedef enum e_ignore_type
{
- IGNORE_NO,
+ IGNORE_CHECKBOX_ONLY = -1, // ignore won't be handled, will set value/checkbox only
+ IGNORE_NO = 0,
IGNORE_WITH_DEFAULT_RESPONSE,
IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY,
IGNORE_WITH_LAST_RESPONSE,
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index b3a79bc1eb..fde6de4921 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -408,6 +408,16 @@ BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks)
return handled;
}
+BOOL LLScrollbar::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+ BOOL handled = FALSE;
+ if (LLScrollbar::HORIZONTAL == mOrientation)
+ {
+ handled = changeLine(clicks * mStepSize, TRUE);
+ }
+ return handled;
+}
+
BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string &tooltip_msg)
{
diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index e2bf52c14b..5f2f490d81 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -88,6 +88,7 @@ public:
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string &tooltip_msg);
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 6135cc56ad..3db38bbfac 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -272,6 +272,25 @@ BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
return FALSE;
}
+BOOL LLScrollContainer::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+ if (LLUICtrl::handleScrollHWheel(x,y,clicks))
+ {
+ return TRUE;
+ }
+
+ LLScrollbar* horizontal = mScrollbar[HORIZONTAL];
+ if (horizontal->getVisible()
+ && horizontal->getEnabled()
+ && horizontal->handleScrollHWheel( 0, 0, clicks ) )
+ {
+ updateScroll();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h
index e6c7891397..c14099dbd5 100644
--- a/indra/llui/llscrollcontainer.h
+++ b/indra/llui/llscrollcontainer.h
@@ -107,6 +107,7 @@ public:
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+ virtual BOOL handleScrollHWheel( S32 x, S32 y, S32 clicks );
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index 8000efad0e..13839da400 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -50,6 +50,10 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_
{
cell = new LLScrollListDate(cell_p);
}
+ else if (cell_p.type() == "icontext")
+ {
+ cell = new LLScrollListIconText(cell_p);
+ }
else // default is "text"
{
cell = new LLScrollListText(cell_p);
@@ -168,7 +172,7 @@ U32 LLScrollListText::sCount = 0;
LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
: LLScrollListCell(p),
- mText(p.value().asString()),
+ mText(p.label.isProvided() ? p.label() : p.value().asString()),
mFont(p.font),
mColor(p.color),
mUseColor(p.color.isProvided()),
@@ -192,7 +196,7 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
void LLScrollListText::highlightText(S32 offset, S32 num_chars)
{
mHighlightOffset = offset;
- mHighlightCount = num_chars;
+ mHighlightCount = llmax(0, num_chars);
}
//virtual
@@ -292,11 +296,12 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
if (mHighlightCount > 0)
{
+ // Highlight text
S32 left = 0;
switch(mFontAlignment)
{
case LLFontGL::LEFT:
- left = mFont->getWidth(mText.getString(), 0, mHighlightOffset);
+ left = mFont->getWidth(mText.getString(), 1, mHighlightOffset);
break;
case LLFontGL::RIGHT:
left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
@@ -319,7 +324,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
switch(mFontAlignment)
{
case LLFontGL::LEFT:
- start_x = 0.f;
+ start_x = 1.f;
break;
case LLFontGL::RIGHT:
start_x = (F32)getWidth();
@@ -435,3 +440,139 @@ const LLSD LLScrollListDate::getValue() const
{
return mDate;
}
+
+//
+// LLScrollListIconText
+//
+LLScrollListIconText::LLScrollListIconText(const LLScrollListCell::Params& p)
+ : LLScrollListText(p),
+ mIcon(p.value().isUUID() ? LLUI::getUIImageByID(p.value().asUUID()) : LLUI::getUIImage(p.value().asString())),
+ mPad(4)
+{
+ mTextWidth = getWidth() - mPad /*padding*/ - mFont->getLineHeight();
+}
+
+LLScrollListIconText::~LLScrollListIconText()
+{
+}
+
+const LLSD LLScrollListIconText::getValue() const
+{
+ if (mIcon.isNull())
+ {
+ return LLStringUtil::null;
+ }
+ return mIcon->getName();
+}
+
+void LLScrollListIconText::setValue(const LLSD& value)
+{
+ if (value.isUUID())
+ {
+ // don't use default image specified by LLUUID::null, use no image in that case
+ LLUUID image_id = value.asUUID();
+ mIcon = image_id.notNull() ? LLUI::getUIImageByID(image_id) : LLUIImagePtr(NULL);
+ }
+ else
+ {
+ std::string value_string = value.asString();
+ if (LLUUID::validate(value_string))
+ {
+ setValue(LLUUID(value_string));
+ }
+ else if (!value_string.empty())
+ {
+ mIcon = LLUI::getUIImage(value.asString());
+ }
+ else
+ {
+ mIcon = NULL;
+ }
+ }
+}
+
+void LLScrollListIconText::setWidth(S32 width)
+{
+ LLScrollListCell::setWidth(width);
+ // Assume that iamge height and width is identical to font height and width
+ mTextWidth = width - mPad /*padding*/ - mFont->getLineHeight();
+}
+
+
+void LLScrollListIconText::draw(const LLColor4& color, const LLColor4& highlight_color) const
+{
+ LLColor4 display_color;
+ if (mUseColor)
+ {
+ display_color = mColor;
+ }
+ else
+ {
+ display_color = color;
+ }
+
+ S32 icon_height = mFont->getLineHeight();
+ S32 icon_space = mIcon ? (icon_height + mPad) : 0;
+
+ if (mHighlightCount > 0)
+ {
+ S32 left = 0;
+ switch (mFontAlignment)
+ {
+ case LLFontGL::LEFT:
+ left = mFont->getWidth(mText.getString(), icon_space + 1, mHighlightOffset);
+ break;
+ case LLFontGL::RIGHT:
+ left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX) - icon_space;
+ break;
+ case LLFontGL::HCENTER:
+ left = (getWidth() - mFont->getWidth(mText.getString()) - icon_space) / 2;
+ break;
+ }
+ LLRect highlight_rect(left - 2,
+ mFont->getLineHeight() + 1,
+ left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,
+ 1);
+ mRoundedRectImage->draw(highlight_rect, highlight_color);
+ }
+
+ // Try to draw the entire string
+ F32 right_x;
+ U32 string_chars = mText.length();
+ F32 start_text_x = 0.f;
+ S32 start_icon_x = 0;
+ switch (mFontAlignment)
+ {
+ case LLFontGL::LEFT:
+ start_text_x = icon_space + 1;
+ start_icon_x = 1;
+ break;
+ case LLFontGL::RIGHT:
+ start_text_x = (F32)getWidth();
+ start_icon_x = getWidth() - mFont->getWidth(mText.getString()) - icon_space;
+ break;
+ case LLFontGL::HCENTER:
+ F32 center = (F32)getWidth()* 0.5f;
+ start_text_x = center + ((F32)icon_space * 0.5f);
+ start_icon_x = center - (((F32)icon_space + mFont->getWidth(mText.getString())) * 0.5f);
+ break;
+ }
+ mFont->render(mText.getWString(), 0,
+ start_text_x, 0.f,
+ display_color,
+ mFontAlignment,
+ LLFontGL::BOTTOM,
+ 0,
+ LLFontGL::NO_SHADOW,
+ string_chars,
+ getTextWidth(),
+ &right_x,
+ TRUE);
+
+ if (mIcon)
+ {
+ mIcon->draw(start_icon_x, 0, icon_height, icon_height, mColor);
+ }
+}
+
+
diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h
index d625ebddcc..19576fb247 100644
--- a/indra/llui/llscrolllistcell.h
+++ b/indra/llui/llscrolllistcell.h
@@ -59,7 +59,8 @@ public:
visible;
Optional<void*> userdata;
- Optional<LLSD> value;
+ Optional<LLSD> value; // state of checkbox, icon id/name, date
+ Optional<std::string> label; // description or text
Optional<std::string> tool_tip;
Optional<const LLFontGL*> font;
@@ -75,6 +76,7 @@ public:
enabled("enabled", true),
visible("visible", true),
value("value"),
+ label("label"),
tool_tip("tool_tip", ""),
font("font", LLFontGL::getFontSansSerifSmall()),
font_color("font_color", LLColor4::black),
@@ -152,11 +154,12 @@ public:
void setText(const LLStringExplicit& text);
void setFontStyle(const U8 font_style);
-private:
+protected:
LLUIString mText;
S32 mTextWidth;
const LLFontGL* mFont;
LLColor4 mColor;
+ LLColor4 mHighlightColor;
U8 mUseColor;
LLFontGL::HAlign mFontAlignment;
BOOL mVisible;
@@ -169,7 +172,7 @@ private:
};
/*
- * Cell displaying an image.
+ * Cell displaying an image. AT the moment, this is specifically UI image
*/
class LLScrollListIcon : public LLScrollListCell
{
@@ -223,4 +226,26 @@ private:
LLDate mDate;
};
+/*
+* Cell displaying icon and text.
+*/
+
+class LLScrollListIconText : public LLScrollListText
+{
+public:
+ LLScrollListIconText(const LLScrollListCell::Params& p);
+ /*virtual*/ ~LLScrollListIconText();
+ /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const;
+ /*virtual*/ const LLSD getValue() const;
+ /*virtual*/ void setValue(const LLSD& value);
+
+
+ S32 getIconWidth() const;
+ /*virtual*/ void setWidth(S32 width);/* { LLScrollListCell::setWidth(width); mTextWidth = width - ; }*/
+
+private:
+ LLPointer<LLUIImage> mIcon;
+ S32 mPad;
+};
+
#endif
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index f4028057e8..94b130e28d 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -115,6 +115,13 @@ struct SortScrollListItem
// LLScrollListCtrl
//---------------------------------------------------------------------------
+void LLScrollListCtrl::SelectionTypeNames::declareValues()
+{
+ declare("row", LLScrollListCtrl::ROW);
+ declare("cell", LLScrollListCtrl::CELL);
+ declare("header", LLScrollListCtrl::HEADER);
+}
+
LLScrollListCtrl::Contents::Contents()
: columns("column"),
rows("row")
@@ -128,8 +135,10 @@ LLScrollListCtrl::Params::Params()
has_border("draw_border"),
draw_heading("draw_heading"),
search_column("search_column", 0),
+ selection_type("selection_type", ROW),
sort_column("sort_column", -1),
sort_ascending("sort_ascending", true),
+ can_sort("can_sort", true),
mouse_wheel_opaque("mouse_wheel_opaque", false),
commit_on_keyboard_movement("commit_on_keyboard_movement", true),
heading_height("heading_height"),
@@ -163,8 +172,10 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),
mCommitOnSelectionChange(false),
mSelectionChanged(false),
+ mSelectionType(p.selection_type),
mNeedsScroll(false),
mCanSelect(true),
+ mCanSort(p.can_sort),
mColumnsDirty(false),
mMaxItemCount(INT_MAX),
mBorderThickness( 2 ),
@@ -819,7 +830,15 @@ BOOL LLScrollListCtrl::selectFirstItem()
{
if (!itemp->getSelected())
{
- selectItem(itemp);
+ switch (mSelectionType)
+ {
+ case CELL:
+ selectItem(itemp, 0);
+ break;
+ case HEADER:
+ case ROW:
+ selectItem(itemp, -1);
+ }
}
success = TRUE;
mOriginalSelection = 0;
@@ -878,7 +897,8 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index )
{
if( itemp->getEnabled() )
{
- selectItem(itemp, FALSE);
+ // TODO: support range selection for cells
+ selectItem(itemp, -1, FALSE);
success = TRUE;
}
}
@@ -1004,10 +1024,14 @@ void LLScrollListCtrl::clearHighlightedItems()
void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index)
{
- if (mHighlightedItem != target_index)
- {
- mHighlightedItem = target_index;
- }
+ if (mHighlightedItem != target_index)
+ {
+ if (mHighlightedItem >= 0 && mHighlightedItem < mItemList.size())
+ {
+ mItemList[mHighlightedItem]->setHoverCell(-1);
+ }
+ mHighlightedItem = target_index;
+ }
}
S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids )
@@ -1022,7 +1046,8 @@ S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids )
{
if (item->getEnabled() && (item->getUUID() == (*iditr)))
{
- selectItem(item,FALSE);
+ // TODO: support multiple selection for cells
+ selectItem(item, -1, FALSE);
++count;
break;
}
@@ -1095,7 +1120,7 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
{
if (prev_item)
{
- selectItem(prev_item, !extend_selection);
+ selectItem(prev_item, cur_item->getSelectedCell(), !extend_selection);
}
else
{
@@ -1139,7 +1164,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
{
if (next_item)
{
- selectItem(next_item, !extend_selection);
+ selectItem(next_item, cur_item->getSelectedCell(), !extend_selection);
}
else
{
@@ -1210,7 +1235,7 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen
bool found = NULL != item;
if(found)
{
- selectItem(item);
+ selectItem(item, -1);
}
if (mCommitOnSelectionChange)
@@ -1278,7 +1303,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
if (select)
{
- selectItem(item);
+ selectItem(item, -1);
found = TRUE;
break;
}
@@ -1318,7 +1343,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
// find offset of matching text (might have leading whitespace)
S32 offset = item_label.find(target_trimmed);
cellp->highlightText(offset, target_trimmed.size());
- selectItem(item);
+ selectItem(item, -1);
found = TRUE;
break;
}
@@ -1384,7 +1409,7 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected)
{
if (selected)
{
- selectItem(item);
+ selectItem(item, -1);
}
else
{
@@ -1464,7 +1489,7 @@ void LLScrollListCtrl::drawItems()
S32 max_columns = 0;
- LLColor4 highlight_color = LLColor4::white;
+ LLColor4 highlight_color = LLColor4::white; // ex: text inside cells
static LLUICachedControl<F32> type_ahead_timeout ("TypeAheadTimeout", 0);
highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout(), 0.4f, 0.f);
@@ -1490,7 +1515,8 @@ void LLScrollListCtrl::drawItems()
max_columns = llmax(max_columns, item->getNumColumns());
LLColor4 fg_color;
- LLColor4 bg_color(LLColor4::transparent);
+ LLColor4 hover_color(LLColor4::transparent);
+ LLColor4 select_color(LLColor4::transparent);
if( mScrollLines <= line && line < mScrollLines + num_page_lines )
{
@@ -1499,44 +1525,44 @@ void LLScrollListCtrl::drawItems()
{
if(item->getHighlighted()) // if it's highlighted, average the colors
{
- bg_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
+ select_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
}
else // otherwise just select-highlight it
{
- bg_color = mBgSelectedColor.get();
+ select_color = mBgSelectedColor.get();
}
fg_color = (item->getEnabled() ? mFgSelectedColor.get() : mFgDisabledColor.get());
}
- else if (mHighlightedItem == line && mCanSelect)
+ if (mHighlightedItem == line && mCanSelect)
{
if(item->getHighlighted()) // if it's highlighted, average the colors
{
- bg_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
+ hover_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
}
else // otherwise just hover-highlight it
{
- bg_color = mHoveredColor.get();
+ hover_color = mHoveredColor.get();
}
}
else if (item->getHighlighted())
{
- bg_color = mHighlightedColor.get();
+ hover_color = mHighlightedColor.get();
}
else
{
if (mDrawStripes && (line % 2 == 0) && (max_columns > 1))
{
- bg_color = mBgStripeColor.get();
+ hover_color = mBgStripeColor.get();
}
}
if (!item->getEnabled())
{
- bg_color = mBgReadOnlyColor.get();
+ hover_color = mBgReadOnlyColor.get();
}
- item->draw(item_rect, fg_color % alpha, bg_color% alpha, highlight_color % alpha, mColumnPadding);
+ item->draw(item_rect, fg_color % alpha, hover_color% alpha, select_color% alpha, highlight_color % alpha, mColumnPadding);
cur_y -= mLineHeight;
}
@@ -1601,6 +1627,20 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
return handled;
}
+BOOL LLScrollListCtrl::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+ BOOL handled = FALSE;
+ // Pretend the mouse is over the scrollbar
+ handled = mScrollbar->handleScrollHWheel( 0, 0, clicks );
+
+ if (mMouseWheelOpaque)
+ {
+ return TRUE;
+ }
+
+ return handled;
+}
+
// *NOTE: Requires a valid row_index and column_index
LLRect LLScrollListCtrl::getCellRect(S32 row_index, S32 column_index)
{
@@ -1674,7 +1714,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if (mLastSelected == NULL)
{
- selectItem(hit_item);
+ selectItem(hit_item, getColumnIndexFromOffset(x));
}
else
{
@@ -1698,7 +1738,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
LLScrollListItem *item = *itor;
if (item == hit_item || item == lastSelected)
{
- selectItem(item, FALSE);
+ selectItem(item, getColumnIndexFromOffset(x), FALSE);
selecting = !selecting;
if (hit_item == lastSelected)
{
@@ -1708,7 +1748,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
}
if (selecting)
{
- selectItem(item, FALSE);
+ selectItem(item, getColumnIndexFromOffset(x), FALSE);
}
}
}
@@ -1723,7 +1763,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable))
{
- selectItem(hit_item, FALSE);
+ selectItem(hit_item, getColumnIndexFromOffset(x), FALSE);
}
else
{
@@ -1737,12 +1777,12 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
else
{
deselectAllItems(TRUE);
- selectItem(hit_item);
+ selectItem(hit_item, getColumnIndexFromOffset(x));
}
}
else
{
- selectItem(hit_item);
+ selectItem(hit_item, getColumnIndexFromOffset(x));
}
selection_changed = mSelectionChanged;
@@ -2110,8 +2150,29 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
{
LLScrollListItem* item = hitItem(x, y);
if (item)
- {
- mouseOverHighlightNthItem(getItemIndex(item));
+ {
+ mouseOverHighlightNthItem(getItemIndex(item));
+ switch (mSelectionType)
+ {
+ case CELL:
+ item->setHoverCell(getColumnIndexFromOffset(x));
+ break;
+ case HEADER:
+ {
+ S32 cell = getColumnIndexFromOffset(x);
+ if (cell > 0)
+ {
+ item->setHoverCell(cell);
+ }
+ else
+ {
+ item->setHoverCell(-1);
+ }
+ break;
+ }
+ case ROW:
+ break;
+ }
}
else
{
@@ -2159,6 +2220,52 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask )
handled = TRUE;
}
break;
+ case KEY_LEFT:
+ if (mAllowKeyboardMovement || hasFocus())
+ {
+ // TODO: support multi-select
+ LLScrollListItem *item = getFirstSelected();
+ S32 cell = item->getSelectedCell();
+ switch (mSelectionType)
+ {
+ case CELL:
+ if (cell < mColumns.size()) cell++;
+ break;
+ case HEADER:
+ if (cell == -1) cell = 1;
+ else if (cell > 1 && cell < mColumns.size()) cell++; // skip header
+ break;
+ case ROW:
+ cell = -1;
+ break;
+ }
+ item->setSelectedCell(cell);
+ handled = TRUE;
+ }
+ break;
+ case KEY_RIGHT:
+ if (mAllowKeyboardMovement || hasFocus())
+ {
+ // TODO: support multi-select
+ LLScrollListItem *item = getFirstSelected();
+ S32 cell = item->getSelectedCell();
+ switch (mSelectionType)
+ {
+ case CELL:
+ if (cell >= 0) cell--;
+ break;
+ case HEADER:
+ if (cell > 1) cell--;
+ else if (cell == 1) cell = -1; // skip header
+ break;
+ case ROW:
+ cell = -1;
+ break;
+ }
+ item->setSelectedCell(cell);
+ handled = TRUE;
+ }
+ break;
case KEY_PAGE_UP:
if (mAllowKeyboardMovement || hasFocus())
{
@@ -2327,7 +2434,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char)
LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)
{
- selectItem(item);
+ selectItem(item, -1);
mNeedsScroll = true;
cellp->highlightText(0, 1);
mSearchTimer.reset();
@@ -2379,7 +2486,7 @@ BOOL LLScrollListCtrl::isRepeatedChars(const LLWString& string) const
return TRUE;
}
-void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_item)
+void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, S32 cell, BOOL select_single_item)
{
if (!itemp) return;
@@ -2398,6 +2505,18 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it
deselectAllItems(TRUE);
}
itemp->setSelected(TRUE);
+ switch (mSelectionType)
+ {
+ case CELL:
+ itemp->setSelectedCell(cell);
+ break;
+ case HEADER:
+ itemp->setSelectedCell(cell <= 0 ? -1 : cell);
+ break;
+ case ROW:
+ itemp->setSelectedCell(-1);
+ break;
+ }
mLastSelected = itemp;
mSelectionChanged = true;
}
@@ -2658,7 +2777,7 @@ void LLScrollListCtrl::selectAll()
LLScrollListItem *itemp = *iter;
if( itemp->getEnabled() )
{
- selectItem(itemp, FALSE);
+ selectItem(itemp, -1, FALSE);
}
}
@@ -2787,6 +2906,8 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
LLScrollListCtrl *parent = info->mParentCtrl;
if (!parent) return;
+ if (!parent->mCanSort) return;
+
S32 column_index = info->mIndex;
LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index b35a8608e7..bf1055c8dc 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -54,6 +54,18 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
public LLCtrlListInterface, public LLCtrlScrollInterface
{
public:
+ typedef enum e_selection_type
+ {
+ ROW, // default
+ CELL, // does not support multi-selection
+ HEADER, // when pointing to cells in column 0 will highlight whole row, otherwise cell, no multi-select
+ } ESelectionType;
+
+ struct SelectionTypeNames : public LLInitParam::TypeValuesHelper<LLScrollListCtrl::ESelectionType, SelectionTypeNames>
+ {
+ static void declareValues();
+ };
+
struct Contents : public LLInitParam::Block<Contents>
{
Multiple<LLScrollListColumn::Params> columns;
@@ -99,6 +111,8 @@ public:
commit_on_keyboard_movement,
mouse_wheel_opaque;
+ Optional<ESelectionType, SelectionTypeNames> selection_type;
+
// display flags
Optional<bool> has_border,
draw_heading,
@@ -114,7 +128,8 @@ public:
// sort and search behavior
Optional<S32> search_column,
sort_column;
- Optional<bool> sort_ascending;
+ Optional<bool> sort_ascending,
+ can_sort; // whether user is allowed to sort
// colors
Optional<LLUIColor> fg_unselected_color,
@@ -317,6 +332,7 @@ public:
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
/*virtual*/ void setEnabled(BOOL enabled);
/*virtual*/ void setFocus( BOOL b );
@@ -428,7 +444,7 @@ private:
void updateLineHeightInsert(LLScrollListItem* item);
void reportInvalidInput();
BOOL isRepeatedChars(const LLWString& string) const;
- void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
+ void selectItem(LLScrollListItem* itemp, S32 cell, BOOL single_select = TRUE);
void deselectItem(LLScrollListItem* itemp);
void commitIfChanged();
BOOL setSort(S32 column, BOOL ascending);
@@ -453,9 +469,11 @@ private:
bool mCommitOnKeyboardMovement;
bool mCommitOnSelectionChange;
bool mSelectionChanged;
+ ESelectionType mSelectionType;
bool mNeedsScroll;
bool mMouseWheelOpaque;
bool mCanSelect;
+ bool mCanSort; // Whether user is allowed to sort
bool mDisplayColumnHeaders;
bool mColumnsDirty;
bool mColumnWidthsDirty;
diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp
index df22c88afb..51c615dd00 100644
--- a/indra/llui/llscrolllistitem.cpp
+++ b/indra/llui/llscrolllistitem.cpp
@@ -40,6 +40,8 @@
LLScrollListItem::LLScrollListItem( const Params& p )
: mSelected(FALSE),
mHighlighted(FALSE),
+ mHoverIndex(-1),
+ mSelectedIndex(-1),
mEnabled(p.enabled),
mUserdata(p.userdata),
mItemValue(p.value)
@@ -53,6 +55,28 @@ LLScrollListItem::~LLScrollListItem()
mColumns.clear();
}
+void LLScrollListItem::setSelected(BOOL b)
+{
+ mSelected = b;
+ mSelectedIndex = -1;
+}
+
+void LLScrollListItem::setHighlighted(BOOL b)
+{
+ mHighlighted = b;
+ mHoverIndex = -1;
+}
+
+void LLScrollListItem::setHoverCell(S32 cell)
+{
+ mHoverIndex = cell;
+}
+
+void LLScrollListItem::setSelectedCell(S32 cell)
+{
+ mSelectedIndex = cell;
+}
+
void LLScrollListItem::addColumn(const LLScrollListCell::Params& p)
{
mColumns.push_back(LLScrollListCell::create(p));
@@ -120,12 +144,21 @@ std::string LLScrollListItem::getContentsCSV() const
}
-void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
+void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& hover_color, const LLColor4& select_color, const LLColor4& highlight_color, S32 column_padding)
{
// draw background rect
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLRect bg_rect = rect;
- gl_rect_2d( bg_rect, bg_color );
+ if (mSelectedIndex < 0 && getSelected())
+ {
+ // Whole item is highlighted/selected
+ gl_rect_2d(bg_rect, select_color);
+ }
+ else if (mHoverIndex < 0)
+ {
+ // Whole item is highlighted/selected
+ gl_rect_2d(bg_rect, hover_color);
+ }
S32 cur_x = rect.mLeft;
S32 num_cols = getNumColumns();
@@ -141,6 +174,25 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const
{
LLUI::translate((F32) cur_x, (F32) rect.mBottom);
+ if (mSelectedIndex == cur_col)
+ {
+ // select specific cell
+ LLRect highlight_rect(0,
+ cell->getHeight(),
+ cell->getWidth(),
+ 0);
+ gl_rect_2d(highlight_rect, select_color);
+ }
+ else if (mHoverIndex == cur_col)
+ {
+ // highlight specific cell
+ LLRect highlight_rect(0,
+ cell->getHeight(),
+ cell->getWidth() ,
+ 0);
+ gl_rect_2d(highlight_rect, hover_color);
+ }
+
cell->draw( fg_color, highlight_color );
}
LLUI::popMatrix();
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
index 13655b5873..d2c3dd7721 100644
--- a/indra/llui/llscrolllistitem.h
+++ b/indra/llui/llscrolllistitem.h
@@ -77,15 +77,21 @@ public:
virtual ~LLScrollListItem();
- void setSelected( BOOL b ) { mSelected = b; }
+ void setSelected( BOOL b );
BOOL getSelected() const { return mSelected; }
void setEnabled( BOOL b ) { mEnabled = b; }
BOOL getEnabled() const { return mEnabled; }
- void setHighlighted( BOOL b ) { mHighlighted = b; }
+ void setHighlighted( BOOL b );
BOOL getHighlighted() const { return mHighlighted; }
+ void setSelectedCell( S32 cell );
+ S32 getSelectedCell() const { return mSelectedIndex; }
+
+ void setHoverCell( S32 cell );
+ S32 getHoverCell() const { return mHoverIndex; }
+
void setUserdata( void* userdata ) { mUserdata = userdata; }
void* getUserdata() const { return mUserdata; }
@@ -107,14 +113,21 @@ public:
std::string getContentsCSV() const;
- virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
+ virtual void draw(const LLRect& rect,
+ const LLColor4& fg_color,
+ const LLColor4& hover_color, // highlight/hover selection of whole item or cell
+ const LLColor4& select_color, // highlight/hover selection of whole item or cell
+ const LLColor4& highlight_color, // highlights contents of cells (ex: text)
+ S32 column_padding);
protected:
LLScrollListItem( const Params& );
private:
BOOL mSelected;
- BOOL mHighlighted;
+ BOOL mHighlighted;
+ S32 mHoverIndex;
+ S32 mSelectedIndex;
BOOL mEnabled;
void* mUserdata;
LLSD mItemValue;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 22635f734e..e64078828b 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -3113,6 +3113,7 @@ BOOL LLTextSegment::handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE;
BOOL LLTextSegment::handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }
BOOL LLTextSegment::handleHover(S32 x, S32 y, MASK mask) { return FALSE; }
BOOL LLTextSegment::handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }
+BOOL LLTextSegment::handleScrollHWheel(S32 x, S32 y, S32 clicks) { return FALSE; }
BOOL LLTextSegment::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; }
const std::string& LLTextSegment::getName() const
{
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 9831c35858..4239cdf43c 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -103,6 +103,7 @@ public:
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
/*virtual*/ const std::string& getName() const;
/*virtual*/ void onMouseCaptureLost();
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index df74e113e9..c98da0d410 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -137,13 +137,29 @@ void LLUICtrl::initFromParams(const Params& p)
{
LLControlVariable* control = findControl(p.enabled_controls.enabled);
if (control)
+ {
setEnabledControlVariable(control);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to assign 'enabled' control variable to " << getName()
+ << ": control " << p.enabled_controls.enabled()
+ << " does not exist." << LL_ENDL;
+ }
}
else if(p.enabled_controls.disabled.isChosen())
{
LLControlVariable* control = findControl(p.enabled_controls.disabled);
if (control)
+ {
setDisabledControlVariable(control);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to assign 'disabled' control variable to " << getName()
+ << ": control " << p.enabled_controls.disabled()
+ << " does not exist." << LL_ENDL;
+ }
}
}
if(p.controls_visibility.isProvided())
@@ -152,13 +168,29 @@ void LLUICtrl::initFromParams(const Params& p)
{
LLControlVariable* control = findControl(p.controls_visibility.visible);
if (control)
+ {
setMakeVisibleControlVariable(control);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to assign visibility control variable to " << getName()
+ << ": control " << p.controls_visibility.visible()
+ << " does not exist." << LL_ENDL;
+ }
}
else if (p.controls_visibility.invisible.isChosen())
{
LLControlVariable* control = findControl(p.controls_visibility.invisible);
if (control)
+ {
setMakeInvisibleControlVariable(control);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to assign invisibility control variable to " << getName()
+ << ": control " << p.controls_visibility.invisible()
+ << " does not exist." << LL_ENDL;
+ }
}
}
@@ -497,6 +529,11 @@ void LLUICtrl::setControlName(const std::string& control_name, LLView *context)
if (!control_name.empty())
{
LLControlVariable* control = context->findControl(control_name);
+ if (!control)
+ {
+ LL_WARNS() << "Failed to assign control variable to " << getName()
+ << ": control "<< control_name << " does not exist." << LL_ENDL;
+ }
setControlVariable(control);
}
}
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 03d946f1b7..f740f14e4d 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -160,8 +160,8 @@ public:
LLXMLNodePtr root_node;
if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
- {
- LL_WARNS() << "Couldn't parse XUI file: " << instance().getCurFileName() << LL_ENDL;
+ {
+ LL_WARNS() << "Couldn't parse XUI from path: " << instance().getCurFileName() << ", from filename: " << filename << LL_ENDL;
goto fail;
}
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 63ed427ab5..333d03f208 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -454,13 +454,13 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
}
//
-// LLUrlEntrySeconlifeURL Describes *secondlife.com/ and *lindenlab.com/ urls to substitute icon 'hand.png' before link
+// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link
//
LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()
{
- mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com)"
+ mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com)"
"|"
- "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?))"
+ "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?))"
"\\/\\S*",
boost::regex::perl|boost::regex::icase);
@@ -495,11 +495,11 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const
}
//
-// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com and *lindenlab.com urls to substitute icon 'hand.png' before link
+// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com and *tilia-inc.com urls to substitute icon 'hand.png' before link
//
LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL()
{
- mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)",
+ mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)",
boost::regex::perl|boost::regex::icase);
mIcon = "Hand";
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 2a190365b3..771d32d2fc 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -875,10 +875,16 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
F32 timeout = LLToolTipMgr::instance().toolTipVisible()
? LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipFastDelay" )
: LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipDelay" );
- LLToolTipMgr::instance().show(LLToolTip::Params()
- .message(tooltip)
- .sticky_rect(calcScreenRect())
- .delay_time(timeout));
+
+ // Even if we don't show tooltips, consume the event, nothing below should show tooltip
+ bool allow_ui_tooltips = LLUI::sSettingGroups["config"]->getBOOL( "BasicUITooltips" );
+ if (allow_ui_tooltips)
+ {
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(tooltip)
+ .sticky_rect(calcScreenRect())
+ .delay_time(timeout));
+ }
handled = TRUE;
}
@@ -1054,6 +1060,11 @@ BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
return childrenHandleScrollWheel( x, y, clicks ) != NULL;
}
+BOOL LLView::handleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+ return childrenHandleScrollHWheel( x, y, clicks ) != NULL;
+}
+
BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
return childrenHandleRightMouseDown( x, y, mask ) != NULL;
@@ -1079,6 +1090,11 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
return childrenHandleMouseEvent(&LLView::handleScrollWheel, x, y, clicks, false);
}
+LLView* LLView::childrenHandleScrollHWheel(S32 x, S32 y, S32 clicks)
+{
+ return childrenHandleMouseEvent(&LLView::handleScrollHWheel, x, y, clicks, false);
+}
+
// Called during downward traversal
LLView* LLView::childrenHandleKey(KEY key, MASK mask)
{
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index e36ca7c8c6..db81900aaf 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -426,6 +426,7 @@ public:
/*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
@@ -556,6 +557,7 @@ protected:
LLView* childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask);
LLView* childrenHandleDoubleClick(S32 x, S32 y, MASK mask);
LLView* childrenHandleScrollWheel(S32 x, S32 y, S32 clicks);
+ LLView* childrenHandleScrollHWheel(S32 x, S32 y, S32 clicks);
LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask);
LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask);
LLView* childrenHandleToolTip(S32 x, S32 y, MASK mask);
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 119cbebc81..3c34fd269e 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -36,6 +36,11 @@
#include <boost/regex.hpp>
+#if LL_WINDOWS
+// because something pulls in window and lldxdiag dependencies which in turn need wbemuuid.lib
+ #pragma comment(lib, "wbemuuid.lib")
+#endif
+
// namespace LLExperienceCache
// {