summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llaccordionctrltab.cpp2
-rw-r--r--indra/llui/llbutton.cpp3
-rw-r--r--indra/llui/lldockablefloater.cpp17
-rw-r--r--indra/llui/lldockablefloater.h4
-rw-r--r--indra/llui/lldockcontrol.cpp62
-rw-r--r--indra/llui/lldockcontrol.h4
-rw-r--r--indra/llui/llfloater.cpp111
-rw-r--r--indra/llui/llfloater.h15
-rw-r--r--indra/llui/llhandle.h67
-rw-r--r--indra/llui/llkeywords.cpp81
-rw-r--r--indra/llui/llkeywords.h33
-rw-r--r--indra/llui/llmenugl.cpp5
-rw-r--r--indra/llui/llmenugl.h6
-rw-r--r--indra/llui/llnotifications.cpp2
-rw-r--r--indra/llui/llpanel.cpp2
-rw-r--r--indra/llui/llpanel.h3
-rw-r--r--indra/llui/llscrolllistctrl.cpp8
-rw-r--r--indra/llui/llscrolllistctrl.h2
-rw-r--r--indra/llui/llsdparam.cpp2
-rw-r--r--indra/llui/llsdparam.h7
-rw-r--r--indra/llui/llspinctrl.h3
-rw-r--r--indra/llui/lltabcontainer.cpp185
-rw-r--r--indra/llui/lltabcontainer.h6
-rw-r--r--indra/llui/lltextbase.cpp6
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/llui/lltextparser.cpp2
-rw-r--r--indra/llui/lltoolbar.cpp175
-rw-r--r--indra/llui/lltoolbar.h102
-rw-r--r--indra/llui/llui.cpp39
-rw-r--r--indra/llui/lluictrl.cpp11
-rw-r--r--indra/llui/lluictrl.h3
-rw-r--r--indra/llui/llurlaction.cpp28
-rw-r--r--indra/llui/llurlaction.h21
-rw-r--r--indra/llui/llview.cpp8
-rw-r--r--indra/llui/llview.h11
-rw-r--r--indra/llui/tests/llurlentry_stub.cpp3
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp5
37 files changed, 668 insertions, 378 deletions
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 4b0b7c561d..7a5f9f9fd6 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -973,7 +973,7 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)
if ( root_rect.overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect))
{
- glMatrixMode(GL_MODELVIEW);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
{
LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom, 0.f);
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 74b8885e1f..93d8282aa7 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -115,7 +115,7 @@ LLButton::Params::Params()
LLButton::LLButton(const LLButton::Params& p)
: LLUICtrl(p),
- LLBadgeOwner(LLView::getHandle()),
+ LLBadgeOwner(getHandle()),
mMouseDownFrame(0),
mMouseHeldDownCount(0),
mBorderEnabled( FALSE ),
@@ -1234,7 +1234,6 @@ void LLButton::resetMouseDownTimer()
mMouseDownTimer.reset();
}
-
BOOL LLButton::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// just treat a double click as a second click
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index aea58be12a..3396213f1c 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -82,7 +82,7 @@ BOOL LLDockableFloater::postBuild()
mForceDocking = true;
}
- mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
+ mDockTongue = LLUI::getUIImage("Flyout_Pointer");
LLFloater::setDocked(true);
return LLView::postBuild();
}
@@ -239,8 +239,21 @@ void LLDockableFloater::setDockControl(LLDockControl* dockControl)
setDocked(isDocked());
}
-const LLUIImagePtr& LLDockableFloater::getDockTongue()
+const LLUIImagePtr& LLDockableFloater::getDockTongue(LLDockControl::DocAt dock_side)
{
+ switch(dock_side)
+ {
+ case LLDockControl::LEFT:
+ mDockTongue = LLUI::getUIImage("Flyout_Left");
+ break;
+ case LLDockControl::RIGHT:
+ mDockTongue = LLUI::getUIImage("Flyout_Right");
+ break;
+ default:
+ mDockTongue = LLUI::getUIImage("Flyout_Pointer");
+ break;
+ }
+
return mDockTongue;
}
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 8deb6c1159..89c9852f4a 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -113,6 +113,8 @@ public:
bool getUniqueDocking() { return mUniqueDocking; }
bool getUseTongue() { return mUseTongue; }
+
+ void setUseTongue(bool use_tongue) { mUseTongue = use_tongue;}
private:
/**
* Provides unique of dockable floater.
@@ -122,7 +124,7 @@ private:
protected:
void setDockControl(LLDockControl* dockControl);
- const LLUIImagePtr& getDockTongue();
+ const LLUIImagePtr& getDockTongue(LLDockControl::DocAt dock_side = LLDockControl::TOP);
// Checks if docking should be forced.
// It may be useful e.g. if floater created in mouselook mode (see EXT-5609)
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
index 6397bbd0de..af39e41fa6 100644
--- a/indra/llui/lldockcontrol.cpp
+++ b/indra/llui/lldockcontrol.cpp
@@ -100,12 +100,16 @@ void LLDockControl::repositionDockable()
if (!mDockWidget) return;
LLRect dockRect = mDockWidget->calcScreenRect();
LLRect rootRect;
+ LLRect floater_rect = mDockableFloater->calcScreenRect();
mGetAllowedRectCallback(rootRect);
- // recalculate dockable position if dock position changed, dock visibility changed,
- // root view rect changed or recalculation is forced
- if (mPrevDockRect != dockRect || mDockWidgetVisible != isDockVisible()
- || mRootRect != rootRect || mRecalculateDocablePosition)
+ // recalculate dockable position if:
+ if (mPrevDockRect != dockRect //dock position changed
+ || mDockWidgetVisible != isDockVisible() //dock visibility changed
+ || mRootRect != rootRect //root view rect changed
+ || mFloaterRect != floater_rect //floater rect changed
+ || mRecalculateDockablePosition //recalculation is forced
+ )
{
// undock dockable and off() if dock not visible
if (!isDockVisible())
@@ -136,7 +140,8 @@ void LLDockControl::repositionDockable()
mPrevDockRect = dockRect;
mRootRect = rootRect;
- mRecalculateDocablePosition = false;
+ mFloaterRect = floater_rect;
+ mRecalculateDockablePosition = false;
mDockWidgetVisible = isDockVisible();
}
}
@@ -203,21 +208,33 @@ void LLDockControl::moveDockable()
switch (mDockAt)
{
case LEFT:
- x = dockRect.mLeft;
- y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
- // check is dockable inside root view rect
- if (x < rootRect.mLeft)
+
+ x = dockRect.mLeft - dockableRect.getWidth();
+ y = dockRect.getCenterY() + dockableRect.getHeight() / 2;
+
+ if (use_tongue)
{
- x = rootRect.mLeft;
+ x -= mDockTongue->getWidth();
}
- if (x + dockableRect.getWidth() > rootRect.mRight)
+
+ mDockTongueX = dockableRect.mRight;
+ mDockTongueY = dockableRect.getCenterY() - mDockTongue->getHeight() / 2;
+
+ break;
+
+ case RIGHT:
+
+ x = dockRect.mRight;
+ y = dockRect.getCenterY() + dockableRect.getHeight() / 2;
+
+ if (use_tongue)
{
- x = rootRect.mRight - dockableRect.getWidth();
+ x += mDockTongue->getWidth();
}
-
- mDockTongueX = x + dockableRect.getWidth()/2 - mDockTongue->getWidth() / 2;
-
- mDockTongueY = dockRect.mTop;
+
+ mDockTongueX = dockRect.mRight;
+ mDockTongueY = dockableRect.getCenterY() - mDockTongue->getHeight() / 2;
+
break;
case TOP:
@@ -315,13 +332,12 @@ void LLDockControl::moveDockable()
dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
dockableRect.getHeight());
}
+
LLRect localDocableParentRect;
- mDockableFloater->getParent()->screenRectToLocal(dockableRect,
- &localDocableParentRect);
- mDockableFloater->setRect(localDocableParentRect);
- mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
- &mDockTongueX, &mDockTongueY);
+ mDockableFloater->getParent()->screenRectToLocal(dockableRect, &localDocableParentRect);
+ mDockableFloater->setRect(localDocableParentRect);
+ mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY, &mDockTongueX, &mDockTongueY);
}
@@ -330,7 +346,7 @@ void LLDockControl::on()
if (isDockVisible())
{
mEnabled = true;
- mRecalculateDocablePosition = true;
+ mRecalculateDockablePosition = true;
}
}
@@ -341,7 +357,7 @@ void LLDockControl::off()
void LLDockControl::forceRecalculatePosition()
{
- mRecalculateDocablePosition = true;
+ mRecalculateDockablePosition = true;
}
void LLDockControl::drawToungue()
diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h
index 2e7359245f..c9602011f6 100644
--- a/indra/llui/lldockcontrol.h
+++ b/indra/llui/lldockcontrol.h
@@ -43,6 +43,7 @@ public:
{
TOP,
LEFT,
+ RIGHT,
BOTTOM
};
@@ -79,12 +80,13 @@ private:
private:
get_allowed_rect_callback_t mGetAllowedRectCallback;
bool mEnabled;
- bool mRecalculateDocablePosition;
+ bool mRecalculateDockablePosition;
bool mDockWidgetVisible;
DocAt mDockAt;
LLView* mDockWidget;
LLRect mPrevDockRect;
LLRect mRootRect;
+ LLRect mFloaterRect;
LLFloater* mDockableFloater;
LLUIImagePtr mDockTongue;
S32 mDockTongueX;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 7100ea13a7..33548151fd 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -58,6 +58,8 @@
#include "llhelp.h"
#include "llmultifloater.h"
#include "llsdutil.h"
+#include <boost/foreach.hpp>
+
// use this to control "jumping" behavior when Ctrl-Tabbing
const S32 TABBED_FLOATER_OFFSET = 0;
@@ -111,7 +113,6 @@ LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] =
LLMultiFloater* LLFloater::sHostp = NULL;
BOOL LLFloater::sQuitting = FALSE; // Flag to prevent storing visibility controls while quitting
-LLFloater::handle_map_t LLFloater::sFloaterMap;
LLFloaterView* gFloaterView = NULL;
@@ -194,7 +195,8 @@ LLFloater::Params::Params()
dock_pressed_image("dock_pressed_image"),
help_pressed_image("help_pressed_image"),
open_callback("open_callback"),
- close_callback("close_callback")
+ close_callback("close_callback"),
+ follows("follows")
{
changeDefault(visible, false);
}
@@ -268,7 +270,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
mMinimizeSignal(NULL)
// mNotificationContext(NULL)
{
- mHandle.bind(this);
// mNotificationContext = new LLFloaterNotificationContext(getHandle());
// Clicks stop here.
@@ -323,9 +324,6 @@ void LLFloater::initFloater(const Params& p)
// Floaters are created in the invisible state
setVisible(FALSE);
- // add self to handle->floater map
- sFloaterMap[mHandle] = this;
-
if (!getParent())
{
gFloaterView->addChild(this);
@@ -532,8 +530,6 @@ LLFloater::~LLFloater()
// correct, non-minimized positions.
setMinimized( FALSE );
- sFloaterMap.erase(mHandle);
-
delete mDragHandle;
for (S32 i = 0; i < 4; i++)
{
@@ -935,7 +931,7 @@ void LLFloater::applyPositioning(LLFloater* other)
case LLFloaterEnums::OPEN_POSITIONING_CASCADE_GROUP:
case LLFloaterEnums::OPEN_POSITIONING_CASCADING:
- if (other != NULL)
+ if (other != NULL && other != this)
{
stackWith(*other);
}
@@ -1038,7 +1034,9 @@ BOOL LLFloater::canSnapTo(const LLView* other_view)
if (other_view != getParent())
{
const LLFloater* other_floaterp = dynamic_cast<const LLFloater*>(other_view);
- if (other_floaterp && other_floaterp->getSnapTarget() == getHandle() && mDependents.find(other_floaterp->getHandle()) != mDependents.end())
+ if (other_floaterp
+ && other_floaterp->getSnapTarget() == getHandle()
+ && mDependents.find(other_floaterp->getHandle()) != mDependents.end())
{
// this is a dependent that is already snapped to us, so don't snap back to it
return FALSE;
@@ -1070,7 +1068,7 @@ void LLFloater::handleReshape(const LLRect& new_rect, bool by_user)
const LLRect old_rect = getRect();
LLView::handleReshape(new_rect, by_user);
- if (by_user)
+ if (by_user && !isMinimized())
{
storeRectControl();
mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_NONE;
@@ -1677,18 +1675,17 @@ void LLFloater::onClickHelp( LLFloater* self )
LLFloater* LLFloater::getClosableFloaterFromFocus()
{
LLFloater* focused_floater = NULL;
-
- handle_map_iter_t iter;
- for(iter = sFloaterMap.begin(); iter != sFloaterMap.end(); ++iter)
+ LLInstanceTracker<LLFloater>::instance_iter it = beginInstances();
+ LLInstanceTracker<LLFloater>::instance_iter end_it = endInstances();
+ for (; it != end_it; ++it)
{
- focused_floater = iter->second;
- if (focused_floater->hasFocus())
+ if (it->hasFocus())
{
break;
}
}
- if (iter == sFloaterMap.end())
+ if (it == endInstances())
{
// nothing found, return
return NULL;
@@ -1949,6 +1946,12 @@ void LLFloater::setCanDrag(BOOL can_drag)
}
}
+bool LLFloater::getCanDrag()
+{
+ return mDragHandle->getEnabled();
+}
+
+
void LLFloater::updateTitleButtons()
{
static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
@@ -2163,8 +2166,15 @@ LLFloaterView::LLFloaterView (const Params& p)
// By default, adjust vertical.
void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
{
- S32 old_width = getRect().getWidth();
- S32 old_height = getRect().getHeight();
+ S32 old_right = mLastSnapRect.mRight;
+ S32 old_top = mLastSnapRect.mTop;
+
+ LLView::reshape(width, height, called_from_parent);
+
+ S32 new_right = getSnapRect().mRight;
+ S32 new_top = getSnapRect().mTop;
+
+ mLastSnapRect = getSnapRect();
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
@@ -2172,66 +2182,48 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
LLFloater* floaterp = (LLFloater*)viewp;
if (floaterp->isDependent())
{
- // dependents use same follow flags as their "dependee"
+ // dependents are moved with their "dependee"
continue;
}
- // Make if follow the edge it is closest to
- U32 follow_flags = 0x0;
-
- if (floaterp->isMinimized())
- {
- follow_flags |= (FOLLOWS_LEFT | FOLLOWS_TOP);
- }
- else
+ if (!floaterp->isMinimized())
{
LLRect r = floaterp->getRect();
// Compute absolute distance from each edge of screen
S32 left_offset = llabs(r.mLeft - 0);
- S32 right_offset = llabs(old_width - r.mRight);
+ S32 right_offset = llabs(old_right - r.mRight);
- S32 top_offset = llabs(old_height - r.mTop);
+ S32 top_offset = llabs(old_top - r.mTop);
S32 bottom_offset = llabs(r.mBottom - 0);
+ S32 translate_x = 0;
+ S32 translate_y = 0;
- if (left_offset < right_offset)
+ if (left_offset > right_offset)
{
- follow_flags |= FOLLOWS_LEFT;
- }
- else
- {
- follow_flags |= FOLLOWS_RIGHT;
+ translate_x = new_right - old_right;
}
- // "No vertical adjustment" usually means that the bottom of the view
- // has been pushed up or down. Hence we want the floaters to follow
- // the top.
if (top_offset < bottom_offset)
{
- follow_flags |= FOLLOWS_TOP;
+ translate_y = new_top - old_top;
}
- else
+
+ // don't reposition immovable floaters
+ if (floaterp->getCanDrag())
{
- follow_flags |= FOLLOWS_BOTTOM;
+ floaterp->translate(translate_x, translate_y);
}
- }
-
- floaterp->setFollows(follow_flags);
-
- //RN: all dependent floaters copy follow behavior of "parent"
- for(LLFloater::handle_set_iter_t dependent_it = floaterp->mDependents.begin();
- dependent_it != floaterp->mDependents.end(); ++dependent_it)
- {
- LLFloater* dependent_floaterp = dependent_it->get();
- if (dependent_floaterp)
+ BOOST_FOREACH(LLHandle<LLFloater> dependent_floater, floaterp->mDependents)
{
- dependent_floaterp->setFollows(follow_flags);
+ if (dependent_floater.get())
+ {
+ dependent_floater.get()->translate(translate_x, translate_y);
+ }
}
}
}
-
- LLView::reshape(width, height, called_from_parent);
}
@@ -2631,6 +2623,12 @@ void LLFloaterView::shiftFloaters(S32 x_offset, S32 y_offset)
void LLFloaterView::refresh()
{
+ LLRect snap_rect = getSnapRect();
+ if (snap_rect != mLastSnapRect)
+ {
+ reshape(getRect().getWidth(), getRect().getHeight(), TRUE);
+ }
+
// Constrain children to be entirely on the screen
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
@@ -2968,6 +2966,9 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
// control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
LLPanel::initFromParams(p);
+ // override any follows flags
+ setFollows(FOLLOWS_NONE);
+
mTitle = p.title;
mShortTitle = p.short_title;
applyTitle();
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 73e9c9e831..59b35d206f 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -83,7 +83,7 @@ namespace LLInitParam
}
-class LLFloater : public LLPanel
+class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
{
friend class LLFloaterView;
friend class LLFloaterReg;
@@ -156,6 +156,8 @@ public:
Optional<CommitCallbackParam> open_callback,
close_callback;
+
+ Ignored follows;
Params();
};
@@ -234,6 +236,7 @@ public:
void setCanTearOff(BOOL can_tear_off);
virtual void setCanResize(BOOL can_resize);
void setCanDrag(BOOL can_drag);
+ bool getCanDrag();
void setHost(LLMultiFloater* host);
BOOL isResizable() const { return mResizable; }
void setResizeLimits( S32 min_width, S32 min_height );
@@ -282,7 +285,7 @@ public:
void clearSnapTarget() { mSnappedTo.markDead(); }
LLHandle<LLFloater> getSnapTarget() const { return mSnappedTo; }
- LLHandle<LLFloater> getHandle() const { return mHandle; }
+ LLHandle<LLFloater> getHandle() const { return getDerivedHandle<LLFloater>(); }
const LLSD& getKey() { return mKey; }
virtual bool matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); }
@@ -460,16 +463,9 @@ private:
typedef void(*click_callback)(LLFloater*);
static click_callback sButtonCallbacks[BUTTON_COUNT];
- typedef std::map<LLHandle<LLFloater>, LLFloater*> handle_map_t;
- typedef std::map<LLHandle<LLFloater>, LLFloater*>::iterator handle_map_iter_t;
- static handle_map_t sFloaterMap;
-
BOOL mHasBeenDraggedWhileMinimized;
S32 mPreviousMinimizedBottom;
S32 mPreviousMinimizedLeft;
-
-// LLFloaterNotificationContext* mNotificationContext;
- LLRootHandle<LLFloater> mHandle;
};
@@ -537,6 +533,7 @@ public:
private:
void hiddenFloaterClosed(LLFloater* floater);
+ LLRect mLastSnapRect;
LLHandle<LLView> mSnapView;
BOOL mFocusCycleMode;
S32 mSnapOffsetBottom;
diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h
index 8c000eee48..37c657dd92 100644
--- a/indra/llui/llhandle.h
+++ b/indra/llui/llhandle.h
@@ -28,17 +28,18 @@
#define LLHANDLE_H
#include "llpointer.h"
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/utility/enable_if.hpp>
-template <typename T>
class LLTombStone : public LLRefCount
{
public:
- LLTombStone(T* target = NULL) : mTarget(target) {}
+ LLTombStone(void* target = NULL) : mTarget(target) {}
- void setTarget(T* target) { mTarget = target; }
- T* getTarget() const { return mTarget; }
+ void setTarget(void* target) { mTarget = target; }
+ void* getTarget() const { return mTarget; }
private:
- T* mTarget;
+ mutable void* mTarget;
};
// LLHandles are used to refer to objects whose lifetime you do not control or influence.
@@ -53,13 +54,15 @@ private:
template <typename T>
class LLHandle
{
+ template <typename U> friend class LLHandle;
+ template <typename U> friend class LLHandleProvider;
public:
LLHandle() : mTombStone(getDefaultTombStone()) {}
- const LLHandle<T>& operator =(const LLHandle<T>& other)
- {
- mTombStone = other.mTombStone;
- return *this;
- }
+
+ template<typename U>
+ LLHandle(const LLHandle<U>& other, typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0)
+ : mTombStone(other.mTombStone)
+ {}
bool isDead() const
{
@@ -73,7 +76,7 @@ public:
T* get() const
{
- return mTombStone->getTarget();
+ return reinterpret_cast<T*>(mTombStone->getTarget());
}
friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
@@ -94,12 +97,13 @@ public:
}
protected:
- LLPointer<LLTombStone<T> > mTombStone;
+ LLPointer<LLTombStone> mTombStone;
private:
- static LLPointer<LLTombStone<T> >& getDefaultTombStone()
+ typedef T* pointer_t;
+ static LLPointer<LLTombStone>& getDefaultTombStone()
{
- static LLPointer<LLTombStone<T> > sDefaultTombStone = new LLTombStone<T>;
+ static LLPointer<LLTombStone> sDefaultTombStone = new LLTombStone;
return sDefaultTombStone;
}
};
@@ -108,23 +112,26 @@ template <typename T>
class LLRootHandle : public LLHandle<T>
{
public:
+ typedef LLRootHandle<T> self_t;
+ typedef LLHandle<T> base_t;
+
LLRootHandle(T* object) { bind(object); }
LLRootHandle() {};
~LLRootHandle() { unbind(); }
- // this is redundant, since a LLRootHandle *is* an LLHandle
- LLHandle<T> getHandle() { return LLHandle<T>(*this); }
+ // this is redundant, since an LLRootHandle *is* an LLHandle
+ //LLHandle<T> getHandle() { return LLHandle<T>(*this); }
void bind(T* object)
{
// unbind existing tombstone
if (LLHandle<T>::mTombStone.notNull())
{
- if (LLHandle<T>::mTombStone->getTarget() == object) return;
+ if (LLHandle<T>::mTombStone->getTarget() == (void*)object) return;
LLHandle<T>::mTombStone->setTarget(NULL);
}
// tombstone reference counted, so no paired delete
- LLHandle<T>::mTombStone = new LLTombStone<T>(object);
+ LLHandle<T>::mTombStone = new LLTombStone((void*)object);
}
void unbind()
@@ -142,6 +149,15 @@ private:
template <typename T>
class LLHandleProvider
{
+public:
+ LLHandle<T> getHandle() const
+ {
+ // perform lazy binding to avoid small tombstone allocations for handle
+ // providers whose handles are never referenced
+ mHandle.bind(static_cast<T*>(const_cast<LLHandleProvider<T>* >(this)));
+ return mHandle;
+ }
+
protected:
typedef LLHandle<T> handle_type_t;
LLHandleProvider()
@@ -149,16 +165,17 @@ protected:
// provided here to enforce T deriving from LLHandleProvider<T>
}
- LLHandle<T> getHandle()
- {
- // perform lazy binding to avoid small tombstone allocations for handle
- // providers whose handles are never referenced
- mHandle.bind(static_cast<T*>(this));
- return mHandle;
+ template <typename U>
+ LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
+ {
+ LLHandle<U> downcast_handle;
+ downcast_handle.mTombStone = getHandle().mTombStone;
+ return downcast_handle;
}
+
private:
- LLRootHandle<T> mHandle;
+ mutable LLRootHandle<T> mHandle;
};
#endif
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index ceec9c7eb1..c1cd04186b 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -57,6 +57,22 @@ LLKeywords::LLKeywords() : mLoaded(FALSE)
{
}
+inline BOOL LLKeywordToken::isTail(const llwchar* s) const
+{
+ BOOL res = TRUE;
+ const llwchar* t = mDelimiter.c_str();
+ S32 len = mDelimiter.size();
+ for (S32 i=0; i<len; i++)
+ {
+ if (s[i] != t[i])
+ {
+ res = FALSE;
+ break;
+ }
+ }
+ return res;
+}
+
LLKeywords::~LLKeywords()
{
std::for_each(mWordTokenMap.begin(), mWordTokenMap.end(), DeletePairedPointer());
@@ -106,6 +122,7 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
std::string SOL_LINE("[line ");
std::string SOL_ONE_SIDED_DELIMITER("[one_sided_delimiter ");
std::string SOL_TWO_SIDED_DELIMITER("[two_sided_delimiter ");
+ std::string SOL_DOUBLE_QUOTATION_MARKS("[double_quotation_marks ");
LLColor3 cur_color( 1, 0, 0 );
LLKeywordToken::TOKEN_TYPE cur_type = LLKeywordToken::WORD;
@@ -137,6 +154,12 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
cur_type = LLKeywordToken::TWO_SIDED_DELIMITER;
continue;
}
+ else if( line.find(SOL_DOUBLE_QUOTATION_MARKS) == 0 )
+ {
+ cur_color = readColor( line.substr(SOL_DOUBLE_QUOTATION_MARKS.size()) );
+ cur_type = LLKeywordToken::DOUBLE_QUOTATION_MARKS;
+ continue;
+ }
else if( line.find(SOL_ONE_SIDED_DELIMITER) == 0 )
{
cur_color = readColor( line.substr(SOL_ONE_SIDED_DELIMITER.size()) );
@@ -154,10 +177,26 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
if( !token_buffer.empty() && token_word_iter != word_tokens.end() )
{
- // first word is keyword
+ // first word is the keyword or a left delimiter
std::string keyword = (*token_word_iter);
LLStringUtil::trim(keyword);
+ // second word may be a right delimiter
+ std::string delimiter;
+ if (cur_type == LLKeywordToken::TWO_SIDED_DELIMITER)
+ {
+ while (delimiter.length() == 0 && ++token_word_iter != word_tokens.end())
+ {
+ delimiter = *token_word_iter;
+ LLStringUtil::trim(delimiter);
+ }
+ }
+ else if (cur_type == LLKeywordToken::DOUBLE_QUOTATION_MARKS)
+ {
+ // Closing delimiter is identical to the opening one.
+ delimiter = keyword;
+ }
+
// following words are tooltip
std::string tool_tip;
while (++token_word_iter != word_tokens.end())
@@ -170,11 +209,11 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
{
// Replace : with \n for multi-line tool tips.
LLStringUtil::replaceChar( tool_tip, ':', '\n' );
- addToken(cur_type, keyword, cur_color, tool_tip );
+ addToken(cur_type, keyword, cur_color, tool_tip, delimiter );
}
else
{
- addToken(cur_type, keyword, cur_color, LLStringUtil::null );
+ addToken(cur_type, keyword, cur_color, LLStringUtil::null, delimiter );
}
}
}
@@ -189,23 +228,26 @@ BOOL LLKeywords::loadFromFile( const std::string& filename )
void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type,
const std::string& key_in,
const LLColor3& color,
- const std::string& tool_tip_in )
+ const std::string& tool_tip_in,
+ const std::string& delimiter_in)
{
LLWString key = utf8str_to_wstring(key_in);
LLWString tool_tip = utf8str_to_wstring(tool_tip_in);
+ LLWString delimiter = utf8str_to_wstring(delimiter_in);
switch(type)
{
case LLKeywordToken::WORD:
- mWordTokenMap[key] = new LLKeywordToken(type, color, key, tool_tip);
+ mWordTokenMap[key] = new LLKeywordToken(type, color, key, tool_tip, LLWStringUtil::null);
break;
case LLKeywordToken::LINE:
- mLineTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip));
+ mLineTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip, LLWStringUtil::null));
break;
case LLKeywordToken::TWO_SIDED_DELIMITER:
+ case LLKeywordToken::DOUBLE_QUOTATION_MARKS:
case LLKeywordToken::ONE_SIDED_DELIMITER:
- mDelimiterTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip));
+ mDelimiterTokenList.push_front(new LLKeywordToken(type, color, key, tool_tip, delimiter));
break;
default:
@@ -357,7 +399,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
}
// cur is now at the first non-whitespace character of a new line
-
+
// Line start tokens
{
BOOL line_done = FALSE;
@@ -418,14 +460,15 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
S32 seg_end = 0;
seg_start = cur - base;
- cur += cur_delimiter->getLength();
+ cur += cur_delimiter->getLengthHead();
- if( cur_delimiter->getType() == LLKeywordToken::TWO_SIDED_DELIMITER )
+ LLKeywordToken::TOKEN_TYPE type = cur_delimiter->getType();
+ if( type == LLKeywordToken::TWO_SIDED_DELIMITER || type == LLKeywordToken::DOUBLE_QUOTATION_MARKS )
{
- while( *cur && !cur_delimiter->isHead(cur))
+ while( *cur && !cur_delimiter->isTail(cur))
{
// Check for an escape sequence.
- if (*cur == '\\')
+ if (type == LLKeywordToken::DOUBLE_QUOTATION_MARKS && *cur == '\\')
{
// Count the number of backslashes.
S32 num_backslashes = 0;
@@ -435,10 +478,10 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
between_delimiters++;
cur++;
}
- // Is the next character the end delimiter?
- if (cur_delimiter->isHead(cur))
+ // If the next character is the end delimiter?
+ if (cur_delimiter->isTail(cur))
{
- // Is there was an odd number of backslashes, then this delimiter
+ // If there was an odd number of backslashes, then this delimiter
// does not end the sequence.
if (num_backslashes % 2 == 1)
{
@@ -461,13 +504,13 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
if( *cur )
{
- cur += cur_delimiter->getLength();
- seg_end = seg_start + between_delimiters + 2 * cur_delimiter->getLength();
+ cur += cur_delimiter->getLengthHead();
+ seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead() + cur_delimiter->getLengthTail();
}
else
{
// eof
- seg_end = seg_start + between_delimiters + cur_delimiter->getLength();
+ seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead();
}
}
else
@@ -479,7 +522,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
between_delimiters++;
cur++;
}
- seg_end = seg_start + between_delimiters + cur_delimiter->getLength();
+ seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead();
}
insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, defaultColor, editor);
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index f6d75b7e75..ac34015393 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -41,23 +41,44 @@ typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
class LLKeywordToken
{
public:
- enum TOKEN_TYPE { WORD, LINE, TWO_SIDED_DELIMITER, ONE_SIDED_DELIMITER };
+ /**
+ * @brief Types of tokens/delimters being parsed.
+ *
+ * @desc Tokens/delimiters that need to be identified/highlighted. All are terminated if an EOF is encountered.
+ * - WORD are keywords in the normal sense, i.e. constants, events, etc.
+ * - LINE are for entire lines (currently only flow control labels use this).
+ * - ONE_SIDED_DELIMITER are for open-ended delimiters which are terminated by EOL.
+ * - TWO_SIDED_DELIMITER are for delimiters that end with a different delimiter than they open with.
+ * - DOUBLE_QUOTATION_MARKS are for delimiting areas using the same delimiter to open and close.
+ */
+ enum TOKEN_TYPE
+ {
+ WORD,
+ LINE,
+ TWO_SIDED_DELIMITER,
+ ONE_SIDED_DELIMITER,
+ DOUBLE_QUOTATION_MARKS
+ };
- LLKeywordToken( TOKEN_TYPE type, const LLColor3& color, const LLWString& token, const LLWString& tool_tip )
+ LLKeywordToken( TOKEN_TYPE type, const LLColor3& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter )
:
mType( type ),
mToken( token ),
mColor( color ),
- mToolTip( tool_tip )
+ mToolTip( tool_tip ),
+ mDelimiter( delimiter ) // right delimiter
{
}
- S32 getLength() const { return mToken.size(); }
+ S32 getLengthHead() const { return mToken.size(); }
+ S32 getLengthTail() const { return mDelimiter.size(); }
BOOL isHead(const llwchar* s) const;
+ BOOL isTail(const llwchar* s) const;
const LLWString& getToken() const { return mToken; }
const LLColor3& getColor() const { return mColor; }
TOKEN_TYPE getType() const { return mType; }
const LLWString& getToolTip() const { return mToolTip; }
+ const LLWString& getDelimiter() const { return mDelimiter; }
#ifdef _DEBUG
void dump();
@@ -68,6 +89,7 @@ private:
LLWString mToken;
LLColor3 mColor;
LLWString mToolTip;
+ LLWString mDelimiter;
};
class LLKeywords
@@ -85,7 +107,8 @@ public:
void addToken(LLKeywordToken::TOKEN_TYPE type,
const std::string& key,
const LLColor3& color,
- const std::string& tool_tip = LLStringUtil::null);
+ const std::string& tool_tip = LLStringUtil::null,
+ const std::string& delimiter = LLStringUtil::null);
// This class is here as a performance optimization.
// The word token map used to be defined as std::map<LLWString, LLKeywordToken*>.
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 3ef8d8ff35..cb237fca7c 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -1686,7 +1686,8 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
mSpilloverMenu(NULL),
mJumpKey(p.jump_key),
mCreateJumpKeys(p.create_jump_keys),
- mNeedsArrange(FALSE),
+ mNeedsArrange(FALSE),
+ mResetScrollPositionOnShow(true),
mShortcutPad(p.shortcut_pad)
{
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
@@ -3043,7 +3044,7 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
S32 mouse_x, mouse_y;
// Resetting scrolling position
- if (menu->isScrollable())
+ if (menu->isScrollable() && menu->isScrollPositionOnShowReset())
{
menu->mFirstVisibleItem = NULL;
}
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 77db588390..36f3ba34b9 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -516,6 +516,9 @@ public:
static class LLMenuHolderGL* sMenuContainer;
+ void resetScrollPositionOnShow(bool reset_scroll_pos) { mResetScrollPositionOnShow = reset_scroll_pos; }
+ bool isScrollPositionOnShowReset() { return mResetScrollPositionOnShow; }
+
protected:
void createSpilloverBranch();
void cleanupSpilloverBranch();
@@ -565,6 +568,7 @@ private:
KEY mJumpKey;
BOOL mCreateJumpKeys;
S32 mShortcutPad;
+ bool mResetScrollPositionOnShow;
}; // end class LLMenuGL
@@ -677,7 +681,7 @@ public:
BOOL appendContextSubMenu(LLContextMenu *menu);
- LLHandle<LLContextMenu> getHandle() { mHandle.bind(this); return mHandle; }
+ LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); }
protected:
BOOL mHoveredAnyItem;
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 8f7025a9a6..d232e27ef2 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -1624,7 +1624,7 @@ LLNotificationPtr LLNotifications::find(LLUUID uuid)
LLNotificationSet::iterator it=mItems.find(target);
if (it == mItems.end())
{
- llwarns << "Tried to dereference uuid '" << uuid << "' as a notification key but didn't find it." << llendl;
+ LL_DEBUGS("Notifications") << "Tried to dereference uuid '" << uuid << "' as a notification key but didn't find it." << llendl;
return LLNotificationPtr((LLNotification*)NULL);
}
else
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index a45b617c2e..00318cec6b 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -122,8 +122,6 @@ LLPanel::LLPanel(const LLPanel::Params& p)
{
addBorder(p.border);
}
-
- mPanelHandle.bind(this);
}
LLPanel::~LLPanel()
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index ab1c87caff..cd33938226 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -153,7 +153,7 @@ public:
void setCtrlsEnabled(BOOL b);
- LLHandle<LLPanel> getHandle() const { return mPanelHandle; }
+ LLHandle<LLPanel> getHandle() const { return getDerivedHandle<LLPanel>(); }
const LLCallbackMap::map_t& getFactoryMap() const { return mFactoryMap; }
@@ -278,7 +278,6 @@ private:
LLViewBorder* mBorder;
LLButton* mDefaultBtn;
LLUIString mLabel;
- LLRootHandle<LLPanel> mPanelHandle;
typedef std::map<std::string, std::string> ui_string_map_t;
ui_string_map_t mUIStrings;
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 622f3e215c..466fac33ea 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -175,6 +175,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mBorder(NULL),
mSortCallback(NULL),
mPopupMenu(NULL),
+ mCommentTextView(NULL),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
mTotalColumnPadding(0),
@@ -476,7 +477,12 @@ void LLScrollListCtrl::updateLayout()
getRect().getWidth() - 2 * mBorderThickness,
getRect().getHeight() - (2 * mBorderThickness ) - heading_size );
- getChildView("comment_text")->setShape(mItemListRect);
+ if (mCommentTextView == NULL)
+ {
+ mCommentTextView = getChildView("comment_text");
+ }
+
+ mCommentTextView->setShape(mItemListRect);
// how many lines of content in a single "page"
S32 page_lines = getLinesPerPage();
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 09ab89960d..ae8aea9245 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -480,6 +480,8 @@ private:
S32 mHighlightedItem;
class LLViewBorder* mBorder;
LLContextMenu *mPopupMenu;
+
+ LLView *mCommentTextView;
LLWString mSearchString;
LLFrameTimer mSearchTimer;
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index 6fa90933a4..0e29873bb0 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -36,6 +36,8 @@ static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
static const LLSD NO_VALUE_MARKER;
+LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
+
//
// LLParamSDParser
//
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
index c1cfa98399..3dfc6d020e 100644
--- a/indra/llui/llsdparam.h
+++ b/indra/llui/llsdparam.h
@@ -91,6 +91,8 @@ private:
LLSD* mCurWriteSD;
};
+
+extern LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
template<typename T>
class LLSDParamAdapter : public T
{
@@ -98,8 +100,11 @@ public:
LLSDParamAdapter() {}
LLSDParamAdapter(const LLSD& sd)
{
+ LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
LLParamSDParser parser;
- parser.readSD(sd, *this);
+ // don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
+ bool parse_silently = true;
+ parser.readSD(sd, *this, parse_silently);
}
operator LLSD() const
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index d197084e38..87814f838e 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -96,6 +96,9 @@ public:
void onUpBtn(const LLSD& data);
void onDownBtn(const LLSD& data);
+
+ const LLColor4& getEnabledTextColor() const { return mTextEnabledColor.get(); }
+ const LLColor4& getDisabledTextColor() const { return mTextDisabledColor.get(); }
private:
void updateLabelColor();
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index ad1f3c504d..d5f8707381 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -214,6 +214,7 @@ LLTabContainer::Params::Params()
middle_tab("middle_tab"),
last_tab("last_tab"),
use_custom_icon_ctrl("use_custom_icon_ctrl", false),
+ open_tabs_on_drag_and_drop("open_tabs_on_drag_and_drop", false),
tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
use_ellipses("use_ellipses"),
font_halign("halign")
@@ -250,6 +251,7 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mMiddleTabParams(p.middle_tab),
mLastTabParams(p.last_tab),
mCustomIconCtrlUsed(p.use_custom_icon_ctrl),
+ mOpenTabsOnDragAndDrop(p.open_tabs_on_drag_and_drop),
mTabIconCtrlPad(p.tab_icon_ctrl_pad),
mUseTabEllipses(p.use_ellipses)
{
@@ -812,50 +814,62 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag
{
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
- if( !getTabsHidden()
- && mDragAndDropDelayTimer.getStarted()
- && mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
+ if(mOpenTabsOnDragAndDrop && !getTabsHidden())
{
- if (has_scroll_arrows)
+ // In that case, we'll open the hovered tab while dragging and dropping items.
+ // This allows for drilling through tabs.
+ if (mDragAndDropDelayTimer.getStarted())
{
- if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
+ if (mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME)
{
- S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
- mJumpPrevArrowBtn->handleHover(local_x, local_y, mask);
- }
- if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
- mJumpNextArrowBtn->handleHover(local_x, local_y, mask);
- }
- if (mPrevArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
- S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
- mPrevArrowBtn->handleHover(local_x, local_y, mask);
- }
- else if (mNextArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mNextArrowBtn->getRect().mLeft;
- S32 local_y = y - mNextArrowBtn->getRect().mBottom;
- mNextArrowBtn->handleHover(local_x, local_y, mask);
- }
- }
+ if (has_scroll_arrows)
+ {
+ if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
+ {
+ S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
+ S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
+ mJumpPrevArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
+ {
+ S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
+ S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
+ mJumpNextArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ if (mPrevArrowBtn->getRect().pointInRect(x, y))
+ {
+ S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
+ S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
+ mPrevArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ else if (mNextArrowBtn->getRect().pointInRect(x, y))
+ {
+ S32 local_x = x - mNextArrowBtn->getRect().mLeft;
+ S32 local_y = y - mNextArrowBtn->getRect().mBottom;
+ mNextArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ }
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( TRUE );
- S32 local_x = x - tuple->mButton->getRect().mLeft;
- S32 local_y = y - tuple->mButton->getRect().mBottom;
- if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
- {
- tuple->mButton->onCommit();
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( TRUE );
+ S32 local_x = x - tuple->mButton->getRect().mLeft;
+ S32 local_y = y - tuple->mButton->getRect().mBottom;
+ if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
+ {
+ tuple->mButton->onCommit();
+ }
+ }
+ // Stop the timer whether successful or not. Don't let it run forever.
mDragAndDropDelayTimer.stop();
}
}
+ else
+ {
+ // Start a timer so we don't open tabs as soon as we hover on them
+ mDragAndDropDelayTimer.start();
+ }
}
return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip);
@@ -1025,85 +1039,50 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
}
else
{
+ LLButton::Params& p = (mCustomIconCtrlUsed ? custom_btn_params : normal_btn_params);
+
+ p.rect(btn_rect);
+ p.font(mFont);
+ p.font_halign = mFontHalign;
+ p.label(trimmed_label);
+ p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
+ if (indent)
+ {
+ p.pad_left(indent);
+ }
+ p.pad_bottom( mLabelPadBottom );
+ p.scale_image(true);
+ p.tab_stop(false);
+ p.label_shadow(false);
+ p.follows.flags = FOLLOWS_LEFT;
+
if (mIsVertical)
{
- LLButton::Params& p = (mCustomIconCtrlUsed)?
- custom_btn_params:normal_btn_params;
-
p.name(std::string("vert tab button"));
- p.rect(btn_rect);
- p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
- p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
- p.font(mFont);
- p.label(trimmed_label);
p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
p.image_selected(mMiddleTabParams.tab_left_image_selected);
- p.scale_image(true);
- p.font_halign = mFontHalign;
- p.pad_bottom( mLabelPadBottom );
- p.tab_stop(false);
- p.label_shadow(false);
- if (indent)
- {
- p.pad_left(indent);
- }
-
-
- if(mCustomIconCtrlUsed)
- {
- btn = LLUICtrlFactory::create<LLCustomButtonIconCtrl>(custom_btn_params);
-
- }
- else
- {
- btn = LLUICtrlFactory::create<LLButton>(p);
- }
+ p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
}
else
{
- LLButton::Params& p = (mCustomIconCtrlUsed)?
- custom_btn_params:normal_btn_params;
p.name(std::string(child->getName()) + " tab");
- p.rect(btn_rect);
- p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
- p.font(mFont);
- p.label(trimmed_label);
p.visible(false);
- p.scale_image(true);
p.image_unselected(tab_img);
p.image_selected(tab_selected_img);
- p.tab_stop(false);
- p.label_shadow(false);
+ p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM);
// Try to squeeze in a bit more text
p.pad_left( mLabelPadLeft );
p.pad_right(2);
- p.pad_bottom( mLabelPadBottom );
- p.font_halign = mFontHalign;
- p.follows.flags = FOLLOWS_LEFT;
- p.follows.flags = FOLLOWS_LEFT;
-
- if (indent)
- {
- p.pad_left(indent);
- }
-
- if( getTabPosition() == TOP )
- {
- p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
- }
- else
- {
- p.follows.flags = p.follows.flags() | FOLLOWS_BOTTOM;
- }
-
- if(mCustomIconCtrlUsed)
- {
- btn = LLUICtrlFactory::create<LLCustomButtonIconCtrl>(custom_btn_params);
- }
- else
- {
- btn = LLUICtrlFactory::create<LLButton>(p);
- }
+ }
+
+ // *TODO : It seems wrong not to use p in both cases considering the way p is initialized
+ if (mCustomIconCtrlUsed)
+ {
+ btn = LLUICtrlFactory::create<LLCustomButtonIconCtrl>(custom_btn_params);
+ }
+ else
+ {
+ btn = LLUICtrlFactory::create<LLButton>(p);
}
}
@@ -1280,6 +1259,10 @@ void LLTabContainer::enableTabButton(S32 which, BOOL enable)
{
mTabList[which]->mButton->setEnabled(enable);
}
+ // Stop the DaD timer as it might run forever
+ // enableTabButton() is typically called on refresh and draw when anything changed
+ // in the tab container so it's a good time to reset that.
+ mDragAndDropDelayTimer.stop();
}
void LLTabContainer::deleteAllTabs()
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index eaa2fd54e0..cebace2ceb 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -105,6 +105,11 @@ public:
Optional<bool> use_custom_icon_ctrl;
/**
+ * Open tabs on hover in drag and drop situations
+ */
+ Optional<bool> open_tabs_on_drag_and_drop;
+
+ /**
* Paddings for LLIconCtrl in case of LLCustomButtonIconCtrl usage(use_custom_icon_ctrl = true)
*/
Optional<S32> tab_icon_ctrl_pad;
@@ -300,6 +305,7 @@ private:
TabParams mLastTabParams;
bool mCustomIconCtrlUsed;
+ bool mOpenTabsOnDragAndDrop;
S32 mTabIconCtrlPad;
bool mUseTabEllipses;
};
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 919364be63..3b768166f1 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -2518,7 +2518,11 @@ 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::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; }
-std::string LLTextSegment::getName() const { return ""; }
+const std::string& LLTextSegment::getName() const
+{
+ static std::string empty_string("");
+ return empty_string;
+}
void LLTextSegment::onMouseCaptureLost() {}
void LLTextSegment::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}
void LLTextSegment::localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 384d9116fc..b699601908 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -84,7 +84,7 @@ public:
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
- /*virtual*/ std::string getName() const;
+ /*virtual*/ const std::string& getName() const;
/*virtual*/ void onMouseCaptureLost();
/*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
/*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
diff --git a/indra/llui/lltextparser.cpp b/indra/llui/lltextparser.cpp
index a4fe4f6ca8..8a85f99e0c 100644
--- a/indra/llui/lltextparser.cpp
+++ b/indra/llui/lltextparser.cpp
@@ -46,8 +46,6 @@ LLTextParser::LLTextParser()
{}
-// Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency.
-
S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
{
if (!highlight.has("pattern")) return -1;
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index 515605200e..7f96c1373c 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -109,9 +109,14 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p)
mPadBetween(p.pad_between),
mMinGirth(p.min_girth),
mPopupMenuHandle(),
+ mRightMouseTargetButton(NULL),
mStartDragItemCallback(NULL),
mHandleDragItemCallback(NULL),
mHandleDropCallback(NULL),
+ mButtonAddSignal(NULL),
+ mButtonEnterSignal(NULL),
+ mButtonLeaveSignal(NULL),
+ mButtonRemoveSignal(NULL),
mDragAndDropTarget(false)
{
mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_WITH_TEXT] = p.button_icon_and_text;
@@ -121,6 +126,10 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p)
LLToolBar::~LLToolBar()
{
delete mPopupMenuHandle.get();
+ delete mButtonAddSignal;
+ delete mButtonEnterSignal;
+ delete mButtonLeaveSignal;
+ delete mButtonRemoveSignal;
}
void LLToolBar::createContextMenu()
@@ -131,6 +140,7 @@ void LLToolBar::createContextMenu()
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit_reg;
commit_reg.add("Toolbars.EnableSetting", boost::bind(&LLToolBar::onSettingEnable, this, _2));
+ commit_reg.add("Toolbars.RemoveSelectedCommand", boost::bind(&LLToolBar::onRemoveSelectedCommand, this));
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_reg;
enable_reg.add("Toolbars.CheckSetting", boost::bind(&LLToolBar::isSettingChecked, this, _2));
@@ -212,7 +222,6 @@ bool LLToolBar::addCommand(const LLCommandId& commandId, int rank)
mButtonPanel->addChild(button);
mButtonMap.insert(std::make_pair(commandId.uuid(), button));
-
// Insert the command and button in the right place in their respective lists
if ((rank >= mButtonCommands.size()) || (rank == RANK_NONE))
{
@@ -238,6 +247,14 @@ bool LLToolBar::addCommand(const LLCommandId& commandId, int rank)
mNeedsLayout = true;
+ updateLayoutAsNeeded();
+
+
+ if (mButtonAddSignal)
+ {
+ (*mButtonAddSignal)(button);
+ }
+
return true;
}
@@ -264,6 +281,11 @@ int LLToolBar::removeCommand(const LLCommandId& commandId)
++rank;
}
+ if (mButtonRemoveSignal)
+ {
+ (*mButtonRemoveSignal)(*it_button);
+ }
+
// Delete the button and erase the command and button records
delete (*it_button);
mButtonCommands.erase(it_command);
@@ -352,6 +374,23 @@ bool LLToolBar::stopCommandInProgress(const LLCommandId& commandId)
return (command_button != NULL);
}
+bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash)
+{
+ LLButton * command_button = NULL;
+
+ if (commandId != LLCommandId::null)
+ {
+ command_id_map::iterator it = mButtonMap.find(commandId.uuid());
+ if (it != mButtonMap.end())
+ {
+ command_button = it->second;
+ command_button->setFlashing(flash ? TRUE : FALSE);
+ }
+ }
+
+ return (command_button != NULL);
+}
+
BOOL LLToolBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
LLRect button_panel_rect;
@@ -360,6 +399,20 @@ BOOL LLToolBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
if (handle_it_here)
{
+ // Determine which button the mouse was over during the click in case the context menu action
+ // is intended to affect the button.
+ BOOST_FOREACH(LLToolBarButton* button, mButtons)
+ {
+ LLRect button_rect;
+ button->localRectToOtherView(button->getLocalRect(), &button_rect, this);
+
+ if (button_rect.pointInRect(x, y))
+ {
+ mRightMouseTargetButton = button;
+ break;
+ }
+ }
+
createContextMenu();
LLContextMenu * menu = (LLContextMenu *) mPopupMenuHandle.get();
@@ -409,6 +462,18 @@ void LLToolBar::onSettingEnable(const LLSD& userdata)
}
}
+void LLToolBar::onRemoveSelectedCommand()
+{
+ llassert(!mReadOnly);
+
+ if (mRightMouseTargetButton)
+ {
+ removeCommand(mRightMouseTargetButton->getCommandId());
+
+ mRightMouseTargetButton = NULL;
+ }
+}
+
void LLToolBar::setButtonType(LLToolBarEnums::ButtonType button_type)
{
bool regenerate_buttons = (mButtonType != button_type);
@@ -487,11 +552,11 @@ int LLToolBar::getRankFromPosition(S32 x, S32 y)
S32 mid_point = (button_rect.mRight + button_rect.mLeft) / 2;
if (button_panel_x < mid_point)
{
- mDragx = button_rect.mLeft - mPadLeft;
- mDragy = button_rect.mTop + mPadTop;
- }
- else
- {
+ mDragx = button_rect.mLeft - mPadLeft;
+ mDragy = button_rect.mTop + mPadTop;
+ }
+ else
+ {
rank++;
mDragx = button_rect.mRight + mPadRight - 1;
mDragy = button_rect.mTop + mPadTop;
@@ -518,12 +583,12 @@ int LLToolBar::getRankFromPosition(S32 x, S32 y)
{
// We hit passed the end of the list so put the insertion point at the end
if (orientation == LLLayoutStack::HORIZONTAL)
- {
+ {
mDragx = button_rect.mRight + mPadRight;
mDragy = button_rect.mTop + mPadTop;
- }
- else
- {
+ }
+ else
+ {
mDragx = button_rect.mLeft - mPadLeft;
mDragy = button_rect.mBottom - mPadBottom;
}
@@ -705,6 +770,12 @@ void LLToolBar::updateLayoutAsNeeded()
// re-center toolbar buttons
mCenteringStack->updateLayout();
+ if (!mButtons.empty())
+ {
+ mButtonPanel->setVisible(TRUE);
+ mButtonPanel->setMouseOpaque(TRUE);
+ }
+
// don't clear flag until after we've resized ourselves, to avoid laying out every frame
mNeedsLayout = false;
}
@@ -790,10 +861,16 @@ void LLToolBar::createButtons()
{
BOOST_FOREACH(LLToolBarButton* button, mButtons)
{
+ if (mButtonRemoveSignal)
+ {
+ (*mButtonRemoveSignal)(button);
+ }
+
delete button;
}
mButtons.clear();
mButtonMap.clear();
+ mRightMouseTargetButton = NULL;
BOOST_FOREACH(LLCommandId& command_id, mButtonCommands)
{
@@ -801,6 +878,11 @@ void LLToolBar::createButtons()
mButtons.push_back(button);
mButtonPanel->addChild(button);
mButtonMap.insert(std::make_pair(command_id.uuid(), button));
+
+ if (mButtonAddSignal)
+ {
+ (*mButtonAddSignal)(button);
+ }
}
mNeedsLayout = true;
}
@@ -870,8 +952,7 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
button->setCommitCallback(executeParam);
}
-
-
+ // Set up "is running" query callback
const std::string& isRunningFunction = commandp->isRunningFunctionName();
if (isRunningFunction.length() > 0)
{
@@ -898,6 +979,36 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
return button;
}
+boost::signals2::connection connectSignal(LLToolBar::button_signal_t*& signal, const LLToolBar::button_signal_t::slot_type& cb)
+{
+ if (!signal)
+ {
+ signal = new LLToolBar::button_signal_t();
+ }
+
+ return signal->connect(cb);
+}
+
+boost::signals2::connection LLToolBar::setButtonAddCallback(const button_signal_t::slot_type& cb)
+{
+ return connectSignal(mButtonAddSignal, cb);
+}
+
+boost::signals2::connection LLToolBar::setButtonEnterCallback(const button_signal_t::slot_type& cb)
+{
+ return connectSignal(mButtonEnterSignal, cb);
+}
+
+boost::signals2::connection LLToolBar::setButtonLeaveCallback(const button_signal_t::slot_type& cb)
+{
+ return connectSignal(mButtonLeaveSignal, cb);
+}
+
+boost::signals2::connection LLToolBar::setButtonRemoveCallback(const button_signal_t::slot_type& cb)
+{
+ return connectSignal(mButtonRemoveSignal, cb);
+}
+
BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
@@ -969,8 +1080,6 @@ LLToolBarButton::LLToolBarButton(const Params& p)
mOriginalImageOverlayColor(p.image_overlay_color),
mOriginalImageOverlaySelectedColor(p.image_overlay_selected_color)
{
- mButtonFlashRate = 0.0;
- mButtonFlashCount = 0;
}
LLToolBarButton::~LLToolBarButton()
@@ -1012,6 +1121,7 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask)
{
handled = LLButton::handleHover(x, y, mask);
}
+
return handled;
}
@@ -1024,6 +1134,23 @@ void LLToolBarButton::onMouseEnter(S32 x, S32 y, MASK mask)
{
mNeedsHighlight = TRUE;
}
+
+ LLToolBar* parent_toolbar = getParentByType<LLToolBar>();
+ if (parent_toolbar && parent_toolbar->mButtonEnterSignal)
+ {
+ (*(parent_toolbar->mButtonEnterSignal))(this);
+ }
+}
+
+void LLToolBarButton::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ LLButton::onMouseLeave(x, y, mask);
+
+ LLToolBar* parent_toolbar = getParentByType<LLToolBar>();
+ if (parent_toolbar && parent_toolbar->mButtonLeaveSignal)
+ {
+ (*(parent_toolbar->mButtonLeaveSignal))(this);
+ }
}
void LLToolBarButton::onMouseCaptureLost()
@@ -1072,25 +1199,25 @@ void LLToolBarButton::setEnabled(BOOL enabled)
}
}
-
const std::string LLToolBarButton::getToolTip() const
{
std::string tooltip;
+
if (labelIsTruncated() || getCurrentLabel().empty())
{
- return LLTrans::getString(LLCommandManager::instance().getCommand(mId)->labelRef()) + " -- " + LLView::getToolTip();
+ tooltip = LLTrans::getString(LLCommandManager::instance().getCommand(mId)->labelRef()) + " -- " + LLView::getToolTip();
}
else
{
- return LLView::getToolTip();
+ tooltip = LLView::getToolTip();
}
-}
-
-
-
-
-
-
+ LLToolBar* parent_toolbar = getParentByType<LLToolBar>();
+ if (parent_toolbar && parent_toolbar->mButtonTooltipSuffix.length() > 0)
+ {
+ tooltip = tooltip + "\n(" + parent_toolbar->mButtonTooltipSuffix + ")";
+ }
+ return tooltip;
+}
diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h
index e634e57f93..51fe23ddd1 100644
--- a/indra/llui/lltoolbar.h
+++ b/indra/llui/lltoolbar.h
@@ -63,14 +63,17 @@ public:
BOOL handleMouseDown(S32 x, S32 y, MASK mask);
BOOL handleHover(S32 x, S32 y, MASK mask);
+
void reshape(S32 width, S32 height, BOOL called_from_parent = true);
void setEnabled(BOOL enabled);
void setCommandId(const LLCommandId& id) { mId = id; }
+ LLCommandId getCommandId() { return mId; }
void setStartDragCallback(tool_startdrag_callback_t cb) { mStartDragItemCallback = cb; }
void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; }
void onMouseEnter(S32 x, S32 y, MASK mask);
+ void onMouseLeave(S32 x, S32 y, MASK mask);
void onMouseCaptureLost();
void onCommit();
@@ -120,6 +123,8 @@ namespace LLToolBarEnums
SIDE_RIGHT,
SIDE_TOP,
};
+
+ LLLayoutStack::ELayoutOrientation getOrientation(SideType sideType);
}
// NOTE: This needs to occur before Param block declaration for proper compilation.
@@ -142,6 +147,7 @@ namespace LLInitParam
class LLToolBar
: public LLUICtrl
{
+ friend class LLToolBarButton;
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
@@ -160,7 +166,8 @@ public:
pad_bottom,
pad_between,
min_girth;
- // get rid of this
+
+ // default command set
Multiple<LLCommandId::Params> commands;
Optional<LLPanel::Params> button_panel;
@@ -171,8 +178,6 @@ public:
// virtuals
void draw();
void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- int getRankFromPosition(S32 x, S32 y);
- int getRankFromPosition(const LLCommandId& id);
BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
@@ -181,80 +186,103 @@ public:
std::string& tooltip_msg);
static const int RANK_NONE = -1;
-
bool addCommand(const LLCommandId& commandId, int rank = RANK_NONE);
int removeCommand(const LLCommandId& commandId); // Returns the rank the removed command was at, RANK_NONE if not found
- bool hasCommand(const LLCommandId& commandId) const;
- bool enableCommand(const LLCommandId& commandId, bool enabled);
- bool stopCommandInProgress(const LLCommandId& commandId);
+ bool hasCommand(const LLCommandId& commandId) const; // is this command bound to a button in this toolbar
+ bool enableCommand(const LLCommandId& commandId, bool enabled); // enable/disable button bound to the specified command, if it exists in this toolbar
+ bool stopCommandInProgress(const LLCommandId& commandId); // stop command if it is currently active
+ bool flashCommand(const LLCommandId& commandId, bool flash); // flash button associated with given command, if in this toolbar
- void setStartDragCallback(tool_startdrag_callback_t cb) { mStartDragItemCallback = cb; }
+ void setStartDragCallback(tool_startdrag_callback_t cb) { mStartDragItemCallback = cb; } // connects drag and drop behavior to external logic
void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; }
void setHandleDropCallback(tool_handledrop_callback_t cb) { mHandleDropCallback = cb; }
bool isReadOnly() const { return mReadOnly; }
LLToolBarButton* createButton(const LLCommandId& id);
+ typedef boost::signals2::signal<void (LLView* button)> button_signal_t;
+ boost::signals2::connection setButtonAddCallback(const button_signal_t::slot_type& cb);
+ boost::signals2::connection setButtonEnterCallback(const button_signal_t::slot_type& cb);
+ boost::signals2::connection setButtonLeaveCallback(const button_signal_t::slot_type& cb);
+ boost::signals2::connection setButtonRemoveCallback(const button_signal_t::slot_type& cb);
+
+ // append the specified string to end of tooltip
+ void setTooltipButtonSuffix(const std::string& suffix) { mButtonTooltipSuffix = suffix; }
+
+ LLToolBarEnums::SideType getSideType() const { return mSideType; }
bool hasButtons() const { return !mButtons.empty(); }
bool isModified() const { return mModified; }
-protected:
- friend class LLUICtrlFactory;
- LLToolBar(const Params&);
- ~LLToolBar();
-
- void initFromParams(const Params&);
- tool_startdrag_callback_t mStartDragItemCallback;
- tool_handledrag_callback_t mHandleDragItemCallback;
- tool_handledrop_callback_t mHandleDropCallback;
- bool mDragAndDropTarget;
- int mDragRank;
- S32 mDragx,
- mDragy,
- mDragGirth;
+ int getRankFromPosition(S32 x, S32 y);
+ int getRankFromPosition(const LLCommandId& id);
-public:
// Methods used in loading and saving toolbar settings
void setButtonType(LLToolBarEnums::ButtonType button_type);
LLToolBarEnums::ButtonType getButtonType() { return mButtonType; }
command_id_list_t& getCommandsList() { return mButtonCommands; }
void clearCommandsList();
-
+
private:
+ friend class LLUICtrlFactory;
+ LLToolBar(const Params&);
+ ~LLToolBar();
+
+ void initFromParams(const Params&);
void createContextMenu();
void updateLayoutAsNeeded();
void createButtons();
void resizeButtonsInRow(std::vector<LLToolBarButton*>& buttons_in_row, S32 max_row_girth);
BOOL isSettingChecked(const LLSD& userdata);
void onSettingEnable(const LLSD& userdata);
+ void onRemoveSelectedCommand();
+private:
+ // static layout state
const bool mReadOnly;
+ const LLToolBarEnums::SideType mSideType;
+ const bool mWrap;
+ const S32 mPadLeft,
+ mPadRight,
+ mPadTop,
+ mPadBottom,
+ mPadBetween,
+ mMinGirth;
+
+ // drag and drop state
+ tool_startdrag_callback_t mStartDragItemCallback;
+ tool_handledrag_callback_t mHandleDragItemCallback;
+ tool_handledrop_callback_t mHandleDropCallback;
+ bool mDragAndDropTarget;
+ int mDragRank;
+ S32 mDragx,
+ mDragy,
+ mDragGirth;
typedef std::list<LLToolBarButton*> toolbar_button_list;
+ typedef std::map<LLUUID, LLToolBarButton*> command_id_map;
toolbar_button_list mButtons;
command_id_list_t mButtonCommands;
- typedef std::map<LLUUID, LLToolBarButton*> command_id_map;
command_id_map mButtonMap;
LLToolBarEnums::ButtonType mButtonType;
+ LLToolBarButton::Params mButtonParams[LLToolBarEnums::BTNTYPE_COUNT];
+
+ // related widgets
LLLayoutStack* mCenteringStack;
- LLLayoutStack* mWrapStack;
LLPanel* mButtonPanel;
- LLToolBarEnums::SideType mSideType;
-
- bool mWrap;
+ LLHandle<class LLContextMenu> mPopupMenuHandle;
+
+ LLToolBarButton* mRightMouseTargetButton;
+
bool mNeedsLayout;
bool mModified;
- S32 mPadLeft,
- mPadRight,
- mPadTop,
- mPadBottom,
- mPadBetween,
- mMinGirth;
- LLToolBarButton::Params mButtonParams[LLToolBarEnums::BTNTYPE_COUNT];
+ button_signal_t* mButtonAddSignal;
+ button_signal_t* mButtonEnterSignal;
+ button_signal_t* mButtonLeaveSignal;
+ button_signal_t* mButtonRemoveSignal;
- LLHandle<class LLContextMenu> mPopupMenuHandle;
+ std::string mButtonTooltipSuffix;
};
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 79ad99a770..6b74c5a6be 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -153,11 +153,11 @@ void gl_state_for_2d(S32 width, S32 height)
F32 window_width = (F32) width;//gViewerWindow->getWindowWidth();
F32 window_height = (F32) height;//gViewerWindow->getWindowHeight();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.loadIdentity();
+ gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.loadIdentity();
stop_glerror();
}
@@ -537,7 +537,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
}
}
- gGL.getTexUnit(0)->bind(image);
+ gGL.getTexUnit(0)->bind(image, true);
gGL.color4fv(color.mV);
@@ -735,7 +735,7 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
LLGLSUIDefault gls_ui;
- gGL.getTexUnit(0)->bind(image);
+ gGL.getTexUnit(0)->bind(image, true);
gGL.color4fv(color.mV);
@@ -788,7 +788,7 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
- gGL.getTexUnit(0)->bind(image);
+ gGL.getTexUnit(0)->bind(image, true);
gGL.color4fv(color.mV);
@@ -955,10 +955,12 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor
if( render_center )
{
gGL.color4fv(center_color.mV);
+ gGL.diffuseColor4fv(center_color.mV);
gl_deep_circle( radius, width, steps );
}
else
{
+ gGL.diffuseColor4fv(side_color.mV);
gl_washer_2d(radius, radius - width, steps, side_color, side_color);
gGL.translateUI(0.f, 0.f, width);
gl_washer_2d(radius - width, radius, steps, side_color, side_color);
@@ -995,10 +997,18 @@ void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
// ...gray squares
gGL.color4f( .7f, .7f, .7f, alpha );
gGL.flush();
- glPolygonStipple( checkerboard );
- LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);
- gl_rect_2d(rect);
+ if (!LLGLSLShader::sNoFixedFunction)
+ { //polygon stipple is deprecated
+ glPolygonStipple( checkerboard );
+
+ LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);
+ gl_rect_2d(rect);
+ }
+ else
+ {
+ gl_rect_2d(rect);
+ }
gGL.flush();
}
@@ -1823,9 +1833,12 @@ void LLUI::setupPaths()
LLXMLNodePtr root;
BOOL success = LLXMLNode::parseFile(filename, root, NULL);
Paths paths;
- LLXUIParser parser;
- parser.readXUI(root, paths, filename);
+ if(success)
+ {
+ LLXUIParser parser;
+ parser.readXUI(root, paths, filename);
+ }
sXUIPaths.clear();
if (success && paths.validateBlock())
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 2fa260ded1..b9c843e931 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -118,7 +118,6 @@ LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)
mDoubleClickSignal(NULL),
mTransparencyType(TT_DEFAULT)
{
- mUICtrlHandle.bind(this);
}
void LLUICtrl::initFromParams(const Params& p)
@@ -460,7 +459,7 @@ void LLUICtrl::setControlVariable(LLControlVariable* control)
if (control)
{
mControlVariable = control;
- mControlConnection = mControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("value")));
+ mControlConnection = mControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("value")));
setValue(mControlVariable->getValue());
}
}
@@ -491,7 +490,7 @@ void LLUICtrl::setEnabledControlVariable(LLControlVariable* control)
if (control)
{
mEnabledControlVariable = control;
- mEnabledControlConnection = mEnabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("enabled")));
+ mEnabledControlConnection = mEnabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("enabled")));
setEnabled(mEnabledControlVariable->getValue().asBoolean());
}
}
@@ -506,7 +505,7 @@ void LLUICtrl::setDisabledControlVariable(LLControlVariable* control)
if (control)
{
mDisabledControlVariable = control;
- mDisabledControlConnection = mDisabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("disabled")));
+ mDisabledControlConnection = mDisabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("disabled")));
setEnabled(!(mDisabledControlVariable->getValue().asBoolean()));
}
}
@@ -521,7 +520,7 @@ void LLUICtrl::setMakeVisibleControlVariable(LLControlVariable* control)
if (control)
{
mMakeVisibleControlVariable = control;
- mMakeVisibleControlConnection = mMakeVisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("visible")));
+ mMakeVisibleControlConnection = mMakeVisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("visible")));
setVisible(mMakeVisibleControlVariable->getValue().asBoolean());
}
}
@@ -536,7 +535,7 @@ void LLUICtrl::setMakeInvisibleControlVariable(LLControlVariable* control)
if (control)
{
mMakeInvisibleControlVariable = control;
- mMakeInvisibleControlConnection = mMakeInvisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("invisible")));
+ mMakeInvisibleControlConnection = mMakeInvisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("invisible")));
setVisible(!(mMakeInvisibleControlVariable->getValue().asBoolean()));
}
}
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 3e055a9d06..fb2196bb16 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -223,7 +223,7 @@ public:
BOOL focusLastItem(BOOL prefer_text_fields = FALSE);
// Non Virtuals
- LLHandle<LLUICtrl> getUICtrlHandle() const { return mUICtrlHandle; }
+ LLHandle<LLUICtrl> getHandle() const { return getDerivedHandle<LLUICtrl>(); }
BOOL getIsChrome() const;
void setTabStop( BOOL b );
@@ -313,7 +313,6 @@ private:
BOOL mRequestsFront;
BOOL mTabStop;
BOOL mTentative;
- LLRootHandle<LLUICtrl> mUICtrlHandle;
ETypeTransparency mTransparencyType;
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
index 42b779bd28..fd9b3d9a6d 100644
--- a/indra/llui/llurlaction.cpp
+++ b/indra/llui/llurlaction.cpp
@@ -33,28 +33,28 @@
#include "llurlregistry.h"
// global state for the callback functions
-void (*LLUrlAction::sOpenURLCallback) (const std::string& url) = NULL;
-void (*LLUrlAction::sOpenURLInternalCallback) (const std::string& url) = NULL;
-void (*LLUrlAction::sOpenURLExternalCallback) (const std::string& url) = NULL;
-bool (*LLUrlAction::sExecuteSLURLCallback) (const std::string& url) = NULL;
+LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback;
+LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback;
+LLUrlAction::url_callback_t LLUrlAction::sOpenURLExternalCallback;
+LLUrlAction::execute_url_callback_t LLUrlAction::sExecuteSLURLCallback;
-void LLUrlAction::setOpenURLCallback(void (*cb) (const std::string& url))
+void LLUrlAction::setOpenURLCallback(url_callback_t cb)
{
sOpenURLCallback = cb;
}
-void LLUrlAction::setOpenURLInternalCallback(void (*cb) (const std::string& url))
+void LLUrlAction::setOpenURLInternalCallback(url_callback_t cb)
{
sOpenURLInternalCallback = cb;
}
-void LLUrlAction::setOpenURLExternalCallback(void (*cb) (const std::string& url))
+void LLUrlAction::setOpenURLExternalCallback(url_callback_t cb)
{
sOpenURLExternalCallback = cb;
}
-void LLUrlAction::setExecuteSLURLCallback(bool (*cb) (const std::string& url))
+void LLUrlAction::setExecuteSLURLCallback(execute_url_callback_t cb)
{
sExecuteSLURLCallback = cb;
}
@@ -63,7 +63,7 @@ void LLUrlAction::openURL(std::string url)
{
if (sOpenURLCallback)
{
- (*sOpenURLCallback)(url);
+ sOpenURLCallback(url);
}
}
@@ -71,7 +71,7 @@ void LLUrlAction::openURLInternal(std::string url)
{
if (sOpenURLInternalCallback)
{
- (*sOpenURLInternalCallback)(url);
+ sOpenURLInternalCallback(url);
}
}
@@ -79,7 +79,7 @@ void LLUrlAction::openURLExternal(std::string url)
{
if (sOpenURLExternalCallback)
{
- (*sOpenURLExternalCallback)(url);
+ sOpenURLExternalCallback(url);
}
}
@@ -87,18 +87,18 @@ void LLUrlAction::executeSLURL(std::string url)
{
if (sExecuteSLURLCallback)
{
- (*sExecuteSLURLCallback)(url);
+ sExecuteSLURLCallback(url);
}
}
void LLUrlAction::clickAction(std::string url)
{
// Try to handle as SLURL first, then http Url
- if ( (sExecuteSLURLCallback) && !(*sExecuteSLURLCallback)(url) )
+ if ( (sExecuteSLURLCallback) && !sExecuteSLURLCallback(url) )
{
if (sOpenURLCallback)
{
- (*sOpenURLCallback)(url);
+ sOpenURLCallback(url);
}
}
}
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
index 0132dbaaf0..c34960b826 100644
--- a/indra/llui/llurlaction.h
+++ b/indra/llui/llurlaction.h
@@ -29,6 +29,7 @@
#define LL_LLURLACTION_H
#include <string>
+#include <boost/function.hpp>
///
/// The LLUrlAction class provides a number of static functions that
@@ -77,17 +78,21 @@ public:
static void showProfile(std::string url);
/// specify the callbacks to enable this class's functionality
- static void setOpenURLCallback(void (*cb) (const std::string& url));
- static void setOpenURLInternalCallback(void (*cb) (const std::string& url));
- static void setOpenURLExternalCallback(void (*cb) (const std::string& url));
- static void setExecuteSLURLCallback(bool (*cb) (const std::string& url));
+ typedef boost::function<void (const std::string&)> url_callback_t;
+ typedef boost::function<bool(const std::string& url)> execute_url_callback_t;
+
+ static void setOpenURLCallback(url_callback_t cb);
+ static void setOpenURLInternalCallback(url_callback_t cb);
+ static void setOpenURLExternalCallback(url_callback_t cb);
+ static void setExecuteSLURLCallback(execute_url_callback_t cb);
private:
// callbacks for operations we can perform on Urls
- static void (*sOpenURLCallback) (const std::string& url);
- static void (*sOpenURLInternalCallback) (const std::string& url);
- static void (*sOpenURLExternalCallback) (const std::string& url);
- static bool (*sExecuteSLURLCallback) (const std::string& url);
+ static url_callback_t sOpenURLCallback;
+ static url_callback_t sOpenURLInternalCallback;
+ static url_callback_t sOpenURLExternalCallback;
+
+ static execute_url_callback_t sExecuteSLURLCallback;
};
#endif
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 3fd7e48428..486babb0ab 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -225,9 +225,11 @@ BOOL LLView::getUseBoundingRect() const
}
// virtual
-std::string LLView::getName() const
+const std::string& LLView::getName() const
{
- return mName.empty() ? std::string("(no name)") : mName;
+ static std::string no_name("(no name)");
+
+ return mName.empty() ? no_name : mName;
}
void LLView::sendChildToFront(LLView* child)
@@ -1215,7 +1217,7 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr
if ((childp->getVisible() && childp->getRect().isValid())
|| force_draw)
{
- glMatrixMode(GL_MODELVIEW);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
{
LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset, 0.f);
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 08828e55e6..f21fb37e18 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -97,7 +97,11 @@ private:
static std::vector<LLViewDrawContext*> sDrawContextStack;
};
-class LLView : public LLMouseHandler, public LLMortician, public LLFocusableElement
+class LLView
+: public LLMouseHandler, // handles mouse events
+ public LLFocusableElement, // handles keyboard events
+ public LLMortician, // lazy deletion
+ public LLHandleProvider<LLView> // passes out weak references to self
{
public:
struct Follows : public LLInitParam::ChoiceBlock<Follows>
@@ -306,8 +310,6 @@ public:
void popVisible() { setVisible(mLastVisible); }
BOOL getLastVisible() const { return mLastVisible; }
- LLHandle<LLView> getHandle() { mHandle.bind(this); return mHandle; }
-
U32 getFollows() const { return mReshapeFlags; }
BOOL followsLeft() const { return mReshapeFlags & FOLLOWS_LEFT; }
BOOL followsRight() const { return mReshapeFlags & FOLLOWS_RIGHT; }
@@ -431,7 +433,7 @@ public:
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
- /*virtual*/ std::string getName() const;
+ /*virtual*/ const std::string& getName() const;
/*virtual*/ void onMouseCaptureLost();
/*virtual*/ BOOL hasMouseCapture();
/*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
@@ -606,7 +608,6 @@ private:
BOOL mIsFocusRoot;
BOOL mUseBoundingRect; // hit test against bounding rectangle that includes all child elements
- LLRootHandle<LLView> mHandle;
BOOL mLastVisible;
S32 mNextInsertionOrdinal;
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index 4f251db93b..c75df86891 100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -105,8 +105,6 @@ LLStyle::Params::Params()
namespace LLInitParam
{
- BaseBlock::BaseBlock() {}
- BaseBlock::~BaseBlock() {}
Param::Param(BaseBlock* enclosing_block)
: mIsProvided(false)
{
@@ -114,7 +112,6 @@ namespace LLInitParam
const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
mEnclosingBlockOffset = (U16)(my_addr - block_addr);
}
- void BaseBlock::paramChanged(const Param& last_param, bool user_provided) {}
void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){}
void BaseBlock::addSynonym(Param& param, const std::string& synonym) {}
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index 627f3129e9..7183413463 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -63,9 +63,6 @@ S32 LLUIImage::getHeight() const
namespace LLInitParam
{
- BaseBlock::BaseBlock() {}
- BaseBlock::~BaseBlock() {}
-
BlockDescriptor::BlockDescriptor() {}
ParamDescriptor::ParamDescriptor(param_handle_t p,
merge_func_t merge_func,
@@ -77,8 +74,6 @@ namespace LLInitParam
S32 max_count){}
ParamDescriptor::~ParamDescriptor() {}
- void BaseBlock::paramChanged(const Param& last_param, bool user_provided) {}
-
void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){}
param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
void BaseBlock::addSynonym(Param& param, const std::string& synonym) {}