summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/CMakeLists.txt12
-rw-r--r--indra/llui/llbutton.cpp20
-rw-r--r--indra/llui/llbutton.h2
-rw-r--r--indra/llui/llcombobox.cpp66
-rw-r--r--indra/llui/llcombobox.h10
-rw-r--r--indra/llui/llfloater.cpp52
-rw-r--r--indra/llui/llfloater.h3
-rw-r--r--indra/llui/llfloaterreg.cpp52
-rw-r--r--indra/llui/llfloaterreg.h1
-rw-r--r--indra/llui/llfolderview.cpp14
-rw-r--r--indra/llui/llfolderviewitem.cpp14
-rw-r--r--indra/llui/llfolderviewitem.h15
-rw-r--r--indra/llui/llfolderviewmodel.h6
-rw-r--r--indra/llui/lliconctrl.cpp13
-rw-r--r--indra/llui/lliconctrl.h7
-rw-r--r--indra/llui/lllayoutstack.cpp6
-rw-r--r--indra/llui/lllineeditor.cpp17
-rw-r--r--indra/llui/lllineeditor.h2
-rw-r--r--indra/llui/llmenubutton.cpp8
-rw-r--r--indra/llui/llmenubutton.h3
-rw-r--r--indra/llui/llmenugl.cpp70
-rw-r--r--indra/llui/llmenugl.h5
-rw-r--r--indra/llui/llmodaldialog.cpp14
-rw-r--r--indra/llui/llnotifications.cpp16
-rw-r--r--indra/llui/llnotifications.h19
-rw-r--r--indra/llui/llnotificationslistener.h3
-rw-r--r--indra/llui/llnotificationtemplate.h2
-rw-r--r--indra/llui/llpanel.cpp4
-rw-r--r--indra/llui/llprogressbar.cpp24
-rw-r--r--indra/llui/llscrolllistcell.cpp23
-rw-r--r--indra/llui/llscrolllistcell.h7
-rw-r--r--indra/llui/llscrolllistctrl.cpp118
-rw-r--r--indra/llui/llscrolllistctrl.h14
-rw-r--r--indra/llui/llscrolllistitem.cpp3
-rw-r--r--indra/llui/llscrolllistitem.h4
-rw-r--r--indra/llui/llspinctrl.cpp2
-rw-r--r--indra/llui/llstatbar.cpp37
-rw-r--r--indra/llui/llstatbar.h6
-rw-r--r--indra/llui/lltabcontainer.cpp18
-rw-r--r--indra/llui/lltextbase.cpp86
-rw-r--r--indra/llui/lltextbase.h9
-rw-r--r--indra/llui/lltextbox.cpp4
-rw-r--r--indra/llui/lltexteditor.h1
-rw-r--r--indra/llui/lltextutil.cpp16
-rw-r--r--indra/llui/lltextutil.h12
-rw-r--r--indra/llui/lltrans.cpp8
-rw-r--r--indra/llui/llui.cpp1
-rw-r--r--indra/llui/lluictrl.cpp17
-rw-r--r--indra/llui/lluictrlfactory.cpp15
-rw-r--r--indra/llui/lluictrlfactory.h16
-rw-r--r--indra/llui/llurlaction.cpp9
-rw-r--r--indra/llui/llurlaction.h1
-rw-r--r--indra/llui/llurlentry.cpp69
-rw-r--r--indra/llui/llurlentry.h13
-rw-r--r--indra/llui/llurlregistry.cpp14
-rw-r--r--indra/llui/llview.cpp13
-rw-r--r--indra/llui/llview.h3
-rw-r--r--indra/llui/llviewereventrecorder.h11
-rw-r--r--indra/llui/llviewmodel.cpp20
-rw-r--r--indra/llui/llviewmodel.h3
60 files changed, 781 insertions, 272 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 68019734ab..44c61dcdbc 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -13,7 +13,7 @@ include(LLCoreHttp)
include(LLRender)
include(LLWindow)
include(LLCoreHttp)
-include(LLVFS)
+include(LLFileSystem)
include(LLXML)
include_directories(
@@ -25,7 +25,7 @@ include_directories(
${LLMESSAGE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
- ${LLVFS_INCLUDE_DIRS}
+ ${LLFILESYSTEM_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LIBS_PREBUILD_DIR}/include/hunspell
)
@@ -289,7 +289,7 @@ target_link_libraries(llui
${LLINVENTORY_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLCOREHTTP_LIBRARIES}
- ${LLVFS_LIBRARIES} # ugh, just for LLDir
+ ${LLFILESYSTEM_LIBRARIES}
${LLXUIXML_LIBRARIES}
${LLXML_LIBRARIES}
${LLMATH_LIBRARIES}
@@ -312,6 +312,10 @@ if(LL_TESTS)
${BOOST_FIBER_LIBRARY} ${BOOST_CONTEXT_LIBRARY} ${BOOST_SYSTEM_LIBRARY}
${WINDOWS_LIBRARIES})
if(NOT LINUX)
- LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "${test_libs}")
+ if(WINDOWS)
+ LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "imm32;${test_libs}")
+ else(WINDOWS)
+ LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "${test_libs}")
+ endif(WINDOWS)
endif(NOT LINUX)
endif(LL_TESTS)
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 0e59fdf519..8028f397f3 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -102,6 +102,7 @@ LLButton::Params::Params()
scale_image("scale_image", true),
hover_glow_amount("hover_glow_amount"),
commit_on_return("commit_on_return", true),
+ commit_on_capture_lost("commit_on_capture_lost", false),
display_pressed_state("display_pressed_state", true),
use_draw_context_alpha("use_draw_context_alpha", true),
badge("badge"),
@@ -165,6 +166,7 @@ LLButton::LLButton(const LLButton::Params& p)
mBottomVPad(p.pad_bottom),
mHoverGlowStrength(p.hover_glow_amount),
mCommitOnReturn(p.commit_on_return),
+ mCommitOnCaptureLost(p.commit_on_capture_lost),
mFadeWhenDisabled(FALSE),
mForcePressedState(false),
mDisplayPressedState(p.display_pressed_state),
@@ -475,6 +477,10 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
// We only handle the click if the click both started and ended within us
if( hasMouseCapture() )
{
+ // reset timers before focus change, to not cause
+ // additional commits if mCommitOnCaptureLost.
+ resetMouseDownTimer();
+
// Always release the mouse
gFocusMgr.setMouseCapture( NULL );
@@ -489,8 +495,6 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
// Regardless of where mouseup occurs, handle callback
if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD());
- resetMouseDownTimer();
-
// DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
// If mouseup in the widget, it's been clicked
if (pointInView(x, y))
@@ -1195,6 +1199,18 @@ void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignmen
void LLButton::onMouseCaptureLost()
{
+ if (mCommitOnCaptureLost
+ && mMouseDownTimer.getStarted())
+ {
+ if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD());
+
+ if (mIsToggle)
+ {
+ toggleState();
+ }
+
+ LLUICtrl::onCommit();
+ }
resetMouseDownTimer();
}
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 572d36996c..ccd31e90c0 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -124,6 +124,7 @@ public:
Optional<bool> is_toggle,
scale_image,
commit_on_return,
+ commit_on_capture_lost,
display_pressed_state;
Optional<F32> hover_glow_amount;
@@ -374,6 +375,7 @@ protected:
F32 mCurGlowStrength;
bool mCommitOnReturn;
+ bool mCommitOnCaptureLost;
bool mFadeWhenDisabled;
bool mForcePressedState;
bool mDisplayPressedState;
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 52dc908655..9ca05a16f3 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -113,6 +113,10 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p)
}
mArrowImage = button_params.image_unselected;
+ if (mArrowImage.notNull())
+ {
+ mImageLoadedConnection = mArrowImage->addLoadedCallback(boost::bind(&LLComboBox::imageLoaded, this));
+ }
mButton = LLUICtrlFactory::create<LLButton>(button_params);
@@ -183,6 +187,7 @@ LLComboBox::~LLComboBox()
// explicitly disconect this signal, since base class destructor might fire top lost
mTopLostSignalConnection.disconnect();
+ mImageLoadedConnection.disconnect();
}
@@ -1037,6 +1042,67 @@ void LLComboBox::prearrangeList(std::string filter)
}
}
+
+//============================================================================
+// ll::ui::SearchableControl functions
+
+//virtual
+std::string LLComboBox::_getSearchText() const
+{
+ std::string res;
+ if (mList)
+ {
+ // getAllData returns a full copy of content, might be a
+ // better option to implement an mList->getSearchText(column)
+ std::vector<LLScrollListItem*> data = mList->getAllData();
+ std::vector<LLScrollListItem*>::iterator iter = data.begin();
+ while (iter != data.end())
+ {
+ LLScrollListCell* cell = (*iter)->getColumn(0);
+ if (cell)
+ {
+ std::string whitelist_url = cell->getValue().asString();
+ res += cell->getValue().asString();
+ }
+ iter++;
+ }
+ }
+ return res + getToolTip();
+}
+
+//virtual
+void LLComboBox::onSetHighlight() const
+{
+ if (mButton)
+ {
+ mButton->ll::ui::SearchableControl::setHighlighted(ll::ui::SearchableControl::getHighlighted());
+ }
+}
+
+void LLComboBox::imageLoaded()
+{
+ static LLUICachedControl<S32> drop_shadow_button("DropShadowButton", 0);
+
+ if (mAllowTextEntry)
+ {
+ LLRect rect = getLocalRect();
+ S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
+ S32 shadow_size = drop_shadow_button;
+ mButton->setRect(LLRect(getRect().getWidth() - llmax(8, arrow_width) - 2 * shadow_size,
+ rect.mTop, rect.mRight, rect.mBottom));
+ if (mButton->getVisible())
+ {
+ // recalculate field size
+ if (mTextEntry)
+ {
+ LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
+ text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * drop_shadow_button;
+ mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
+ }
+ }
+ }
+}
+
//============================================================================
// LLCtrlListInterface functions
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 4af3313162..cac8850a25 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -44,7 +44,9 @@ class LLFontGL;
class LLViewBorder;
class LLComboBox
-: public LLUICtrl, public LLCtrlListInterface
+: public LLUICtrl
+, public LLCtrlListInterface
+, public ll::ui::SearchableControl
{
public:
typedef enum e_preferred_position
@@ -100,6 +102,11 @@ protected:
void initFromParams(const Params&);
void prearrangeList(std::string filter = "");
+ virtual std::string _getSearchText() const;
+ virtual void onSetHighlight() const;
+
+ void imageLoaded();
+
public:
// LLView interface
virtual void onFocusLost();
@@ -239,6 +246,7 @@ private:
commit_callback_t mTextChangedCallback;
commit_callback_t mSelectionCallback;
boost::signals2::connection mTopLostSignalConnection;
+ boost::signals2::connection mImageLoadedConnection;
commit_signal_t mOnReturnSignal;
S32 mLastSelectedIndex;
};
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 6f341bc0cd..763b67bb3a 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -259,6 +259,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
mMinHeight(p.min_height),
mHeaderHeight(p.header_height),
mLegacyHeaderHeight(p.legacy_header_height),
+ mDefaultRectForGroup(true),
mMinimized(FALSE),
mForeground(FALSE),
mFirstLook(TRUE),
@@ -761,17 +762,13 @@ void LLFloater::closeFloater(bool app_quitting)
for(handle_set_iter_t dependent_it = mDependents.begin();
dependent_it != mDependents.end(); )
{
-
LLFloater* floaterp = dependent_it->get();
- if (floaterp)
- {
- ++dependent_it;
- floaterp->closeFloater(app_quitting);
- }
- else
- {
- mDependents.erase(dependent_it++);
- }
+ dependent_it = mDependents.erase(dependent_it);
+ if (floaterp)
+ {
+ floaterp->mDependeeHandle = LLHandle<LLFloater>();
+ floaterp->closeFloater(app_quitting);
+ }
}
cleanupHandles();
@@ -906,7 +903,10 @@ bool LLFloater::applyRectControl()
if (last_in_group && last_in_group != this)
{
// other floaters in our group, position ourselves relative to them and don't save the rect
- mRectControl.clear();
+ if (mDefaultRectForGroup)
+ {
+ mRectControl.clear();
+ }
mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP;
}
else
@@ -1439,7 +1439,7 @@ void LLFloater::cleanupHandles()
LLFloater* floaterp = dependent_it->get();
if (!floaterp)
{
- mDependents.erase(dependent_it++);
+ dependent_it = mDependents.erase(dependent_it);
}
else
{
@@ -3295,11 +3295,9 @@ boost::signals2::connection LLFloater::setCloseCallback( const commit_signal_t::
return mCloseSignal.connect(cb);
}
-LLTrace::BlockTimerStatHandle POST_BUILD("Floater Post Build");
-static LLTrace::BlockTimerStatHandle FTM_EXTERNAL_FLOATER_LOAD("Load Extern Floater Reference");
-
bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node)
{
+ LL_PROFILE_ZONE_SCOPED;
Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>());
Params params(default_params);
@@ -3326,7 +3324,6 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
LLUICtrlFactory::instance().pushFileName(xml_filename);
- LL_RECORD_BLOCK_TIME(FTM_EXTERNAL_FLOATER_LOAD);
if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml))
{
LL_WARNS() << "Couldn't parse panel from: " << xml_filename << LL_ENDL;
@@ -3402,12 +3399,8 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
}
BOOL result;
- {
- LL_RECORD_BLOCK_TIME(POST_BUILD);
-
- result = postBuild();
- }
-
+ result = postBuild();
+
if (!result)
{
LL_ERRS() << "Failed to construct floater " << getName() << LL_ENDL;
@@ -3451,11 +3444,9 @@ bool LLFloater::isVisible(const LLFloater* floater)
return floater && floater->getVisible();
}
-static LLTrace::BlockTimerStatHandle FTM_BUILD_FLOATERS("Build Floaters");
-
bool LLFloater::buildFromFile(const std::string& filename)
{
- LL_RECORD_BLOCK_TIME(FTM_BUILD_FLOATERS);
+ LL_PROFILE_ZONE_SCOPED;
LLXMLNodePtr root;
if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
@@ -3517,8 +3508,15 @@ void LLFloater::stackWith(LLFloater& other)
}
next_rect.translate(floater_offset, -floater_offset);
- next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight());
-
+ const LLRect& rect = getControlGroup()->getRect(mRectControl);
+ if (rect.notEmpty() && !mDefaultRectForGroup && mResizable)
+ {
+ next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight()));
+ }
+ else
+ {
+ next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight());
+ }
setShape(next_rect);
if (!other.getHost())
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 1d4aff31eb..282f7a80ac 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -349,6 +349,8 @@ public:
// handle refocusing.
static void closeFrontmostFloater();
+ static bool isQuitRequested() { return sQuitting; }
+
// LLNotification::Params contextualNotification(const std::string& name)
// {
// return LLNotification::Params(name).context(mNotificationContext);
@@ -455,6 +457,7 @@ public:
protected:
bool mSaveRect;
+ bool mDefaultRectForGroup;
std::string mRectControl;
std::string mPosXControl;
std::string mPosYControl;
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 36a0cb0fd0..f888d7ff68 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -531,6 +531,58 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
}
// static
+// Same as toggleInstanceOrBringToFront but does not close floater.
+// unlike showInstance() does not trigger onOpen() if already open
+void LLFloaterReg::showInstanceOrBringToFront(const LLSD& sdname, const LLSD& key)
+{
+ std::string name = sdname.asString();
+ LLFloater* instance = getInstance(name, key);
+
+
+ if (!instance)
+ {
+ LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL;
+ return;
+ }
+
+ // If hosted, we need to take that into account
+ LLFloater* host = instance->getHost();
+
+ if (host)
+ {
+ if (host->isMinimized() || !host->isShown() || !host->isFrontmost())
+ {
+ host->setMinimized(FALSE);
+ instance->openFloater(key);
+ instance->setVisibleAndFrontmost(true, key);
+ }
+ else if (!instance->getVisible())
+ {
+ instance->openFloater(key);
+ instance->setVisibleAndFrontmost(true, key);
+ instance->setFocus(TRUE);
+ }
+ }
+ else
+ {
+ if (instance->isMinimized())
+ {
+ instance->setMinimized(FALSE);
+ instance->setVisibleAndFrontmost(true, key);
+ }
+ else if (!instance->isShown())
+ {
+ instance->openFloater(key);
+ instance->setVisibleAndFrontmost(true, key);
+ }
+ else if (!instance->isFrontmost())
+ {
+ instance->setVisibleAndFrontmost(true, key);
+ }
+ }
+}
+
+// static
U32 LLFloaterReg::getVisibleFloaterInstanceCount()
{
U32 count = 0;
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index a457a15673..eaa59b1d6f 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -129,6 +129,7 @@ public:
// Callback wrappers
static void toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD());
+ static void showInstanceOrBringToFront(const LLSD& sdname, const LLSD& key = LLSD());
// Typed find / get / show
template <class T>
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 622c9edba7..ea2ca68e47 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -189,7 +189,6 @@ LLFolderView::LLFolderView(const Params& p)
mViewModel(p.view_model),
mGroupedItemModel(p.grouped_item_model)
{
- claimMem(mViewModel);
LLPanel* panel = p.parent_panel;
mParentPanel = panel->getHandle();
mViewModel->setFolderView(this);
@@ -257,6 +256,8 @@ LLFolderView::LLFolderView(const Params& p)
mPopupMenuHandle = menu->getHandle();
mViewModelItem->openItem();
+
+ mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited.
}
// Destroys the object
@@ -337,11 +338,9 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height )
return ll_round(mTargetHeight);
}
-static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View");
-
void LLFolderView::filter( LLFolderViewFilter& filter )
{
- LL_RECORD_BLOCK_TIME(FTM_FILTER);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
static LLCachedControl<S32> time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
static LLCachedControl<S32> time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1);
filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100));
@@ -503,10 +502,9 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected)
return rv;
}
-static LLTrace::BlockTimerStatHandle FTM_SANITIZE_SELECTION("Sanitize Selection");
void LLFolderView::sanitizeSelection()
{
- LL_RECORD_BLOCK_TIME(FTM_SANITIZE_SELECTION);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
// store off current item in case it is automatically deselected
// and we want to preserve context
LLFolderViewItem* original_selected_item = getCurSelectedItem();
@@ -1621,7 +1619,6 @@ void LLFolderView::setShowSingleSelection(bool show)
}
}
-static LLTrace::BlockTimerStatHandle FTM_AUTO_SELECT("Open and Select");
static LLTrace::BlockTimerStatHandle FTM_INVENTORY("Inventory");
// Main idle routine
@@ -1629,7 +1626,7 @@ void LLFolderView::update()
{
// If this is associated with the user's inventory, don't do anything
// until that inventory is loaded up.
- LL_RECORD_BLOCK_TIME(FTM_INVENTORY);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_INVENTORY);
// If there's no model, the view is in suspended state (being deleted) and shouldn't be updated
if (getFolderViewModel() == NULL)
@@ -1657,7 +1654,6 @@ void LLFolderView::update()
// automatically show matching items, and select first one if we had a selection
if (mNeedsAutoSelect)
{
- LL_RECORD_BLOCK_TIME(FTM_AUTO_SELECT);
// select new item only if a filtered item not currently selected and there was a selection
LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back();
if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible())
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 835d3b781d..d5988dadbc 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -132,7 +132,6 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mCutGeneration(0),
mLabelStyle( LLFontGL::NORMAL ),
mHasVisibleChildren(FALSE),
- mIsFolderComplete(true),
mLocalIndentation(p.folder_indentation),
mIndentation(0),
mItemHeight(p.item_height),
@@ -1003,11 +1002,11 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
mCurHeight(0.f),
mTargetHeight(0.f),
mAutoOpenCountdown(0.f),
+ mIsFolderComplete(false), // folder might have children that are not loaded yet.
+ mAreChildrenInited(false), // folder might have children that are not built yet.
mLastArrangeGeneration( -1 ),
mLastCalculatedWidth(0)
{
- // folder might have children that are not loaded yet. Mark it as incomplete until chance to check it.
- mIsFolderComplete = false;
}
void LLFolderViewFolder::updateLabelRotation()
@@ -1063,13 +1062,16 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )
{
// Sort before laying out contents
// Note that we sort from the root (CHUI-849)
- getRoot()->getFolderViewModel()->sort(this);
+ if (mAreChildrenInited)
+ {
+ getRoot()->getFolderViewModel()->sort(this);
+ }
LL_RECORD_BLOCK_TIME(FTM_ARRANGE);
// evaluate mHasVisibleChildren
mHasVisibleChildren = false;
- if (getViewModelItem()->descendantsPassedFilter())
+ if (mAreChildrenInited && getViewModelItem()->descendantsPassedFilter())
{
// We have to verify that there's at least one child that's not filtered out
bool found = false;
@@ -1095,7 +1097,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )
mHasVisibleChildren = found;
}
- if (!mIsFolderComplete)
+ if (!mIsFolderComplete && mAreChildrenInited)
{
mIsFolderComplete = getFolderViewModel()->isFolderComplete(this);
}
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 616d2e7d86..ee20d048fd 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -116,7 +116,6 @@ protected:
F32 mControlLabelRotation;
LLFolderView* mRoot;
bool mHasVisibleChildren,
- mIsFolderComplete, // indicates that some children were not loaded/added yet
mIsCurSelection,
mDragAndDropTarget,
mIsMouseOverTitle,
@@ -219,7 +218,10 @@ public:
BOOL hasVisibleChildren() { return mHasVisibleChildren; }
// true if object can't have children
- BOOL isFolderComplete() { return mIsFolderComplete; }
+ virtual bool isFolderComplete() { return true; }
+ // true if object can't have children
+ virtual bool areChildrenInited() { return true; }
+ virtual void setChildrenInited(bool inited) { }
// Call through to the viewed object and return true if it can be
// removed. Returns true if it's removed.
@@ -334,6 +336,8 @@ protected:
S32 mLastArrangeGeneration;
S32 mLastCalculatedWidth;
bool mNeedsSort;
+ bool mIsFolderComplete; // indicates that some children were not loaded/added yet
+ bool mAreChildrenInited; // indicates that no children were initialized
public:
typedef enum e_recurse_type
@@ -385,6 +389,13 @@ public:
// destroys this folder, and all children
virtual void destroyView();
+ // whether known children are fully loaded (arrange sets to true)
+ virtual bool isFolderComplete() { return mIsFolderComplete; }
+
+ // whether known children are fully built
+ virtual bool areChildrenInited() { return mAreChildrenInited; }
+ virtual void setChildrenInited(bool inited) { mAreChildrenInited = inited; }
+
// extractItem() removes the specified item from the folder, but
// doesn't delete it.
virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true);
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index e62b2779dd..093e213be3 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -108,11 +108,10 @@ public:
virtual S32 getFirstRequiredGeneration() const = 0;
};
-class LLFolderViewModelInterface : public LLTrace::MemTrackable<LLFolderViewModelInterface>
+class LLFolderViewModelInterface
{
public:
LLFolderViewModelInterface()
- : LLTrace::MemTrackable<LLFolderViewModelInterface>("LLFolderViewModelInterface")
{}
virtual ~LLFolderViewModelInterface() {}
@@ -133,11 +132,10 @@ public:
// This is an abstract base class that users of the folderview classes
// would use to bridge the folder view with the underlying data
-class LLFolderViewModelItem : public LLRefCount, public LLTrace::MemTrackable<LLFolderViewModelItem>
+class LLFolderViewModelItem : public LLRefCount
{
public:
LLFolderViewModelItem()
- : LLTrace::MemTrackable<LLFolderViewModelItem>("LLFolderViewModelItem")
{}
virtual ~LLFolderViewModelItem() { }
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index 82b01e705d..e01aba402e 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -35,6 +35,7 @@
#include "llui.h"
#include "lluictrlfactory.h"
#include "lluiimage.h"
+#include "llwindow.h"
static LLDefaultChildRegistry::Register<LLIconCtrl> r("icon");
@@ -42,6 +43,7 @@ LLIconCtrl::Params::Params()
: image("image_name"),
color("color"),
use_draw_context_alpha("use_draw_context_alpha", true),
+ interactable("interactable", false),
scale_image("scale_image"),
min_width("min_width", 0),
min_height("min_height", 0)
@@ -52,6 +54,7 @@ LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p)
mColor(p.color()),
mImagep(p.image),
mUseDrawContextAlpha(p.use_draw_context_alpha),
+ mInteractable(p.interactable),
mPriority(0),
mMinWidth(p.min_width),
mMinHeight(p.min_height),
@@ -81,6 +84,16 @@ void LLIconCtrl::draw()
LLUICtrl::draw();
}
+BOOL LLIconCtrl::handleHover(S32 x, S32 y, MASK mask)
+{
+ if (mInteractable && getEnabled())
+ {
+ getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
+ }
+ return LLUICtrl::handleHover(x, y, mask);
+}
+
// virtual
// value might be a string or a UUID
void LLIconCtrl::setValue(const LLSD& value)
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index dd83e78fd3..9c3b517bca 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -48,7 +48,8 @@ public:
{
Optional<LLUIImage*> image;
Optional<LLUIColor> color;
- Optional<bool> use_draw_context_alpha;
+ Optional<bool> use_draw_context_alpha,
+ interactable;
Optional<S32> min_width,
min_height;
Ignored scale_image;
@@ -67,6 +68,9 @@ public:
// llview overrides
virtual void draw();
+ // llview overrides
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+
// lluictrl overrides
virtual void setValue(const LLSD& value );
@@ -88,6 +92,7 @@ protected:
// If set to true (default), use the draw context transparency.
// If false, will use transparency returned by getCurrentTransparency(). See STORM-698.
bool mUseDrawContextAlpha;
+ bool mInteractable;
private:
LLUIColor mColor;
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 29a156e933..77938edf27 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -340,8 +340,6 @@ void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
mNeedsLayout = true;
}
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_LAYOUT("Update LayoutStacks");
-
class LLImagePanel : public LLPanel
{
public:
@@ -369,7 +367,7 @@ private:
void LLLayoutStack::updateLayout()
{
- LL_RECORD_BLOCK_TIME(FTM_UPDATE_LAYOUT);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
if (!mNeedsLayout) return;
@@ -397,7 +395,6 @@ void LLLayoutStack::updateLayout()
space_to_distribute += panelp ? ll_round((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0;
S32 remaining_space = space_to_distribute;
- F32 fraction_distributed = 0.f;
if (space_to_distribute > 0 && total_visible_fraction > 0.f)
{ // give space proportionally to visible auto resize panels
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
@@ -406,7 +403,6 @@ void LLLayoutStack::updateLayout()
{
F32 fraction_to_distribute = (panelp->mFractionalSize * panelp->getAutoResizeFactor()) / (total_visible_fraction);
S32 delta = ll_round((F32)space_to_distribute * fraction_to_distribute);
- fraction_distributed += fraction_to_distribute;
panelp->mTargetDim += delta;
remaining_space -= delta;
}
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 1badd54fca..33037b5001 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -175,6 +175,14 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mTripleClickTimer.reset();
setText(p.default_text());
+ if (p.initial_value.isProvided()
+ && !p.control_name.isProvided())
+ {
+ // Initial value often is descriptive, like "Type some ID here"
+ // and can be longer than size limitation, ignore size
+ setText(p.initial_value.getValue().asString(), false);
+ }
+
// Initialize current history line iterator
mCurrentHistoryLine = mLineHistory.begin();
@@ -390,6 +398,11 @@ void LLLineEditor::updateTextPadding()
void LLLineEditor::setText(const LLStringExplicit &new_text)
{
+ setText(new_text, true);
+}
+
+void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit)
+{
// If new text is identical, don't copy and don't move insertion point
if (mText.getString() == new_text)
{
@@ -407,13 +420,13 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived);
std::string truncated_utf8 = new_text;
- if (truncated_utf8.size() > (U32)mMaxLengthBytes)
+ if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes)
{
truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes);
}
mText.assign(truncated_utf8);
- if (mMaxLengthChars)
+ if (use_size_limit && mMaxLengthChars)
{
mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars));
}
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index f84625bea7..ae4e05c065 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -320,6 +320,8 @@ private:
virtual S32 getPreeditFontSize() const;
virtual LLWString getPreeditString() const { return getWText(); }
+ void setText(const LLStringExplicit &new_text, bool use_size_limit);
+
void setContextMenu(LLContextMenu* new_context_menu);
protected:
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 303afcda15..583704418b 100644
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -40,6 +40,7 @@ void LLMenuButton::MenuPositions::declareValues()
declare("topleft", MP_TOP_LEFT);
declare("topright", MP_TOP_RIGHT);
declare("bottomleft", MP_BOTTOM_LEFT);
+ declare("bottomright", MP_BOTTOM_RIGHT);
}
LLMenuButton::Params::Params()
@@ -212,6 +213,13 @@ void LLMenuButton::updateMenuOrigin()
mY = rect.mBottom;
break;
}
+ case MP_BOTTOM_RIGHT:
+ {
+ const LLRect& menu_rect = menu->getRect();
+ mX = rect.mRight - menu_rect.getWidth();
+ mY = rect.mBottom;
+ break;
+ }
}
}
diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h
index 67ec1983b3..e42f8f53bd 100644
--- a/indra/llui/llmenubutton.h
+++ b/indra/llui/llmenubutton.h
@@ -41,7 +41,8 @@ public:
{
MP_TOP_LEFT,
MP_TOP_RIGHT,
- MP_BOTTOM_LEFT
+ MP_BOTTOM_LEFT,
+ MP_BOTTOM_RIGHT
} EMenuPosition;
struct MenuPositions
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index cdaf03ebde..4264028338 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -1363,6 +1363,9 @@ public:
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
+
+ virtual void onFocusLost();
+ virtual void setFocus(BOOL b);
};
LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const Params& p) :
@@ -1517,6 +1520,21 @@ BOOL LLMenuItemBranchDownGL::handleAcceleratorKey(KEY key, MASK mask)
return handled;
}
+void LLMenuItemBranchDownGL::onFocusLost()
+{
+ // needed for tab-based selection
+ LLMenuItemBranchGL::onFocusLost();
+ LLMenuGL::setKeyboardMode(FALSE);
+ setHighlight(FALSE);
+}
+
+void LLMenuItemBranchDownGL::setFocus(BOOL b)
+{
+ // needed for tab-based selection
+ LLMenuItemBranchGL::setFocus(b);
+ LLMenuGL::setKeyboardMode(b);
+ setHighlight(b);
+}
BOOL LLMenuItemBranchDownGL::handleKeyHere(KEY key, MASK mask)
{
@@ -2362,6 +2380,16 @@ void LLMenuGL::arrange( void )
(*item_iter)->setRect( rect );
}
}
+
+
+ if (getTornOff())
+ {
+ LLTearOffMenu * torn_off_menu = dynamic_cast<LLTearOffMenu*>(getParent());
+ if (torn_off_menu)
+ {
+ torn_off_menu->updateSize();
+ }
+ }
}
if (mKeepFixedSize)
{
@@ -3879,7 +3907,8 @@ void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item)
/// Class LLTearOffMenu
///============================================================================
LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) :
- LLFloater(LLSD())
+ LLFloater(LLSD()),
+ mQuitRequested(false)
{
S32 floater_header_size = getHeaderHeight();
@@ -3894,7 +3923,7 @@ LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) :
LLRect rect;
menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView);
// make sure this floater is big enough for menu
- mTargetHeight = (F32)(rect.getHeight() + floater_header_size);
+ mTargetHeight = rect.getHeight() + floater_header_size;
reshape(rect.getWidth(), rect.getHeight());
setRect(rect);
@@ -3926,19 +3955,24 @@ LLTearOffMenu::~LLTearOffMenu()
void LLTearOffMenu::draw()
{
mMenu->setBackgroundVisible(isBackgroundOpaque());
- mMenu->needsArrange();
if (getRect().getHeight() != mTargetHeight)
{
// animate towards target height
- reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f))));
+ reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), (F32)mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f))));
}
+ mMenu->needsArrange();
LLFloater::draw();
}
void LLTearOffMenu::onFocusReceived()
{
- // if nothing is highlighted, just highlight first item
+ if (mQuitRequested)
+ {
+ return;
+ }
+
+ // if nothing is highlighted, just highlight first item
if (!mMenu->getHighlightedItem())
{
mMenu->highlightNextItem(NULL);
@@ -4014,6 +4048,31 @@ LLTearOffMenu* LLTearOffMenu::create(LLMenuGL* menup)
return tearoffp;
}
+void LLTearOffMenu::updateSize()
+{
+ if (mMenu)
+ {
+ S32 floater_header_size = getHeaderHeight();
+ const LLRect &floater_rect = getRect();
+ LLRect new_rect;
+ mMenu->localRectToOtherView(LLRect(-1, mMenu->getRect().getHeight() + floater_header_size, mMenu->getRect().getWidth() + 3, 0), &new_rect, gFloaterView);
+
+ if (floater_rect.getWidth() != new_rect.getWidth()
+ || mTargetHeight != new_rect.getHeight())
+ {
+ // make sure this floater is big enough for menu
+ mTargetHeight = new_rect.getHeight();
+ reshape(new_rect.getWidth(), mTargetHeight);
+
+ // Restore menu position
+ LLRect menu_rect = mMenu->getRect();
+ menu_rect.setOriginAndSize(1, 1,
+ menu_rect.getWidth(), menu_rect.getHeight());
+ mMenu->setRect(menu_rect);
+ }
+ }
+}
+
void LLTearOffMenu::closeTearOff()
{
removeChild(mMenu);
@@ -4024,6 +4083,7 @@ void LLTearOffMenu::closeTearOff()
mMenu->setVisible(FALSE);
mMenu->setTornOff(FALSE);
mMenu->setDropShadowed(TRUE);
+ mQuitRequested = true;
}
LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p)
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 273bd789c4..abbfd9a24a 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -873,6 +873,8 @@ public:
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual void translate(S32 x, S32 y);
+ void updateSize();
+
private:
LLTearOffMenu(LLMenuGL* menup);
@@ -880,7 +882,8 @@ private:
LLView* mOldParent;
LLMenuGL* mMenu;
- F32 mTargetHeight;
+ S32 mTargetHeight;
+ bool mQuitRequested;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp
index 5cfa8ea973..3e5978eb59 100644
--- a/indra/llui/llmodaldialog.cpp
+++ b/indra/llui/llmodaldialog.cpp
@@ -100,7 +100,10 @@ void LLModalDialog::onOpen(const LLSD& key)
if (!sModalStack.empty())
{
LLModalDialog* front = sModalStack.front();
- front->setVisible(FALSE);
+ if (front != this)
+ {
+ front->setVisible(FALSE);
+ }
}
// This is a modal dialog. It sucks up all mouse and keyboard operations.
@@ -108,7 +111,14 @@ void LLModalDialog::onOpen(const LLSD& key)
LLUI::getInstance()->addPopup(this);
setFocus(TRUE);
- sModalStack.push_front( this );
+ std::list<LLModalDialog*>::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this);
+ if (iter != sModalStack.end())
+ {
+ // if already present, we want to move it to front.
+ sModalStack.erase(iter);
+ }
+
+ sModalStack.push_front(this);
}
}
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index b791a19c2b..7c381161c9 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -1387,7 +1387,7 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)
LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName)
{
- return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName));
+ return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName).get());
}
@@ -1700,6 +1700,20 @@ void LLNotifications::add(const LLNotificationPtr pNotif)
updateItem(LLSD().with("sigtype", "add").with("id", pNotif->id()), pNotif);
}
+void LLNotifications::load(const LLNotificationPtr pNotif)
+{
+ if (pNotif == NULL) return;
+
+ // first see if we already have it -- if so, that's a problem
+ LLNotificationSet::iterator it=mItems.find(pNotif);
+ if (it != mItems.end())
+ {
+ LL_ERRS() << "Notification loaded a second time to the master notification channel." << LL_ENDL;
+ }
+
+ updateItem(LLSD().with("sigtype", "load").with("id", pNotif->id()), pNotif);
+}
+
void LLNotifications::cancel(LLNotificationPtr pNotif)
{
if (pNotif == NULL || pNotif->isCancelled()) return;
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index b1123d27e5..921398a693 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -84,7 +84,6 @@
#include <sstream>
#include <boost/utility.hpp>
-#include <boost/shared_ptr.hpp>
#include <boost/type_traits.hpp>
#include <boost/signals2.hpp>
#include <boost/range.hpp>
@@ -131,7 +130,7 @@ public:
typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder;
-typedef boost::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr;
+typedef std::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr;
typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry;
typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration;
@@ -276,19 +275,19 @@ private:
bool mInvertSetting;
};
-typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
+typedef std::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
struct LLNotificationTemplate;
// we want to keep a map of these by name, and it's best to manage them
// with smart pointers
-typedef boost::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr;
+typedef std::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr;
struct LLNotificationVisibilityRule;
-typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr;
+typedef std::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr;
/**
* @class LLNotification
@@ -745,6 +744,10 @@ public:
{}
virtual ~LLNotificationChannelBase()
{
+ // explicit cleanup for easier issue detection
+ mChanged.disconnect_all_slots();
+ mPassedFilter.disconnect_all_slots();
+ mFailedFilter.disconnect_all_slots();
mItems.clear();
}
// you can also connect to a Channel, so you can be notified of
@@ -914,6 +917,7 @@ public:
LLNotificationPtr add(const LLNotification::Params& p);
void add(const LLNotificationPtr pNotif);
+ void load(const LLNotificationPtr pNotif);
void cancel(LLNotificationPtr pNotif);
void cancelByName(const std::string& name);
void cancelByOwner(const LLUUID ownerId);
@@ -1114,6 +1118,11 @@ private:
mHistory.push_back(p);
}
+ void onLoad(LLNotificationPtr p)
+ {
+ mHistory.push_back(p);
+ }
+
std::vector<LLNotificationPtr> mHistory;
};
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
index f9f7641de6..4bab377626 100644
--- a/indra/llui/llnotificationslistener.h
+++ b/indra/llui/llnotificationslistener.h
@@ -31,7 +31,6 @@
#include "lleventapi.h"
#include "llnotificationptr.h"
-#include <boost/shared_ptr.hpp>
#include <map>
#include <string>
@@ -61,7 +60,7 @@ private:
static LLSD asLLSD(LLNotificationPtr);
class Forwarder;
- typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
+ typedef std::map<std::string, std::shared_ptr<Forwarder> > ForwarderMap;
ForwarderMap mForwarders;
LLNotifications & mNotifications;
};
diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h
index 20cbc89ede..a8902486e4 100644
--- a/indra/llui/llnotificationtemplate.h
+++ b/indra/llui/llnotificationtemplate.h
@@ -31,7 +31,7 @@
#include "llinitparam.h"
#include "llnotifications.h"
-typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
+typedef std::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
// This is the class of object read from the XML file (notifications.xml,
// from the appropriate local language directory).
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 00da0f5fec..f770920c4a 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -800,14 +800,12 @@ boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t::
return mVisibleSignal->connect(cb);
}
-static LLTrace::BlockTimerStatHandle FTM_BUILD_PANELS("Build Panels");
-
//-----------------------------------------------------------------------------
// buildPanel()
//-----------------------------------------------------------------------------
BOOL LLPanel::buildFromFile(const std::string& filename, const LLPanel::Params& default_params)
{
- LL_RECORD_BLOCK_TIME(FTM_BUILD_PANELS);
+ LL_PROFILE_ZONE_SCOPED;
BOOL didPost = FALSE;
LLXMLNodePtr root;
diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp
index 209796565c..cf57b1fe76 100644
--- a/indra/llui/llprogressbar.cpp
+++ b/indra/llui/llprogressbar.cpp
@@ -69,16 +69,22 @@ void LLProgressBar::draw()
static LLTimer timer;
F32 alpha = getDrawContext().mAlpha;
- LLColor4 image_bar_color = mColorBackground.get();
- image_bar_color.setAlpha(alpha);
- mImageBar->draw(getLocalRect(), image_bar_color);
+ if (mImageBar) // optional according to parameters
+ {
+ LLColor4 image_bar_color = mColorBackground.get();
+ image_bar_color.setAlpha(alpha);
+ mImageBar->draw(getLocalRect(), image_bar_color);
+ }
- alpha *= 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32()));
- LLColor4 bar_color = mColorBar.get();
- bar_color.mV[VALPHA] *= alpha; // modulate alpha
- LLRect progress_rect = getLocalRect();
- progress_rect.mRight = ll_round(getRect().getWidth() * (mPercentDone / 100.f));
- mImageFill->draw(progress_rect, bar_color);
+ if (mImageFill)
+ {
+ alpha *= 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32()));
+ LLColor4 bar_color = mColorBar.get();
+ bar_color.mV[VALPHA] *= alpha; // modulate alpha
+ LLRect progress_rect = getLocalRect();
+ progress_rect.mRight = ll_round(getRect().getWidth() * (mPercentDone / 100.f));
+ mImageFill->draw(progress_rect, bar_color);
+ }
}
void LLProgressBar::setValue(const LLSD& value)
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index 13839da400..8dd552d2ad 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -79,6 +79,14 @@ const LLSD LLScrollListCell::getValue() const
return LLStringUtil::null;
}
+
+// virtual
+const LLSD LLScrollListCell::getAltValue() const
+{
+ return LLStringUtil::null;
+}
+
+
//
// LLScrollListIcon
//
@@ -173,6 +181,7 @@ U32 LLScrollListText::sCount = 0;
LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
: LLScrollListCell(p),
mText(p.label.isProvided() ? p.label() : p.value().asString()),
+ mAltText(p.alt_value().asString()),
mFont(p.font),
mColor(p.color),
mUseColor(p.color.isProvided()),
@@ -275,10 +284,22 @@ void LLScrollListText::setValue(const LLSD& text)
setText(text.asString());
}
+//virtual
+void LLScrollListText::setAltValue(const LLSD& text)
+{
+ mAltText = text.asString();
+}
+
//virtual
const LLSD LLScrollListText::getValue() const
{
- return LLSD(mText.getString());
+ return LLSD(mText.getString());
+}
+
+//virtual
+const LLSD LLScrollListText::getAltValue() const
+{
+ return LLSD(mAltText.getString());
}
diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h
index 19576fb247..ede8d847d9 100644
--- a/indra/llui/llscrolllistcell.h
+++ b/indra/llui/llscrolllistcell.h
@@ -60,6 +60,7 @@ public:
Optional<void*> userdata;
Optional<LLSD> value; // state of checkbox, icon id/name, date
+ Optional<LLSD> alt_value;
Optional<std::string> label; // description or text
Optional<std::string> tool_tip;
@@ -76,6 +77,7 @@ public:
enabled("enabled", true),
visible("visible", true),
value("value"),
+ alt_value("alt_value", ""),
label("label"),
tool_tip("tool_tip", ""),
font("font", LLFontGL::getFontSansSerifSmall()),
@@ -98,7 +100,9 @@ public:
virtual S32 getContentWidth() const { return 0; }
virtual S32 getHeight() const { return 0; }
virtual const LLSD getValue() const;
+ virtual const LLSD getAltValue() const;
virtual void setValue(const LLSD& value) { }
+ virtual void setAltValue(const LLSD& value) { }
virtual const std::string &getToolTip() const { return mToolTip; }
virtual void setToolTip(const std::string &str) { mToolTip = str; }
virtual BOOL getVisible() const { return TRUE; }
@@ -138,7 +142,9 @@ public:
/*virtual*/ S32 getContentWidth() const;
/*virtual*/ S32 getHeight() const;
/*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ void setAltValue(const LLSD& value);
/*virtual*/ const LLSD getValue() const;
+ /*virtual*/ const LLSD getAltValue() const;
/*virtual*/ BOOL getVisible() const;
/*virtual*/ void highlightText(S32 offset, S32 num_chars);
@@ -156,6 +162,7 @@ public:
protected:
LLUIString mText;
+ LLUIString mAltText;
S32 mTextWidth;
const LLFontGL* mFont;
LLColor4 mColor;
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index de644185fd..65c7b420ce 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -66,9 +66,10 @@ static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list");
// local structures & classes.
struct SortScrollListItem
{
- SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal)
+ SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal, bool alternate_sort)
: mSortOrders(sort_orders)
, mSortSignal(sort_signal)
+ , mAltSort(alternate_sort)
{}
bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2)
@@ -93,7 +94,14 @@ struct SortScrollListItem
}
else
{
- sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
+ if (mAltSort && !cell1->getAltValue().asString().empty() && !cell2->getAltValue().asString().empty())
+ {
+ sort_result = order * LLStringUtil::compareDict(cell1->getAltValue().asString(), cell2->getAltValue().asString());
+ }
+ else
+ {
+ sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString());
+ }
}
if (sort_result != 0)
{
@@ -109,6 +117,7 @@ struct SortScrollListItem
typedef std::vector<std::pair<S32, BOOL> > sort_order_t;
const LLScrollListCtrl::sort_signal_t* mSortSignal;
const sort_order_t& mSortOrders;
+ const bool mAltSort;
};
//---------------------------------------------------------------------------
@@ -213,6 +222,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mSearchColumn(p.search_column),
mColumnPadding(p.column_padding),
mRowPadding(p.row_padding),
+ mAlternateSort(false),
mContextMenuType(MENU_NONE),
mIsFriendSignal(NULL)
{
@@ -336,8 +346,7 @@ LLScrollListCtrl::~LLScrollListCtrl()
std::for_each(mItemList.begin(), mItemList.end(), DeletePointer());
mItemList.clear();
- std::for_each(mColumns.begin(), mColumns.end(), DeletePairedPointer());
- mColumns.clear();
+ clearColumns(); //clears columns and deletes headers
delete mIsFriendSignal;
}
@@ -1379,6 +1388,84 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
return found;
}
+U32 LLScrollListCtrl::searchItems(const std::string& substring, bool case_sensitive, bool focus)
+{
+ return searchItems(utf8str_to_wstring(substring), case_sensitive, focus);
+}
+
+U32 LLScrollListCtrl::searchItems(const LLWString& substring, bool case_sensitive, bool focus)
+{
+ U32 found = 0;
+
+ LLWString substring_trimmed(substring);
+ S32 len = substring_trimmed.size();
+
+ if (0 == len)
+ {
+ // at the moment search for empty element is not supported
+ return 0;
+ }
+ else
+ {
+ deselectAllItems(TRUE);
+ if (!case_sensitive)
+ {
+ // do comparisons in lower case
+ LLWStringUtil::toLower(substring_trimmed);
+ }
+
+ for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); iter++)
+ {
+ LLScrollListItem* item = *iter;
+ // Only select enabled items with matching names
+ if (!item->getEnabled())
+ {
+ continue;
+ }
+ LLScrollListCell* cellp = item->getColumn(getSearchColumn());
+ if (!cellp)
+ {
+ continue;
+ }
+ LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
+ if (!case_sensitive)
+ {
+ LLWStringUtil::toLower(item_label);
+ }
+ // remove extraneous whitespace from searchable label
+ LLWStringUtil::trim(item_label);
+
+ size_t found_iter = item_label.find(substring_trimmed);
+
+ if (found_iter != std::string::npos)
+ {
+ // find offset of matching text
+ cellp->highlightText(found_iter, substring_trimmed.size());
+ selectItem(item, -1, FALSE);
+
+ found++;
+
+ if (!mAllowMultipleSelection)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if (focus && found != 0)
+ {
+ mNeedsScroll = true;
+ }
+
+ if (mCommitOnSelectionChange)
+ {
+ commitIfChanged();
+ }
+
+ return found;
+}
+
const std::string LLScrollListCtrl::getSelectedItemLabel(S32 column) const
{
LLScrollListItem* item;
@@ -1903,6 +1990,7 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
registrar.add("Url.SendIM", boost::bind(&LLScrollListCtrl::sendIM, id));
registrar.add("Url.AddFriend", boost::bind(&LLScrollListCtrl::addFriend, id));
registrar.add("Url.RemoveFriend", boost::bind(&LLScrollListCtrl::removeFriend, id));
+ registrar.add("Url.ReportAbuse", boost::bind(&LLScrollListCtrl::reportAbuse, id, is_group));
registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group));
registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group));
registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group));
@@ -1966,6 +2054,15 @@ void LLScrollListCtrl::removeFriend(std::string id)
LLUrlAction::removeFriend(slurl);
}
+void LLScrollListCtrl::reportAbuse(std::string id, bool is_group)
+{
+ if (!is_group)
+ {
+ std::string slurl = "secondlife:///app/agent/" + id + "/about";
+ LLUrlAction::reportAbuse(slurl);
+ }
+}
+
void LLScrollListCtrl::showNameDetails(std::string id, bool is_group)
{
// open the resident's details or the group details
@@ -2680,7 +2777,7 @@ void LLScrollListCtrl::updateSort() const
std::stable_sort(
mItemList.begin(),
mItemList.end(),
- SortScrollListItem(mSortColumns,mSortCallback));
+ SortScrollListItem(mSortColumns,mSortCallback, mAlternateSort));
mSorted = true;
}
@@ -2696,7 +2793,7 @@ void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending)
std::stable_sort(
mItemList.begin(),
mItemList.end(),
- SortScrollListItem(sort_column,mSortCallback));
+ SortScrollListItem(sort_column,mSortCallback,mAlternateSort));
}
void LLScrollListCtrl::dirtyColumns()
@@ -3011,6 +3108,8 @@ void LLScrollListCtrl::clearColumns()
mSortColumns.clear();
mTotalStaticColumnWidth = 0;
mTotalColumnPadding = 0;
+
+ dirtyColumns(); // Clears mColumnsIndexed
}
void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label)
@@ -3045,10 +3144,9 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name)
return NULL;
}
-LLTrace::BlockTimerStatHandle FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item");
LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
{
- LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
LLScrollListItem::Params item_params;
LLParamSDParser parser;
parser.readSD(element, item_params);
@@ -3058,14 +3156,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition
LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)
{
- LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
LLScrollListItem *new_item = new LLScrollListItem(item_p);
return addRow(new_item, item_p, pos);
}
LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos)
{
- LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
if (!item_p.validateBlock() || !new_item) return NULL;
new_item->setNumColumns(mColumns.size());
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 0cc481b113..77d10fdec7 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -267,6 +267,14 @@ public:
const std::string getSelectedItemLabel(S32 column = 0) const;
LLSD getSelectedValue();
+ // If multi select is on, select all element that include substring,
+ // otherwise select first match only.
+ // If focus is true will scroll to selection.
+ // Returns number of results.
+ // Note: at the moment search happens in one go and is expensive
+ U32 searchItems(const std::string& substring, bool case_sensitive = false, bool focus = true);
+ U32 searchItems(const LLWString& substring, bool case_sensitive = false, bool focus = true);
+
// DEPRECATED: Use LLSD versions of setCommentText() and getSelectedValue().
// "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which
// has an associated, unique UUID, and only one of which can be selected at a time.
@@ -325,6 +333,7 @@ public:
// support right-click context menus for avatar/group lists
enum ContextMenuType { MENU_NONE, MENU_AVATAR, MENU_GROUP };
void setContextMenu(const ContextMenuType &menu) { mContextMenuType = menu; }
+ ContextMenuType getContextMenuType() { return mContextMenuType; }
// Overridden from LLView
/*virtual*/ void draw();
@@ -398,6 +407,8 @@ public:
BOOL hasSortOrder() const;
void clearSortOrder();
+ void setAlternateSort() { mAlternateSort = true; }
+
S32 selectMultiple( uuid_vec_t ids );
// conceptually const, but mutates mItemList
void updateSort() const;
@@ -458,6 +469,7 @@ private:
static void sendIM(std::string id);
static void addFriend(std::string id);
static void removeFriend(std::string id);
+ static void reportAbuse(std::string id, bool is_group);
static void showNameDetails(std::string id, bool is_group);
static void copyNameToClipboard(std::string id, bool is_group);
static void copySLURLToClipboard(std::string id, bool is_group);
@@ -482,6 +494,8 @@ private:
bool mColumnsDirty;
bool mColumnWidthsDirty;
+ bool mAlternateSort;
+
mutable item_list mItemList;
LLScrollListItem *mLastSelected;
diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp
index 51c615dd00..e1360f80cd 100644
--- a/indra/llui/llscrolllistitem.cpp
+++ b/indra/llui/llscrolllistitem.cpp
@@ -44,7 +44,8 @@ LLScrollListItem::LLScrollListItem( const Params& p )
mSelectedIndex(-1),
mEnabled(p.enabled),
mUserdata(p.userdata),
- mItemValue(p.value)
+ mItemValue(p.value),
+ mItemAltValue(p.alt_value)
{
}
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
index d2c3dd7721..a3398305b1 100644
--- a/indra/llui/llscrolllistitem.h
+++ b/indra/llui/llscrolllistitem.h
@@ -55,6 +55,7 @@ public:
Optional<bool> enabled;
Optional<void*> userdata;
Optional<LLSD> value;
+ Optional<LLSD> alt_value;
Ignored name; // use for localization tools
Ignored type;
@@ -65,6 +66,7 @@ public:
Params()
: enabled("enabled", true),
value("value"),
+ alt_value("alt_value"),
name("name"),
type("type"),
length("length"),
@@ -97,6 +99,7 @@ public:
virtual LLUUID getUUID() const { return mItemValue.asUUID(); }
LLSD getValue() const { return mItemValue; }
+ LLSD getAltValue() const { return mItemAltValue; }
void setRect(LLRect rect) { mRectangle = rect; }
LLRect getRect() const { return mRectangle; }
@@ -131,6 +134,7 @@ private:
BOOL mEnabled;
void* mUserdata;
LLSD mItemValue;
+ LLSD mItemAltValue;
std::vector<LLScrollListCell *> mColumns;
LLRect mRectangle;
};
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index ee78b82429..ef7c8ec012 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -103,6 +103,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height);
up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
+ up_button_params.commit_on_capture_lost = true;
mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params);
addChild(mUpBtn);
@@ -111,6 +112,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height);
down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
+ down_button_params.commit_on_capture_lost = true;
mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params);
addChild(mDownBtn);
diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp
index 6c8e63442b..2449100952 100644
--- a/indra/llui/llstatbar.cpp
+++ b/indra/llui/llstatbar.cpp
@@ -160,6 +160,7 @@ LLStatBar::Params::Params()
tick_spacing("tick_spacing", 0.f),
decimal_digits("decimal_digits", 3),
show_bar("show_bar", false),
+ show_median("show_median", false),
show_history("show_history", false),
scale_range("scale_range", true),
num_frames("num_frames", 200),
@@ -186,6 +187,7 @@ LLStatBar::LLStatBar(const Params& p)
mNumShortHistoryFrames(p.num_frames_short),
mMaxHeight(p.max_height),
mDisplayBar(p.show_bar),
+ mShowMedian(p.show_median),
mDisplayHistory(p.show_history),
mOrientation(p.orientation),
mAutoScaleMax(!p.bar_max.isProvided()),
@@ -318,7 +320,14 @@ void LLStatBar::draw()
min = frame_recording.getPeriodMinPerSec(count_stat, num_frames);
max = frame_recording.getPeriodMaxPerSec(count_stat, num_frames);
mean = frame_recording.getPeriodMeanPerSec(count_stat, num_frames);
- display_value = mean;
+ if (mShowMedian)
+ {
+ display_value = frame_recording.getPeriodMedianPerSec(count_stat, num_frames);
+ }
+ else
+ {
+ display_value = mean;
+ }
}
break;
case STAT_EVENT:
@@ -344,7 +353,11 @@ void LLStatBar::draw()
mean = frame_recording.getPeriodMean(sample_stat, num_frames);
num_rapid_changes = calc_num_rapid_changes(frame_recording, sample_stat, RAPID_CHANGE_WINDOW);
- if (num_rapid_changes / RAPID_CHANGE_WINDOW.value() > MAX_RAPID_CHANGES_PER_SEC)
+ if (mShowMedian)
+ {
+ display_value = frame_recording.getPeriodMedian(sample_stat, num_frames);
+ }
+ else if (num_rapid_changes / RAPID_CHANGE_WINDOW.value() > MAX_RAPID_CHANGES_PER_SEC)
{
display_value = mean;
}
@@ -554,29 +567,25 @@ void LLStatBar::draw()
void LLStatBar::setStat(const std::string& stat_name)
{
using namespace LLTrace;
- const StatType<CountAccumulator>* count_stat;
- const StatType<EventAccumulator>* event_stat;
- const StatType<SampleAccumulator>* sample_stat;
- const StatType<MemAccumulator>* mem_stat;
- if ((count_stat = StatType<CountAccumulator>::getInstance(stat_name)))
+ if (auto count_stat = StatType<CountAccumulator>::getInstance(stat_name))
{
- mStat.countStatp = count_stat;
+ mStat.countStatp = count_stat.get();
mStatType = STAT_COUNT;
}
- else if ((event_stat = StatType<EventAccumulator>::getInstance(stat_name)))
+ else if (auto event_stat = StatType<EventAccumulator>::getInstance(stat_name))
{
- mStat.eventStatp = event_stat;
+ mStat.eventStatp = event_stat.get();
mStatType = STAT_EVENT;
}
- else if ((sample_stat = StatType<SampleAccumulator>::getInstance(stat_name)))
+ else if (auto sample_stat = StatType<SampleAccumulator>::getInstance(stat_name))
{
- mStat.sampleStatp = sample_stat;
+ mStat.sampleStatp = sample_stat.get();
mStatType = STAT_SAMPLE;
}
- else if ((mem_stat = StatType<MemAccumulator>::getInstance(stat_name)))
+ else if (auto mem_stat = StatType<MemAccumulator>::getInstance(stat_name))
{
- mStat.memStatp = mem_stat;
+ mStat.memStatp = mem_stat.get();
mStatType = STAT_MEM;
}
}
diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h
index 1ff4c67fc5..6b481ca68f 100644
--- a/indra/llui/llstatbar.h
+++ b/indra/llui/llstatbar.h
@@ -44,9 +44,10 @@ public:
bar_max,
tick_spacing;
- Optional<bool> show_bar,
+ Optional<bool> show_bar,
show_history,
- scale_range;
+ scale_range,
+ show_median; // default is mean
Optional<S32> decimal_digits,
num_frames,
@@ -112,6 +113,7 @@ private:
bool mDisplayBar, // Display the bar graph.
mDisplayHistory,
+ mShowMedian,
mAutoScaleMax,
mAutoScaleMin;
};
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 459fdcf2ae..0aa7a2d217 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -402,9 +402,13 @@ void LLTabContainer::draw()
S32 cur_scroll_pos = getScrollPos();
if (cur_scroll_pos > 0)
{
- S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1);
- if (!mIsVertical)
+ if (mIsVertical)
{
+ target_pixel_scroll = cur_scroll_pos * (BTN_HEIGHT + tabcntrv_pad);
+ }
+ else
+ {
+ S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1);
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
if (cur_scroll_pos == 0)
@@ -1189,13 +1193,15 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
sendChildToFront(mNextArrowBtn);
sendChildToFront(mJumpPrevArrowBtn);
sendChildToFront(mJumpNextArrowBtn);
-
+
+ updateMaxScrollPos();
+
if( select )
{
selectLastTab();
+ mScrollPos = mMaxScrollPos;
}
- updateMaxScrollPos();
}
void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label)
@@ -2079,9 +2085,9 @@ void LLTabContainer::updateMaxScrollPos()
if( tab_total_height > available_height )
{
static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0);
- S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad);
+ S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad) - mNextArrowBtn->getRect().mBottom;
S32 additional_needed = tab_total_height - available_height_with_arrows;
- setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT) ) );
+ setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT + tabcntrv_pad) ) );
no_scroll = FALSE;
}
}
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 28165aa1ef..05cdb88dbc 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -165,6 +165,7 @@ LLTextBase::Params::Params()
text_valign("text_valign"),
wrap("wrap"),
trusted_content("trusted_content", true),
+ always_show_icons("always_show_icons", false),
use_ellipses("use_ellipses", false),
use_color("use_color", false),
parse_urls("parse_urls", false),
@@ -187,6 +188,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mFontShadow(p.font_shadow),
mPopupMenuHandle(),
mReadOnly(p.read_only),
+ mSkipTripleClick(false),
mSkipLinkUnderline(p.skip_link_underline),
mSpellCheck(p.spellcheck),
mSpellCheckStart(-1),
@@ -215,6 +217,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mClip(p.clip),
mClipPartial(p.clip_partial && !p.allow_scroll),
mTrustedContent(p.trusted_content),
+ mAlwaysShowIcons(p.always_show_icons),
mTrackEnd( p.track_end ),
mScrollIndex(-1),
mSelectionStart( 0 ),
@@ -452,8 +455,48 @@ void LLTextBase::drawSelectionBackground()
++rect_it)
{
LLRect selection_rect = *rect_it;
- selection_rect = *rect_it;
- selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom);
+ if (mScroller)
+ {
+ // If scroller is On content_display_rect has correct rect and safe to use as is
+ // Note: we might need to account for border
+ selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom);
+ }
+ else
+ {
+ // If scroller is Off content_display_rect will have rect from document, adjusted to text width, heigh and position
+ // and we have to acount for offset depending on position
+ S32 v_delta = 0;
+ S32 h_delta = 0;
+ switch (mVAlign)
+ {
+ case LLFontGL::TOP:
+ v_delta = mVisibleTextRect.mTop - content_display_rect.mTop - mVPad;
+ break;
+ case LLFontGL::VCENTER:
+ v_delta = (llmax(mVisibleTextRect.getHeight() - content_display_rect.mTop, -content_display_rect.mBottom) + (mVisibleTextRect.mBottom - content_display_rect.mBottom)) / 2;
+ break;
+ case LLFontGL::BOTTOM:
+ v_delta = mVisibleTextRect.mBottom - content_display_rect.mBottom;
+ break;
+ default:
+ break;
+ }
+ switch (mHAlign)
+ {
+ case LLFontGL::LEFT:
+ h_delta = mVisibleTextRect.mLeft - content_display_rect.mLeft + mHPad;
+ break;
+ case LLFontGL::HCENTER:
+ h_delta = (llmax(mVisibleTextRect.getWidth() - content_display_rect.mLeft, -content_display_rect.mRight) + (mVisibleTextRect.mRight - content_display_rect.mRight)) / 2;
+ break;
+ case LLFontGL::RIGHT:
+ h_delta = mVisibleTextRect.mRight - content_display_rect.mRight;
+ break;
+ default:
+ break;
+ }
+ selection_rect.translate(h_delta, v_delta);
+ }
gl_rect_2d(selection_rect, selection_color);
}
}
@@ -1041,6 +1084,11 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
// handle triple click
if (!mTripleClickTimer.hasExpired())
{
+ if (mSkipTripleClick)
+ {
+ return TRUE;
+ }
+
S32 real_line = getLineNumFromDocIndex(mCursorPos, false);
S32 line_start = -1;
S32 line_end = -1;
@@ -1508,11 +1556,9 @@ S32 LLTextBase::getLeftOffset(S32 width)
}
}
-
-static LLTrace::BlockTimerStatHandle FTM_TEXT_REFLOW ("Text Reflow");
void LLTextBase::reflow()
{
- LL_RECORD_BLOCK_TIME(FTM_TEXT_REFLOW);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
updateSegments();
@@ -1582,11 +1628,14 @@ void LLTextBase::reflow()
{
// find first element whose end comes after start_index
line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
- line_start_index = iter->mDocIndexStart;
- line_count = iter->mLineNum;
- cur_top = iter->mRect.mTop;
- getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
- mLineInfoList.erase(iter, mLineInfoList.end());
+ if (iter != mLineInfoList.end())
+ {
+ line_start_index = iter->mDocIndexStart;
+ line_count = iter->mLineNum;
+ cur_top = iter->mRect.mTop;
+ getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
+ mLineInfoList.erase(iter, mLineInfoList.end());
+ }
}
S32 line_height = 0;
@@ -1857,10 +1906,9 @@ void LLTextBase::removeDocumentChild(LLView* view)
}
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_TEXT_SEGMENTS("Update Text Segments");
void LLTextBase::updateSegments()
{
- LL_RECORD_BLOCK_TIME(FTM_UPDATE_TEXT_SEGMENTS);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
createDefaultSegment();
}
@@ -2021,6 +2069,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url));
registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url));
registrar.add("Url.RemoveFriend", boost::bind(&LLUrlAction::removeFriend, url));
+ registrar.add("Url.ReportAbuse", boost::bind(&LLUrlAction::reportAbuse, url));
registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url));
registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url));
registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
@@ -2116,24 +2165,21 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name)
}
}
-static LLTrace::BlockTimerStatHandle FTM_PARSE_HTML("Parse HTML");
-
-
void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
LLStyle::Params style_params(input_params);
style_params.fillFrom(getStyleParams());
S32 part = (S32)LLTextParser::WHOLE;
if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358).
{
- LL_RECORD_BLOCK_TIME(FTM_PARSE_HTML);
S32 start=0,end=0;
LLUrlMatch match;
std::string text = new_text;
while ( LLUrlRegistry::instance().findUrl(text, match,
- boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted()))
+ boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3),isContentTrusted() || mAlwaysShowIcons))
{
start = match.getStart();
end = match.getEnd()+1;
@@ -2158,7 +2204,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
}
// add icon before url if need
- LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted());
+ LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted() || mAlwaysShowIcons);
if ((isContentTrusted() || match.isTrusted()) && !match.getIcon().empty() )
{
setLastSegmentToolTip(LLTrans::getString("TooltipSLIcon"));
@@ -2222,11 +2268,9 @@ void LLTextBase::setLastSegmentToolTip(const std::string &tooltip)
}
}
-static LLTrace::BlockTimerStatHandle FTM_APPEND_TEXT("Append Text");
-
void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
{
- LL_RECORD_BLOCK_TIME(FTM_APPEND_TEXT);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
if (new_text.empty())
return;
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index a047db25b2..4d742b6827 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -334,7 +334,8 @@ public:
parse_highlights,
clip,
clip_partial,
- trusted_content;
+ trusted_content,
+ always_show_icons;
Optional<S32> v_pad,
h_pad;
@@ -384,6 +385,8 @@ public:
virtual void onFocusReceived();
virtual void onFocusLost();
+ void setParseHTML(bool parse_html) { mParseHTML = parse_html; }
+
// LLSpellCheckMenuHandler overrides
/*virtual*/ bool getSpellCheck() const;
@@ -473,6 +476,8 @@ public:
void setSkipLinkUnderline(bool skip_link_underline) { mSkipLinkUnderline = skip_link_underline; }
bool getSkipLinkUnderline() { return mSkipLinkUnderline; }
+ void setParseURLs(bool parse_urls) { mParseHTML = parse_urls; }
+
void setPlainText(bool value) { mPlainText = value;}
bool getPlainText() const { return mPlainText; }
@@ -717,6 +722,8 @@ protected:
bool mPlainText; // didn't use Image or Icon segments
bool mAutoIndent;
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
+ bool mSkipTripleClick;
+ bool mAlwaysShowIcons;
bool mSkipLinkUnderline;
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 134afc005b..c567451973 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -45,7 +45,9 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p)
: LLTextBase(p),
mClickedCallback(NULL),
mShowCursorHand(true)
-{}
+{
+ mSkipTripleClick = true;
+}
LLTextBox::~LLTextBox()
{}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 4c8175a286..f7621b39f0 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -199,6 +199,7 @@ public:
const LLUUID& getSourceID() const { return mSourceID; }
const LLTextSegmentPtr getPreviousSegment() const;
+ const LLTextSegmentPtr getLastSegment() const;
void getSelectedSegments(segment_vec_t& segments) const;
void setShowContextMenu(bool show) { mShowContextMenu = show; }
diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp
index 538508b856..78049319bc 100644
--- a/indra/llui/lltextutil.cpp
+++ b/indra/llui/lltextutil.cpp
@@ -76,22 +76,6 @@ void LLTextUtil::textboxSetGreyedVal(LLTextBox *txtbox, const LLStyle::Params& n
txtbox->appendText(text.substr(greyed_begin + greyed_len), false, normal_style);
}
-const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str)
-{
- static const std::string PHONE_SEPARATOR = LLUI::getInstance()->mSettingGroups["config"]->getString("AvalinePhoneSeparator");
- static const S32 PHONE_PART_LEN = 2;
-
- static std::string formatted_phone_str;
- formatted_phone_str = phone_str;
- S32 separator_pos = (S32)(formatted_phone_str.size()) - PHONE_PART_LEN;
- for (; separator_pos >= PHONE_PART_LEN; separator_pos -= PHONE_PART_LEN)
- {
- formatted_phone_str.insert(separator_pos, PHONE_SEPARATOR);
- }
-
- return formatted_phone_str;
-}
-
bool LLTextUtil::processUrlMatch(LLUrlMatch* match,LLTextBase* text_base, bool is_content_trusted)
{
if (match == 0 || text_base == 0)
diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h
index a9c143e445..1adc3516f7 100644
--- a/indra/llui/lltextutil.h
+++ b/indra/llui/lltextutil.h
@@ -59,18 +59,6 @@ namespace LLTextUtil
const std::string& greyed);
/**
- * Formats passed phone number to be more human readable.
- *
- * It just divides the number on parts by two digits from right to left. The first left part
- * can have 2 or 3 digits, i.e. +44-33-33-44-55-66 or 12-34-56-78-90. Separator is set in
- * application settings (AvalinePhoneSeparator)
- *
- * @param[in] phone_str string with original phone number
- * @return reference to string with formatted phone number
- */
- const std::string& formatPhoneNumber(const std::string& phone_str);
-
- /**
* Adds icon before url if need.
*
* @param[in] match an object with results of matching
diff --git a/indra/llui/lltrans.cpp b/indra/llui/lltrans.cpp
index a1a8feedaa..a1ef34159d 100644
--- a/indra/llui/lltrans.cpp
+++ b/indra/llui/lltrans.cpp
@@ -147,7 +147,7 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::
{
// Don't care about time as much as call count. Make sure we're not
// calling LLTrans::getString() in an inner loop. JC
- LL_RECORD_BLOCK_TIME(FTM_GET_TRANS);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
if (def_string)
{
@@ -196,7 +196,7 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLSD& msg_args
{
// Don't care about time as much as call count. Make sure we're not
// calling LLTrans::getString() in an inner loop. JC
- LL_RECORD_BLOCK_TIME(FTM_GET_TRANS);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
if (def_string)
{
@@ -237,7 +237,7 @@ std::string LLTrans::getDefString(const std::string &xml_desc, const LLSD& msg_a
//static
bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args)
{
- LL_RECORD_BLOCK_TIME(FTM_GET_TRANS);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
template_map_t::iterator iter = sStringTemplates.find(xml_desc);
if (iter != sStringTemplates.end())
@@ -259,7 +259,7 @@ bool LLTrans::findString(std::string &result, const std::string &xml_desc, const
//static
bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLSD& msg_args)
{
- LL_RECORD_BLOCK_TIME(FTM_GET_TRANS);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
template_map_t::iterator iter = sStringTemplates.find(xml_desc);
if (iter != sStringTemplates.end())
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 6f16745bd3..3f3ec7ee8b 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -173,6 +173,7 @@ mHelpImpl(NULL)
reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleInstance, _2, LLSD()));
reg.add("Floater.ToggleOrBringToFront", boost::bind(&LLFloaterReg::toggleInstanceOrBringToFront, _2, LLSD()));
reg.add("Floater.Show", boost::bind(&LLFloaterReg::showInstance, _2, LLSD(), FALSE));
+ reg.add("Floater.ShowOrBringToFront", boost::bind(&LLFloaterReg::showInstanceOrBringToFront, _2, LLSD()));
reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideInstance, _2, LLSD()));
// Button initialization callback for toggle buttons
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 5924542a19..2196ba201b 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -121,7 +121,6 @@ LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)
mDoubleClickSignal(NULL),
mTransparencyType(TT_DEFAULT)
{
- claimMem(viewmodel.get());
}
void LLUICtrl::initFromParams(const Params& p)
@@ -476,6 +475,7 @@ LLViewModel* LLUICtrl::getViewModel() const
//virtual
BOOL LLUICtrl::postBuild()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
//
// Find all of the children that want to be in front and move them to the front
//
@@ -781,12 +781,9 @@ BOOL LLUICtrl::getIsChrome() const
}
-
-LLTrace::BlockTimerStatHandle FTM_FOCUS_FIRST_ITEM("Focus First Item");
-
BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields, BOOL focus_flash)
{
- LL_RECORD_BLOCK_TIME(FTM_FOCUS_FIRST_ITEM);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
// try to select default tab group child
LLViewQuery query = getTabOrderQuery();
child_list_t result = query(this);
@@ -1005,7 +1002,6 @@ boost::signals2::connection LLUICtrl::setCommitCallback( boost::function<void (L
boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb )
{
if (!mValidateSignal) mValidateSignal = new enable_signal_t();
- claimMem(mValidateSignal);
return mValidateSignal->connect(boost::bind(cb, _2));
}
@@ -1070,7 +1066,6 @@ boost::signals2::connection LLUICtrl::setValidateCallback(const EnableCallbackPa
boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb )
{
if (!mCommitSignal) mCommitSignal = new commit_signal_t();
- claimMem(mCommitSignal);
return mCommitSignal->connect(cb);
}
@@ -1078,7 +1073,6 @@ boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::
boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb )
{
if (!mValidateSignal) mValidateSignal = new enable_signal_t();
- claimMem(mValidateSignal);
return mValidateSignal->connect(cb);
}
@@ -1086,7 +1080,6 @@ boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t
boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb )
{
if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t();
- claimMem(mMouseEnterSignal);
return mMouseEnterSignal->connect(cb);
}
@@ -1094,7 +1087,6 @@ boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal
boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb )
{
if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t();
- claimMem(mMouseLeaveSignal);
return mMouseLeaveSignal->connect(cb);
}
@@ -1102,7 +1094,6 @@ boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal
boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
{
if (!mMouseDownSignal) mMouseDownSignal = new mouse_signal_t();
- claimMem(mMouseDownSignal);
return mMouseDownSignal->connect(cb);
}
@@ -1110,7 +1101,6 @@ boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t
boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t::slot_type& cb )
{
if (!mMouseUpSignal) mMouseUpSignal = new mouse_signal_t();
- claimMem(mMouseUpSignal);
return mMouseUpSignal->connect(cb);
}
@@ -1118,7 +1108,6 @@ boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t::
boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_signal_t::slot_type& cb )
{
if (!mRightMouseDownSignal) mRightMouseDownSignal = new mouse_signal_t();
- claimMem(mRightMouseDownSignal);
return mRightMouseDownSignal->connect(cb);
}
@@ -1126,7 +1115,6 @@ boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_sig
boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signal_t::slot_type& cb )
{
if (!mRightMouseUpSignal) mRightMouseUpSignal = new mouse_signal_t();
- claimMem(mRightMouseUpSignal);
return mRightMouseUpSignal->connect(cb);
}
@@ -1134,7 +1122,6 @@ boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signa
boost::signals2::connection LLUICtrl::setDoubleClickCallback( const mouse_signal_t::slot_type& cb )
{
if (!mDoubleClickSignal) mDoubleClickSignal = new mouse_signal_t();
- claimMem(mDoubleClickSignal);
return mDoubleClickSignal->connect(cb);
}
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index fdefae01b1..a85db17c7f 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -44,10 +44,6 @@
// this library includes
#include "llpanel.h"
-LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION("Widget Construction");
-LLTrace::BlockTimerStatHandle FTM_INIT_FROM_PARAMS("Widget InitFromParams");
-LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP("Widget Setup");
-
//-----------------------------------------------------------------------------
// UI Ctrl class for padding
@@ -117,12 +113,10 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa
}
}
-static LLTrace::BlockTimerStatHandle FTM_CREATE_CHILDREN("Create XUI Children");
-
//static
void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t& registry, LLXMLNodePtr output_node)
{
- LL_RECORD_BLOCK_TIME(FTM_CREATE_CHILDREN);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
if (node.isNull()) return;
for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling())
@@ -159,14 +153,13 @@ void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const wid
}
-static LLTrace::BlockTimerStatHandle FTM_XML_PARSE("XML Reading/Parsing");
//-----------------------------------------------------------------------------
// getLayeredXMLNode()
//-----------------------------------------------------------------------------
bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root,
LLDir::ESkinConstraint constraint)
{
- LL_RECORD_BLOCK_TIME(FTM_XML_PARSE);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
std::vector<std::string> paths =
gDirUtilp->findSkinnedFilenames(LLDir::XUI, xui_filename, constraint);
@@ -191,11 +184,9 @@ S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
-static LLTrace::BlockTimerStatHandle FTM_CREATE_FROM_XML("Create child widget");
-
LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t& registry, LLXMLNodePtr output_node)
{
- LL_RECORD_BLOCK_TIME(FTM_CREATE_FROM_XML);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
std::string ctrl_type = node->getName()->mString;
LLStringUtil::toLower(ctrl_type);
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 135ed57a4f..6e585abfc0 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -79,10 +79,6 @@ class LLWidgetNameRegistry
// LLSINGLETON(LLDefaultParamBlockRegistry);
//};
-extern LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP;
-extern LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION;
-extern LLTrace::BlockTimerStatHandle FTM_INIT_FROM_PARAMS;
-
// Build time optimization, generate this once in .cpp file
#ifndef LLUICTRLFACTORY_CPP
extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance();
@@ -213,6 +209,7 @@ private:
template<typename T>
static T* createWidgetImpl(const typename T::Params& params, LLView* parent = NULL)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
T* widget = NULL;
if (!params.validateBlock())
@@ -221,12 +218,9 @@ private:
//return NULL;
}
- { LL_RECORD_BLOCK_TIME(FTM_WIDGET_CONSTRUCTION);
- widget = new T(params);
- }
- { LL_RECORD_BLOCK_TIME(FTM_INIT_FROM_PARAMS);
- widget->initFromParams(params);
- }
+ widget = new T(params);
+
+ widget->initFromParams(params);
if (parent)
{
@@ -239,7 +233,7 @@ private:
template<typename T>
static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
- LL_RECORD_BLOCK_TIME(FTM_WIDGET_SETUP);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
typename T::Params params(getDefaultParams<T>());
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
index 84ea770a8d..8216046174 100644
--- a/indra/llui/llurlaction.cpp
+++ b/indra/llui/llurlaction.cpp
@@ -222,6 +222,15 @@ void LLUrlAction::removeFriend(std::string url)
}
}
+void LLUrlAction::reportAbuse(std::string url)
+{
+ std::string id_str = getUserID(url);
+ if (LLUUID::validate(id_str))
+ {
+ executeSLURL("secondlife:///app/agent/" + id_str + "/reportAbuse");
+ }
+}
+
void LLUrlAction::blockObject(std::string url)
{
std::string object_id = getObjectId(url);
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
index 2d2a8dfef1..c2c576254d 100644
--- a/indra/llui/llurlaction.h
+++ b/indra/llui/llurlaction.h
@@ -82,6 +82,7 @@ public:
static void sendIM(std::string url);
static void addFriend(std::string url);
static void removeFriend(std::string url);
+ static void reportAbuse(std::string url);
static void blockObject(std::string url);
static void unblockObject(std::string url);
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e43c52c0c2..1547a4ba5c 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -35,6 +35,7 @@
#include "llavatarnamecache.h"
#include "llcachename.h"
+#include "llregex.h"
#include "lltrans.h"
#include "lluicolortable.h"
#include "message.h"
@@ -181,11 +182,51 @@ bool LLUrlEntryBase::isLinkDisabled() const
return globally_disabled;
}
-bool LLUrlEntryBase::isWikiLinkCorrect(std::string url)
+bool LLUrlEntryBase::isWikiLinkCorrect(const std::string &labeled_url) const
{
- LLWString label = utf8str_to_wstring(getLabelFromWikiLink(url));
- label.erase(std::remove(label.begin(), label.end(), L'\u200B'), label.end());
- return (LLUrlRegistry::instance().hasUrl(wstring_to_utf8str(label))) ? false : true;
+ LLWString wlabel = utf8str_to_wstring(getLabelFromWikiLink(labeled_url));
+ wlabel.erase(std::remove(wlabel.begin(), wlabel.end(), L'\u200B'), wlabel.end());
+
+ // Unicode URL validation, see SL-15243
+ std::replace_if(wlabel.begin(),
+ wlabel.end(),
+ [](const llwchar &chr)
+ {
+ return (chr == L'\u2024') // "One Dot Leader"
+ || (chr == L'\uFE52') // "Small Full Stop"
+ || (chr == L'\uFF0E') // "Fullwidth Full Stop"
+ // Not a decomposition, but suficiently similar
+ || (chr == L'\u05C5'); // "Hebrew Mark Lower Dot"
+ },
+ L'\u002E'); // Dot "Full Stop"
+
+ std::replace_if(wlabel.begin(),
+ wlabel.end(),
+ [](const llwchar &chr)
+ {
+ return (chr == L'\u02D0') // "Modifier Letter Colon"
+ || (chr == L'\uFF1A') // "Fullwidth Colon"
+ || (chr == L'\uFE55'); // "Small Colon"
+ },
+ L'\u003A'); // Colon
+
+ std::replace_if(wlabel.begin(),
+ wlabel.end(),
+ [](const llwchar &chr)
+ {
+ return (chr == L'\uFF0F'); // "Fullwidth Solidus"
+ },
+ L'\u002F'); // Solidus
+
+ std::string label = wstring_to_utf8str(wlabel);
+ if ((label.find(".com") != std::string::npos
+ || label.find("www.") != std::string::npos)
+ && label.find("://") == std::string::npos)
+ {
+ label = "http://" + label;
+ }
+
+ return (LLUrlRegistry::instance().hasUrl(label)) ? false : true;
}
std::string LLUrlEntryBase::urlToLabelWithGreyQuery(const std::string &url) const
@@ -976,6 +1017,24 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const
return LLUrlEntryBase::getLocation(url);
}
+//
+// LLUrlEntryChat Describes a Second Life chat Url, e.g.,
+// secondlife:///app/chat/42/This%20Is%20a%20test
+//
+
+LLUrlEntryChat::LLUrlEntryChat()
+{
+ mPattern = boost::regex("secondlife:///app/chat/\\d+/\\S+",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slapp.xml";
+ mTooltip = LLTrans::getString("TooltipSLAPP");
+}
+
+std::string LLUrlEntryChat::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
// LLUrlEntryParcel statics.
LLUUID LLUrlEntryParcel::sAgentID(LLUUID::null);
LLUUID LLUrlEntryParcel::sSessionID(LLUUID::null);
@@ -1416,7 +1475,7 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url)
// Grep icon info between <icon>...</icon> tags
// matches[1] contains the icon name/path
boost::match_results<std::string::const_iterator> matches;
- mIcon = (boost::regex_match(url, matches, mPattern) && matches[1].matched)
+ mIcon = (ll_regex_match(url, matches, mPattern) && matches[1].matched)
? matches[1]
: LLStringUtil::null;
LLStringUtil::trim(mIcon);
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 4af1ab5096..63a1506731 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -105,7 +105,7 @@ public:
bool isLinkDisabled() const;
- bool isWikiLinkCorrect(std::string url);
+ bool isWikiLinkCorrect(const std::string &url) const;
virtual bool isSLURLvalid(const std::string &url) const { return TRUE; };
@@ -370,6 +370,17 @@ public:
private:
};
+//
+// LLUrlEntryChat Describes a Second Life chat Url, e.g.,
+// secondlife:///app/chat/42/This%20Is%20a%20test
+//
+class LLUrlEntryChat : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryChat();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+};
+
///
/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 321a0ec5b9..c9d7013a11 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -26,10 +26,10 @@
*/
#include "linden_common.h"
+#include "llregex.h"
#include "llurlregistry.h"
#include "lluriparser.h"
-#include <boost/regex.hpp>
// default dummy callback that ignores any label updates from the server
void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon)
@@ -63,6 +63,7 @@ LLUrlRegistry::LLUrlRegistry()
// LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since
// LLUrlEntryAgent is a less specific (catchall for agent urls)
registerUrl(new LLUrlEntryAgent());
+ registerUrl(new LLUrlEntryChat());
registerUrl(new LLUrlEntryGroup());
registerUrl(new LLUrlEntryParcel());
registerUrl(new LLUrlEntryTeleport());
@@ -71,7 +72,6 @@ LLUrlRegistry::LLUrlRegistry()
registerUrl(new LLUrlEntryObjectIM());
registerUrl(new LLUrlEntryPlace());
registerUrl(new LLUrlEntryInventory());
- registerUrl(new LLUrlEntryObjectIM());
registerUrl(new LLUrlEntryExperienceProfile());
//LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern,
//so it should be registered in the end of list
@@ -108,15 +108,7 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en
boost::cmatch result;
bool found;
- // regex_search can potentially throw an exception, so check for it
- try
- {
- found = boost::regex_search(text, result, regex);
- }
- catch (std::runtime_error &)
- {
- return false;
- }
+ found = ll_regex_search(text, result, regex);
if (! found)
{
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 2781c991a7..74abe54690 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -140,8 +140,7 @@ LLView::Params::Params()
}
LLView::LLView(const LLView::Params& p)
-: LLTrace::MemTrackable<LLView>("LLView"),
- mVisible(p.visible),
+: mVisible(p.visible),
mInDraw(false),
mName(p.name),
mParentView(NULL),
@@ -1597,15 +1596,11 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse) const
return getChild<LLView>(name, recurse);
}
-static LLTrace::BlockTimerStatHandle FTM_FIND_VIEWS("Find Widgets");
-
LLView* LLView::findChildView(const std::string& name, BOOL recurse) const
{
- LL_RECORD_BLOCK_TIME(FTM_FIND_VIEWS);
- //richard: should we allow empty names?
- //if(name.empty())
- // return NULL;
- // Look for direct children *first*
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
+
+ // Look for direct children *first*
BOOST_FOREACH(LLView* childp, mChildList)
{
llassert(childp);
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index c60dcf3344..bec45df78a 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -100,8 +100,7 @@ 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 LLTrace::MemTrackable<LLView> // track memory usage
+ public LLHandleProvider<LLView> // passes out weak references to self
{
public:
diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h
index d1059d55de..6170005b2b 100644
--- a/indra/llui/llviewereventrecorder.h
+++ b/indra/llui/llviewereventrecorder.h
@@ -32,7 +32,6 @@
#include "lldir.h"
#include "llsd.h"
#include "llfile.h"
-#include "llvfile.h"
#include "lldate.h"
#include "llsdserialize.h"
#include "llkeyboard.h"
@@ -42,12 +41,12 @@
#include "llsingleton.h" // includes llerror which we need here so we can skip the include here
-class LLViewerEventRecorder : public LLSingleton<LLViewerEventRecorder>
+class LLViewerEventRecorder : public LLSimpleton<LLViewerEventRecorder>
{
- LLSINGLETON(LLViewerEventRecorder);
- ~LLViewerEventRecorder();
-
- public:
+public:
+ LLViewerEventRecorder();
+ ~LLViewerEventRecorder();
+
void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y, std::string mName);
void setMouseLocalCoords(S32 x,S32 y);
void setMouseGlobalCoords(S32 x,S32 y);
diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp
index 282addf692..a400eb70c0 100644
--- a/indra/llui/llviewmodel.cpp
+++ b/indra/llui/llviewmodel.cpp
@@ -37,15 +37,13 @@
///
LLViewModel::LLViewModel()
-: LLTrace::MemTrackable<LLViewModel>("LLViewModel"),
- mDirty(false)
+: mDirty(false)
{
}
/// Instantiate an LLViewModel with an existing data value
LLViewModel::LLViewModel(const LLSD& value)
-: LLTrace::MemTrackable<LLViewModel>("LLViewModel"),
- mDirty(false)
+: mDirty(false)
{
setValue(value);
}
@@ -82,15 +80,9 @@ LLTextViewModel::LLTextViewModel(const LLSD& value)
void LLTextViewModel::setValue(const LLSD& value)
{
// approximate LLSD storage usage
- disclaimMem(mDisplay.size());
LLViewModel::setValue(value);
- disclaimMem(mDisplay);
mDisplay = utf8str_to_wstring(value.asString());
- claimMem(mDisplay);
- // approximate LLSD storage usage
- claimMem(mDisplay.size());
-
// mDisplay and mValue agree
mUpdateFromDisplay = false;
}
@@ -101,12 +93,8 @@ void LLTextViewModel::setDisplay(const LLWString& value)
// and do the utf8str_to_wstring() to get the corresponding mDisplay
// value. But a text editor might want to edit the display string
// directly, then convert back to UTF8 on commit.
- disclaimMem(mDisplay.size());
- disclaimMem(mDisplay);
- mDisplay = value;
- claimMem(mDisplay);
- claimMem(mDisplay.size());
- mDirty = true;
+ mDisplay = value;
+ mDirty = true;
// Don't immediately convert to UTF8 -- do it lazily -- we expect many
// more setDisplay() calls than getValue() calls. Just flag that it needs
// doing.
diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h
index 49d7c322a3..e7dceb6c31 100644
--- a/indra/llui/llviewmodel.h
+++ b/indra/llui/llviewmodel.h
@@ -62,8 +62,7 @@ typedef LLPointer<LLListViewModel> LLListViewModelPtr;
* last referencing widget is destroyed.
*/
class LLViewModel
-: public LLRefCount,
- public LLTrace::MemTrackable<LLViewModel>
+: public LLRefCount
{
public:
LLViewModel();