diff options
Diffstat (limited to 'indra/llui')
125 files changed, 1868 insertions, 602 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 5991a5b35e..83b3a220a0 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -18,6 +18,7 @@ set(llui_SOURCE_FILES llbadgeowner.cpp llbutton.cpp llchatentry.cpp + llchatmentionhelper.cpp llcheckboxctrl.cpp llclipboard.cpp llcombobox.cpp @@ -130,6 +131,7 @@ set(llui_HEADER_FILES llcallbackmap.h llchatentry.h llchat.h + llchatmentionhelper.h llcheckboxctrl.h llclipboard.h llcombobox.h diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 495ba2f40f..ac8f7c2126 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -47,6 +47,8 @@ static constexpr F32 AUTO_SCROLL_RATE_ACCEL = 120.f; static LLDefaultChildRegistry::Register<LLAccordionCtrl> t2("accordion"); +std::set<LLAccordionCtrl*> LLAccordionCtrl::sPendingArrange; + LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) , mFitParent(params.fit_parent) , mNoVisibleTabsOrigString(params.no_visible_tabs_text.initial_value().asString()) @@ -163,7 +165,11 @@ bool LLAccordionCtrl::postBuild() //--------------------------------------------------------------------------------- LLAccordionCtrl::~LLAccordionCtrl() { - mAccordionTabs.clear(); + if (mArrangePending) + { + sPendingArrange.erase(this); + } + mAccordionTabs.clear(); } //--------------------------------------------------------------------------------- @@ -184,7 +190,7 @@ void LLAccordionCtrl::reshape(S32 width, S32 height, bool called_from_parent) // necessary text paddings can be set via h_pad and v_pad mNoVisibleTabsHelpText->setRect(getLocalRect()); - arrange(); + scheduleArrange(); } //--------------------------------------------------------------------------------- @@ -325,7 +331,7 @@ void LLAccordionCtrl::addCollapsibleCtrl(LLAccordionCtrlTab* accordion_tab) mAccordionTabs.push_back(accordion_tab); accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, (S16)(mAccordionTabs.size() - 1)) ); - arrange(); + scheduleArrange(); } void LLAccordionCtrl::removeCollapsibleCtrl(LLAccordionCtrlTab* accordion_tab) @@ -494,6 +500,7 @@ void LLAccordionCtrl::arrangeMultiple() void LLAccordionCtrl::arrange() { + LL_PROFILE_ZONE_SCOPED; updateNoTabsHelpTextVisibility(); if (mAccordionTabs.empty()) @@ -681,8 +688,9 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) std::string str_action = info["action"]; if (str_action == "size_changes") { - // - arrange(); + // Multiple children can request an arrange, + // but only need to do it once so schedule it for later. + scheduleArrange(); return 1; } if (str_action == "select_next") @@ -924,3 +932,25 @@ void LLAccordionCtrl::collapseAllTabs() arrange(); } } + +void LLAccordionCtrl::scheduleArrange() +{ + if (!mArrangePending) + { + mArrangePending = true; + sPendingArrange.insert(this); + } +} + +void LLAccordionCtrl::updateClass() +{ + for (LLAccordionCtrl* inst : sPendingArrange) + { + if (inst) + { + inst->mArrangePending = false; + inst->arrange(); + } + } + sPendingArrange.clear(); +} diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index 43a33a2b3c..c7bb8bc9ff 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -142,6 +142,9 @@ public: void setSkipScrollToChild(bool skip) { mSkipScrollToChild = skip; } + void scheduleArrange(); + static void updateClass(); + private: void initNoTabsWidget(const LLTextBox::Params& tb_params); void updateNoTabsHelpTextVisibility(); @@ -188,12 +191,15 @@ private: LLTextBox* mNoVisibleTabsHelpText = nullptr; bool mSkipScrollToChild = false; + bool mArrangePending = false; std::string mNoMatchedTabsOrigString; std::string mNoVisibleTabsOrigString; LLAccordionCtrlTab* mSelectedTab = nullptr; const LLTabComparator* mTabComparator = nullptr; + + static std::set<LLAccordionCtrl*> sPendingArrange; }; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index ac66525030..828bfb289b 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -248,10 +248,22 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height, bool called_from_parent /* = true */) { S32 header_height = mHeaderTextbox->getTextPixelHeight(); + LLRect old_header_rect = mHeaderTextbox->getRect(); LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET, (height + header_height) / 2, width, (height - header_height) / 2); - mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight()); - mHeaderTextbox->setRect(textboxRect); + if (old_header_rect.getHeight() != textboxRect.getHeight() + || old_header_rect.mLeft != textboxRect.mLeft + || old_header_rect.mTop != textboxRect.mTop + || old_header_rect.getWidth() > textboxRect.getWidth() // reducing header's width + || (old_header_rect.getWidth() < textboxRect.getWidth() && old_header_rect.getWidth() < mHeaderTextbox->getTextPixelWidth())) + { + // Expensive text reflow + // Update if position or height changes + // Update if width reduces + // But do not update if text already fits and width increases (arguably LLTextBox::reshape should be smarter, not Accordion) + mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight()); + mHeaderTextbox->setRect(textboxRect); + } if (mHeaderTextbox->getTextPixelWidth() > mHeaderTextbox->getRect().getWidth()) { @@ -416,8 +428,11 @@ void LLAccordionCtrlTab::reshape(S32 width, S32 height, bool called_from_parent LLRect headerRect; headerRect.setLeftTopAndSize(0, height, width, HEADER_HEIGHT); - mHeader->setRect(headerRect); - mHeader->reshape(headerRect.getWidth(), headerRect.getHeight()); + if (mHeader->getRect() != headerRect) + { + mHeader->setRect(headerRect); + mHeader->reshape(headerRect.getWidth(), headerRect.getHeight()); + } if (!mDisplayChildren) return; @@ -464,7 +479,34 @@ void LLAccordionCtrlTab::onUpdateScrollToChild(const LLUICtrl *cntrl) // Translate to parent coordinatess to check if we are in visible rectangle rect.translate(getRect().mLeft, getRect().mBottom); - if (!getRect().contains(rect)) + bool needs_to_scroll = false; + const LLRect &acc_rect = getRect(); + if (!acc_rect.contains(rect)) + { + if (acc_rect.mTop < rect.mBottom || acc_rect.mBottom > rect.mTop) + { + // Content fully not in view + needs_to_scroll = true; + } + else if (acc_rect.getHeight() >= rect.getHeight()) + { + // Content can be displayed fully, but only partially in view + needs_to_scroll = true; + } + else if (acc_rect.mTop <= rect.mTop || acc_rect.mBottom >= rect.mBottom) + { + // Intersects, but too big to be displayed fully + S32 covered_height = acc_rect.mTop > rect.mTop ? rect.mTop - acc_rect.mBottom : acc_rect.mTop - rect.mBottom; + constexpr F32 covered_ratio = 0.7f; + if (covered_height < covered_ratio * acc_rect.getHeight()) + { + // Try to show bigger portion of the content + needs_to_scroll = true; + } + } + // else too big and in the middle of the view as is + } + if (needs_to_scroll) { // for accordition's scroll, height is in pixels // Back to local coords and calculate position for scroller @@ -932,7 +974,7 @@ void LLAccordionCtrlTab::adjustContainerPanel(const LLRect& child_rect) show_hide_scrollbar(child_rect); updateLayout(child_rect); } - else + else if (mContainerPanel->getRect() != child_rect) { mContainerPanel->reshape(child_rect.getWidth(), child_rect.getHeight()); mContainerPanel->setRect(child_rect); diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index cf3569683e..bb0b8ce04f 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -126,7 +126,7 @@ public: void setSelected(bool is_selected); - bool getCollapsible() { return mCollapsible; }; + bool getCollapsible() const { return mCollapsible; }; void setCollapsible(bool collapsible) { mCollapsible = collapsible; }; void changeOpenClose(bool is_open); @@ -140,7 +140,7 @@ public: S32 notify(const LLSD& info); bool notifyChildren(const LLSD& info); - void draw(); + virtual void draw(); void storeOpenCloseState(); void restoreOpenCloseState(); @@ -181,7 +181,7 @@ public: void setHeaderVisible(bool value); - bool getHeaderVisible() { return mHeaderVisible;} + bool getHeaderVisible() const { return mHeaderVisible;} S32 mExpandedHeight; // Height of expanded ctrl. // Used to restore height after expand. diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 1bce31edb1..0048c44189 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -190,7 +190,7 @@ LLButton::LLButton(const LLButton::Params& p) // Note: flashing should be allowed in settings.xml (boolean key "EnableButtonFlashing"). S32 flash_count = p.button_flash_count.isProvided()? p.button_flash_count : 0; F32 flash_rate = p.button_flash_rate.isProvided()? p.button_flash_rate : 0.0f; - mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate); + mFlashingTimer = new LLFlashTimer((LLFlashTimer::callback_t) nullptr, flash_count, flash_rate); } else { @@ -837,7 +837,7 @@ void LLButton::draw() // Highlight if needed if( ll::ui::SearchableControl::getHighlighted() ) - label_color = ll::ui::SearchableControl::getHighlightColor(); + label_color = ll::ui::SearchableControl::getHighlightFontColor(); // overlay with keyboard focus border if (hasFocus()) diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 890e7c2d1e..f530eceb4b 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -153,7 +153,7 @@ public: ~LLButton(); // For backward compatability only - typedef boost::function<void(void*)> button_callback_t; + typedef std::function<void(void*)> button_callback_t; void addImageAttributeToXML(LLXMLNodePtr node, const std::string& imageName, const LLUUID& imageID,const std::string& xmlTagName) const; diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h index 07775dc30f..3115606d91 100644 --- a/indra/llui/llcallbackmap.h +++ b/indra/llui/llcallbackmap.h @@ -29,13 +29,13 @@ #include <map> #include <string> -#include <boost/function.hpp> +#include <functional> class LLCallbackMap { public: // callback definition. - typedef boost::function<void* (void* data)> callback_t; + typedef std::function<void* (void* data)> callback_t; typedef std::map<std::string, LLCallbackMap> map_t; typedef map_t::iterator map_iter_t; @@ -48,8 +48,8 @@ public: return (void*)panel; } - LLCallbackMap() : mCallback(NULL), mData(NULL) { } - LLCallbackMap(callback_t callback, void* data = NULL) : mCallback(callback), mData(data) { } + LLCallbackMap() : mCallback(nullptr), mData(nullptr) {} + LLCallbackMap(callback_t callback, void* data = nullptr) : mCallback(callback), mData(data) {} callback_t mCallback; void* mData; diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index da5afd0386..7506cd99c0 100644 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -45,12 +45,14 @@ LLChatEntry::LLChatEntry(const Params& p) mExpandLinesCount(p.expand_lines_count), mPrevLinesCount(0), mSingleLineMode(false), - mPrevExpandedLineCount(S32_MAX) + mPrevExpandedLineCount(S32_MAX), + mCurrentInput("") { // Initialize current history line iterator mCurrentHistoryLine = mLineHistory.begin(); mAutoIndent = false; + mShowChatMentionPicker = true; keepSelectionOnReturn(true); } @@ -189,6 +191,7 @@ bool LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) { needsReflow(); } + mCurrentInput = ""; break; case KEY_UP: @@ -196,6 +199,11 @@ bool LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) { if (!mLineHistory.empty() && mCurrentHistoryLine > mLineHistory.begin()) { + if (mCurrentHistoryLine == mLineHistory.end()) + { + mCurrentInput = getText(); + } + setText(*(--mCurrentHistoryLine)); endOfDoc(); } @@ -210,16 +218,15 @@ bool LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) case KEY_DOWN: if (mHasHistory && MASK_CONTROL == mask) { - if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1) ) + if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1)) { setText(*(++mCurrentHistoryLine)); endOfDoc(); } - else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1) ) + else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1)) { mCurrentHistoryLine++; - std::string empty(""); - setText(empty); + setText(mCurrentInput); needsReflow(); endOfDoc(); } diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index 5621ede1e7..9a0e8ee91e 100644 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -101,6 +101,8 @@ private: S32 mExpandLinesCount; S32 mPrevLinesCount; S32 mPrevExpandedLineCount; + + std::string mCurrentInput; }; #endif /* LLCHATENTRY_H_ */ diff --git a/indra/llui/llchatmentionhelper.cpp b/indra/llui/llchatmentionhelper.cpp new file mode 100644 index 0000000000..5745389a58 --- /dev/null +++ b/indra/llui/llchatmentionhelper.cpp @@ -0,0 +1,158 @@ +/** +* @file llchatmentionhelper.cpp +* +* $LicenseInfo:firstyear=2025&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2025, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "llchatmentionhelper.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lluictrl.h" + +constexpr char CHAT_MENTION_HELPER_FLOATER[] = "chat_mention_picker"; + +bool LLChatMentionHelper::isActive(const LLUICtrl* ctrl) const +{ + return mHostHandle.get() == ctrl; +} + +bool LLChatMentionHelper::isCursorInNameMention(const LLWString& wtext, S32 cursor_pos, S32* mention_start_pos) const +{ + if (cursor_pos <= 0 || cursor_pos > static_cast<S32>(wtext.size())) + return false; + + // Find the beginning of the current word + S32 start = cursor_pos - 1; + while (start > 0 && wtext[start - 1] != U32(' ') && wtext[start - 1] != U32('\n')) + { + --start; + } + + if (wtext[start] != U32('@')) + return false; + + if (mention_start_pos) + *mention_start_pos = start; + + S32 word_length = cursor_pos - start; + + if (word_length == 1) + { + return true; + } + + // Get the name after '@' + std::string name = wstring_to_utf8str(wtext.substr(start + 1, word_length - 1)); + LLStringUtil::toLower(name); + for (const auto& av_name : mAvatarNames) + { + if (av_name == name || av_name.find(name) == 0) + { + return true; + } + } + + return false; +} + +void LLChatMentionHelper::showHelper(LLUICtrl* host_ctrl, S32 local_x, S32 local_y, const std::string& av_name, std::function<void(std::string)> cb) +{ + if (mHelperHandle.isDead()) + { + LLFloater* av_picker_floater = LLFloaterReg::getInstance(CHAT_MENTION_HELPER_FLOATER); + mHelperHandle = av_picker_floater->getHandle(); + mHelperCommitConn = av_picker_floater->setCommitCallback([&](LLUICtrl* ctrl, const LLSD& param) { onCommitName(param.asString()); }); + } + setHostCtrl(host_ctrl); + mNameCommitCb = cb; + + S32 floater_x, floater_y; + if (!host_ctrl->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView)) + { + LL_WARNS() << "Cannot show helper for non-floater controls." << LL_ENDL; + return; + } + + LLFloater* av_picker_floater = mHelperHandle.get(); + LLRect rect = av_picker_floater->getRect(); + rect.setLeftTopAndSize(floater_x, floater_y + rect.getHeight(), rect.getWidth(), rect.getHeight()); + av_picker_floater->setRect(rect); + if (av_picker_floater->isShown()) + { + av_picker_floater->onOpen(LLSD().with("av_name", av_name)); + } + else + { + av_picker_floater->openFloater(LLSD().with("av_name", av_name)); + } +} + +void LLChatMentionHelper::hideHelper(const LLUICtrl* ctrl) +{ + if ((ctrl && !isActive(ctrl))) + { + return; + } + setHostCtrl(nullptr); +} + +bool LLChatMentionHelper::handleKey(const LLUICtrl* ctrl, KEY key, MASK mask) +{ + if (mHelperHandle.isDead() || !isActive(ctrl)) + { + return false; + } + + return mHelperHandle.get()->handleKey(key, mask, true); +} + +void LLChatMentionHelper::onCommitName(std::string name_url) +{ + if (!mHostHandle.isDead() && mNameCommitCb) + { + mNameCommitCb(name_url); + } +} + +void LLChatMentionHelper::setHostCtrl(LLUICtrl* host_ctrl) +{ + const LLUICtrl* pCurHostCtrl = mHostHandle.get(); + if (pCurHostCtrl != host_ctrl) + { + mHostCtrlFocusLostConn.disconnect(); + mHostHandle.markDead(); + mNameCommitCb = {}; + + if (!mHelperHandle.isDead()) + { + mHelperHandle.get()->closeFloater(); + } + + if (host_ctrl) + { + mHostHandle = host_ctrl->getHandle(); + mHostCtrlFocusLostConn = host_ctrl->setFocusLostCallback(std::bind([&]() { hideHelper(getHostCtrl()); })); + } + } +} diff --git a/indra/llui/llchatmentionhelper.h b/indra/llui/llchatmentionhelper.h new file mode 100644 index 0000000000..5f95d06f31 --- /dev/null +++ b/indra/llui/llchatmentionhelper.h @@ -0,0 +1,66 @@ +/** +* @file llchatmentionhelper.h +* @brief Header file for LLChatMentionHelper +* +* $LicenseInfo:firstyear=2025&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2025, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#pragma once + +#include "llhandle.h" +#include "llsingleton.h" + +#include <boost/signals2.hpp> + +class LLFloater; +class LLUICtrl; + +class LLChatMentionHelper : public LLSingleton<LLChatMentionHelper> +{ + LLSINGLETON(LLChatMentionHelper) {} + ~LLChatMentionHelper() override {} + +public: + + bool isActive(const LLUICtrl* ctrl) const; + bool isCursorInNameMention(const LLWString& wtext, S32 cursor_pos, S32* mention_start_pos = nullptr) const; + void showHelper(LLUICtrl* host_ctrl, S32 local_x, S32 local_y, const std::string& av_name, std::function<void(std::string)> commit_cb); + void hideHelper(const LLUICtrl* ctrl = nullptr); + + bool handleKey(const LLUICtrl* ctrl, KEY key, MASK mask); + void onCommitName(std::string name_url); + + void updateAvatarList(std::vector<std::string> av_names) { mAvatarNames = av_names; } + +protected: + void setHostCtrl(LLUICtrl* host_ctrl); + LLUICtrl* getHostCtrl() const { return mHostHandle.get(); } + +private: + LLHandle<LLUICtrl> mHostHandle; + LLHandle<LLFloater> mHelperHandle; + boost::signals2::connection mHostCtrlFocusLostConn; + boost::signals2::connection mHelperCommitConn; + std::function<void(std::string)> mNameCommitCb; + + std::vector<std::string> mAvatarNames; +}; diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index 135f128692..4068741978 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -36,8 +36,8 @@ // Constants // -const bool RADIO_STYLE = true; -const bool CHECK_STYLE = false; +constexpr bool RADIO_STYLE = true; +constexpr bool CHECK_STYLE = false; // // Classes @@ -94,7 +94,7 @@ public: // LLUICtrl interface virtual void setValue(const LLSD& value ); virtual LLSD getValue() const; - bool get() { return (bool)getValue().asBoolean(); } + bool get() const { return (bool)getValue().asBoolean(); } void set(bool value) { setValue(value); } virtual void setTentative(bool b); @@ -106,7 +106,7 @@ public: virtual void onCommit(); // LLCheckBoxCtrl interface - virtual bool toggle() { return mButton->toggleState(); } // returns new state + virtual bool toggle() { return mButton->toggleState(); } // returns new state void setBtnFocus() { mButton->setFocus(true); } diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h index 12d8233e0a..9f9cc3e54d 100644 --- a/indra/llui/llclipboard.h +++ b/indra/llui/llclipboard.h @@ -27,8 +27,6 @@ #ifndef LL_LLCLIPBOARD_H #define LL_LLCLIPBOARD_H -#include <boost/function.hpp> - #include "llstring.h" #include "lluuid.h" #include "llsingleton.h" diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index f3876ef695..ae676251ff 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -1009,7 +1009,7 @@ void LLComboBox::setKeystrokeOnEsc(bool enable) void LLComboBox::onTextEntry(LLLineEditor* line_editor) { - if (mTextEntryCallback != NULL) + if (mTextEntryCallback != nullptr) { (mTextEntryCallback)(line_editor, LLSD()); } @@ -1029,7 +1029,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) mList->deselectAllItems(); mLastSelectedIndex = -1; } - if (mTextChangedCallback != NULL) + if (mTextChangedCallback != nullptr) { (mTextChangedCallback)(line_editor, LLSD()); } @@ -1077,7 +1077,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) // RN: presumably text entry updateSelection(); } - if (mTextChangedCallback != NULL) + if (mTextChangedCallback != nullptr) { (mTextChangedCallback)(line_editor, LLSD()); } diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 8be3eb57e4..d6ea1202d3 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -36,7 +36,6 @@ #include "llrect.h" #include "llscrolllistctrl.h" #include "lllineeditor.h" -#include <boost/function.hpp> // Classes diff --git a/indra/llui/llcommandmanager.cpp b/indra/llui/llcommandmanager.cpp index 03717da80b..b10ec51f18 100644 --- a/indra/llui/llcommandmanager.cpp +++ b/indra/llui/llcommandmanager.cpp @@ -170,12 +170,14 @@ bool LLCommandManager::load() if (!parser.readXUI(commands_file, commandsParams)) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Unable to load xml file: " << commands_file << LL_ENDL; return false; } if (!commandsParams.validateBlock()) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Invalid commands file: " << commands_file << LL_ENDL; return false; } diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index c6dd401e85..2675d21c22 100644 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -65,21 +65,21 @@ protected: public: ~LLContainerView(); - /*virtual*/ bool postBuild(); - /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + bool postBuild() override; + bool addChild(LLView* view, S32 tab_group = 0) override; - /*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask); + bool handleDoubleClick(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; - /*virtual*/ void draw(); - /*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true); - /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. + void draw() override; + void reshape(S32 width, S32 height, bool called_from_parent = true) override; + LLRect getRequiredRect() override; // Return the height of this object, given the set options. void setLabel(const std::string& label); void showLabel(bool show) { mShowLabel = show; } void setDisplayChildren(bool displayChildren); - bool getDisplayChildren() { return mDisplayChildren; } + bool getDisplayChildren() const { return mDisplayChildren; } void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} private: diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 19ae03cdf9..c20e5a806c 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -77,7 +77,7 @@ LLDockableFloater::~LLDockableFloater() bool LLDockableFloater::postBuild() { // Remember we should force docking when the floater is opened for the first time - if (mIsDockedStateForcedCallback != NULL && mIsDockedStateForcedCallback()) + if (mIsDockedStateForcedCallback != nullptr && mIsDockedStateForcedCallback()) { mForceDocking = true; } diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 3effc977db..accd9fddfc 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -112,8 +112,8 @@ public: virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); } virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; } - bool getUniqueDocking() { return mUniqueDocking; } - bool getUseTongue() { return mUseTongue; } + bool getUniqueDocking() const { return mUniqueDocking; } + bool getUseTongue() const { return mUseTongue; } void setUseTongue(bool use_tongue) { mUseTongue = use_tongue;} private: @@ -129,7 +129,7 @@ protected: // Checks if docking should be forced. // It may be useful e.g. if floater created in mouselook mode (see EXT-5609) - boost::function<bool ()> mIsDockedStateForcedCallback; + std::function<bool()> mIsDockedStateForcedCallback; private: std::unique_ptr<LLDockControl> mDockControl; diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 11dbad8c09..1a00c03856 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -156,7 +156,7 @@ void LLDockControl::repositionDockable() } } -bool LLDockControl::isDockVisible() +bool LLDockControl::isDockVisible() const { bool res = true; diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index 7e31330713..1f6c3b9f57 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -49,11 +49,11 @@ public: public: // callback for a function getting a rect valid for control's position - typedef boost::function<void (LLRect& )> get_allowed_rect_callback_t; + typedef std::function<void (LLRect& )> get_allowed_rect_callback_t; LOG_CLASS(LLDockControl); LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, - const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_rect_callback = NULL); + const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_rect_callback = nullptr); virtual ~LLDockControl(); public: @@ -61,19 +61,19 @@ public: void off(); void forceRecalculatePosition(); void setDock(LLView* dockWidget); - LLView* getDock() + LLView* getDock() const { return mDockWidgetHandle.get(); } void repositionDockable(); void drawToungue(); - bool isDockVisible(); + bool isDockVisible() const; // gets a rect that bounds possible positions for a dockable control (EXT-1111) void getAllowedRect(LLRect& rect); - S32 getTongueWidth() { return mDockTongue->getWidth(); } - S32 getTongueHeight() { return mDockTongue->getHeight(); } + S32 getTongueWidth() const { return mDockTongue->getWidth(); } + S32 getTongueHeight() const { return mDockTongue->getHeight(); } private: virtual void moveDockable(); diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index a522e63243..73211d5292 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -66,7 +66,7 @@ public: void setMaxTitleWidth(S32 max_width) {mMaxTitleWidth = llmin(max_width, mMaxTitleWidth); } S32 getMaxTitleWidth() const { return mMaxTitleWidth; } void setButtonsRect(const LLRect& rect){ mButtonsRect = rect; } - LLRect getButtonsRect() { return mButtonsRect; } + LLRect getButtonsRect() const { return mButtonsRect; } void setTitleVisible(bool visible); virtual void setTitle( const std::string& title ) = 0; diff --git a/indra/llui/llemojidictionary.cpp b/indra/llui/llemojidictionary.cpp index 925608e47e..16e6f0591a 100644 --- a/indra/llui/llemojidictionary.cpp +++ b/indra/llui/llemojidictionary.cpp @@ -390,14 +390,17 @@ void LLEmojiDictionary::loadEmojis() continue; } + std::string category; std::list<std::string> categories = loadCategories(sd); if (categories.empty()) { - LL_WARNS() << "Skipping invalid emoji descriptor (no categories)" << LL_ENDL; - continue; + // Should already have a localization for "other symbols" + category = "other symbols"; + } + else + { + category = categories.front(); } - - std::string category = categories.front(); if (std::find(mSkipCategories.begin(), mSkipCategories.end(), category) != mSkipCategories.end()) { diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index b9441a9c91..7cdd19bebc 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -99,6 +99,7 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER); mHelperHandle = pHelperFloater->getHandle(); mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2)); + mHelperCloseConn = pHelperFloater->setCloseCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCloseHelper(ctrl, param); }); } setHostCtrl(hostctrl_p); mEmojiCommitCb = cb; @@ -116,7 +117,17 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c S32 top = floater_y - HELPER_FLOATER_OFFSET_Y + rect.getHeight(); rect.setLeftTopAndSize(left, top, rect.getWidth(), rect.getHeight()); pHelperFloater->setRect(rect); + + // Hack: Trying to open floater, search for a match, + // and hide floater immediately if no match found, + // instead of checking prior to opening + // + // Supress sounds in case floater won't be shown. + // Todo: add some kind of shouldShow(short_code) + U8 sound_flags = pHelperFloater->getSoundFlags(); + pHelperFloater->setSoundFlags(LLView::SILENT); pHelperFloater->openFloater(LLSD().with("hint", short_code)); + pHelperFloater->setSoundFlags(sound_flags); } void LLEmojiHelper::hideHelper(const LLUICtrl* ctrl_p, bool strict) @@ -148,6 +159,16 @@ void LLEmojiHelper::onCommitEmoji(llwchar emoji) } } +void LLEmojiHelper::onCloseHelper(LLUICtrl* ctrl, const LLSD& param) +{ + mCloseSignal(ctrl, param); +} + +boost::signals2::connection LLEmojiHelper::setCloseCallback(const commit_signal_t::slot_type& cb) +{ + return mCloseSignal.connect(cb); +} + void LLEmojiHelper::setHostCtrl(LLUICtrl* hostctrl_p) { const LLUICtrl* pCurHostCtrl = mHostHandle.get(); diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h index 2834b06061..26840eef94 100644 --- a/indra/llui/llemojihelper.h +++ b/indra/llui/llemojihelper.h @@ -51,16 +51,23 @@ public: // Eventing bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask); void onCommitEmoji(llwchar emoji); + void onCloseHelper(LLUICtrl* ctrl, const LLSD& param); + + typedef boost::signals2::signal<void(LLUICtrl* ctrl, const LLSD& param)> commit_signal_t; + boost::signals2::connection setCloseCallback(const commit_signal_t::slot_type& cb); protected: LLUICtrl* getHostCtrl() const { return mHostHandle.get(); } void setHostCtrl(LLUICtrl* hostctrl_p); private: + commit_signal_t mCloseSignal; + LLHandle<LLUICtrl> mHostHandle; LLHandle<LLFloater> mHelperHandle; boost::signals2::connection mHostCtrlFocusLostConn; boost::signals2::connection mHelperCommitConn; + boost::signals2::connection mHelperCloseConn; std::function<void(llwchar)> mEmojiCommitCb; bool mIsHideDisabled; }; diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h index 686827d94c..685219c9f6 100644 --- a/indra/llui/llfiltereditor.h +++ b/indra/llui/llfiltereditor.h @@ -49,7 +49,7 @@ protected: LLFilterEditor(const Params&); friend class LLUICtrlFactory; - /*virtual*/ void handleKeystroke(); + void handleKeystroke() override; }; #endif // LL_FILTEREDITOR_H diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp index c3db24c987..addc3375b3 100644 --- a/indra/llui/llflashtimer.cpp +++ b/indra/llui/llflashtimer.cpp @@ -50,7 +50,7 @@ LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period) void LLFlashTimer::unset() { mUnset = true; - mCallback = NULL; + mCallback = nullptr; } bool LLFlashTimer::tick() @@ -85,12 +85,12 @@ void LLFlashTimer::stopFlashing() mCurrentTickCount = 0; } -bool LLFlashTimer::isFlashingInProgress() +bool LLFlashTimer::isFlashingInProgress() const { return mIsFlashingInProgress; } -bool LLFlashTimer::isCurrentlyHighlighted() +bool LLFlashTimer::isCurrentlyHighlighted() const { return mIsCurrentlyHighlighted; } diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h index b55ce53fc0..1cd1df392b 100644 --- a/indra/llui/llflashtimer.h +++ b/indra/llui/llflashtimer.h @@ -28,13 +28,13 @@ #define LL_FLASHTIMER_H #include "lleventtimer.h" -#include "boost/function.hpp" +#include <functional> class LLFlashTimer : public LLEventTimer { public: - typedef boost::function<void (bool)> callback_t; + typedef std::function<void (bool)> callback_t; /** * Constructor. @@ -43,7 +43,7 @@ public: * @param period - how frequently callback should be called * @param cb - callback to be called each tick */ - LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0); + LLFlashTimer(callback_t cb = nullptr, S32 count = 0, F32 period = 0.0); ~LLFlashTimer() {}; /*virtual*/ bool tick(); @@ -51,8 +51,8 @@ public: void startFlashing(); void stopFlashing(); - bool isFlashingInProgress(); - bool isCurrentlyHighlighted(); + bool isFlashingInProgress() const; + bool isCurrentlyHighlighted() const; /* * Use this instead of deleting this object. * The next call to tick() will return true and that will destroy this object. diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 53f39766c6..34eb1ea3fc 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -69,7 +69,7 @@ const LLRect& LLFlatListView::getItemsRect() const bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/) { if (!item) return false; - if (value.isUndefined()) return false; + if (value.isUndefined()) return false; // item stays an orphan?!!! //force uniqueness of items, easiest check but unreliable if (item->getParent() == mItemsPanel) return false; @@ -459,6 +459,7 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p) , mNoItemsCommentTextbox(NULL) , mIsConsecutiveSelection(false) , mKeepSelectionVisibleOnReshape(p.keep_selection_visible_on_reshape) + , mFocusOnItemClicked(true) { mBorderThickness = getBorderWidth(); @@ -536,6 +537,7 @@ bool LLFlatListView::postBuild() void LLFlatListView::rearrangeItems() { + LL_PROFILE_ZONE_SCOPED; static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); setNoItemsCommentVisible(0==size()); @@ -610,7 +612,10 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask) return; } - setFocus(true); + if (mFocusOnItemClicked) + { + setFocus(true); + } bool select_item = !isSelected(item_pair); @@ -1128,6 +1133,7 @@ bool LLFlatListView::removeItemPair(item_pair_t* item_pair, bool rearrange) void LLFlatListView::notifyParentItemsRectChanged() { + LL_PROFILE_ZONE_SCOPED; S32 comment_height = 0; // take into account comment text height if exists @@ -1337,14 +1343,22 @@ void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string) } } -bool LLFlatListViewEx::getForceShowingUnmatchedItems() +bool LLFlatListViewEx::getForceShowingUnmatchedItems() const { return mForceShowingUnmatchedItems; } -void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show) +void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show, bool notify_parent) +{ + if (mForceShowingUnmatchedItems != show) { mForceShowingUnmatchedItems = show; + if (!mFilterSubString.empty()) + { + updateNoItemsMessage(mFilterSubString); + filterItems(false, true); + } + } } void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent) @@ -1389,7 +1403,7 @@ bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) return false; } -void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) +bool LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) { std::string cur_filter = mFilterSubString; LLStringUtil::toUpper(cur_filter); @@ -1412,8 +1426,11 @@ void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) if (visibility_changed && notify_parent) { + rearrangeItems(); notifyParentItemsRectChanged(); + return true; } + return false; } bool LLFlatListViewEx::hasMatchedItems() diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 6d75e9f282..39afa33be8 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -113,7 +113,7 @@ public: }; // disable traversal when finding widget to hand focus off to - /*virtual*/ bool canFocusChildren() const { return false; } + /*virtual*/ bool canFocusChildren() const override { return false; } /** * Connects callback to signal called when Return key is pressed. @@ -121,15 +121,15 @@ public: boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); } /** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */ - virtual void reshape(S32 width, S32 height, bool called_from_parent = true); + virtual void reshape(S32 width, S32 height, bool called_from_parent = true) override; /** Returns full rect of child panel */ const LLRect& getItemsRect() const; - LLRect getRequiredRect() { return getItemsRect(); } + LLRect getRequiredRect() override { return getItemsRect(); } /** Returns distance between items */ - const S32 getItemsPad() { return mItemPad; } + const S32 getItemsPad() const { return mItemPad; } /** * Adds and item and LLSD value associated with it to the list at specified position @@ -264,13 +264,13 @@ public: void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; } /** Get number of selected items in the list */ - U32 numSelected() const {return static_cast<U32>(mSelectedItemPairs.size()); } + U32 numSelected() const { return static_cast<U32>(mSelectedItemPairs.size()); } /** Get number of (visible) items in the list */ U32 size(const bool only_visible_items = true) const; /** Removes all items from the list */ - virtual void clear(); + virtual void clear() override; /** * Removes all items that can be detached from the list but doesn't destroy @@ -294,10 +294,12 @@ public: void scrollToShowFirstSelectedItem(); - void selectFirstItem (); - void selectLastItem (); + void selectFirstItem(); + void selectLastItem(); - virtual S32 notify(const LLSD& info) ; + virtual S32 notify(const LLSD& info) override; + + void setFocusOnItemClicked(bool b) { mFocusOnItemClicked = b; } virtual ~LLFlatListView(); @@ -346,8 +348,8 @@ protected: virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection); - virtual bool canSelectAll() const; - virtual void selectAll(); + virtual bool canSelectAll() const override; + virtual void selectAll() override; virtual bool isSelected(item_pair_t* item_pair) const; @@ -364,15 +366,15 @@ protected: */ void notifyParentItemsRectChanged(); - virtual bool handleKeyHere(KEY key, MASK mask); + virtual bool handleKeyHere(KEY key, MASK mask) override; - virtual bool postBuild(); + virtual bool postBuild() override; - virtual void onFocusReceived(); + virtual void onFocusReceived() override; - virtual void onFocusLost(); + virtual void onFocusLost() override; - virtual void draw(); + virtual void draw() override; LLRect getLastSelectedItemRect(); @@ -423,6 +425,8 @@ private: bool mKeepSelectionVisibleOnReshape; + bool mFocusOnItemClicked; + /** All pairs of the list */ pairs_list_t mItemPairs; @@ -478,21 +482,26 @@ public: void setNoItemsMsg(const std::string& msg) { mNoItemsMsg = msg; } void setNoFilteredItemsMsg(const std::string& msg) { mNoFilteredItemsMsg = msg; } - bool getForceShowingUnmatchedItems(); + bool getForceShowingUnmatchedItems() const; - void setForceShowingUnmatchedItems(bool show); + /** + * Sets filtered out items to stay visible. Can result in rect changes, + * so can notify_parent if rect changes + */ + void setForceShowingUnmatchedItems(bool show, bool notify_parent); /** * Sets up new filter string and filters the list. */ void setFilterSubString(const std::string& filter_str, bool notify_parent); - std::string getFilterSubString() { return mFilterSubString; } + std::string getFilterSubString() const { return mFilterSubString; } /** * Filters the list, rearranges and notifies parent about shape changes. * Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration. + * Returns true in case of changes */ - void filterItems(bool re_sort, bool notify_parent); + bool filterItems(bool re_sort, bool notify_parent); /** * Returns true if last call of filterItems() found at least one matching item diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 4b904f09e0..52a5e3dbd6 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2165,7 +2165,7 @@ void LLFloater::setCanDrag(bool can_drag) } } -bool LLFloater::getCanDrag() +bool LLFloater::getCanDrag() const { return mDragHandle->getEnabled(); } @@ -2274,7 +2274,7 @@ void LLFloater::drawConeToOwner(F32 &context_cone_opacity, LLRect local_rect = getLocalRect(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable(GL_CULL_FACE); + LLGLEnable cull_face(GL_CULL_FACE); gGL.begin(LLRender::TRIANGLE_STRIP); { gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity); diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 9be2240f6f..9e1594bdd2 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -46,24 +46,24 @@ class LLMultiFloater; class LLFloater; -const bool RESIZE_YES = true; -const bool RESIZE_NO = false; +constexpr bool RESIZE_YES = true; +constexpr bool RESIZE_NO = false; -const bool DRAG_ON_TOP = false; -const bool DRAG_ON_LEFT = true; +constexpr bool DRAG_ON_TOP = false; +constexpr bool DRAG_ON_LEFT = true; -const bool MINIMIZE_YES = true; -const bool MINIMIZE_NO = false; +constexpr bool MINIMIZE_YES = true; +constexpr bool MINIMIZE_NO = false; -const bool CLOSE_YES = true; -const bool CLOSE_NO = false; +constexpr bool CLOSE_YES = true; +constexpr bool CLOSE_NO = false; -const bool ADJUST_VERTICAL_YES = true; -const bool ADJUST_VERTICAL_NO = false; +constexpr bool ADJUST_VERTICAL_YES = true; +constexpr bool ADJUST_VERTICAL_NO = false; -const F32 CONTEXT_CONE_IN_ALPHA = 0.f; -const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; -const F32 CONTEXT_CONE_FADE_TIME = .08f; +constexpr F32 CONTEXT_CONE_IN_ALPHA = 0.f; +constexpr F32 CONTEXT_CONE_OUT_ALPHA = 1.f; +constexpr F32 CONTEXT_CONE_FADE_TIME = .08f; namespace LLFloaterEnums { @@ -228,7 +228,7 @@ public: /*virtual*/ void setIsChrome(bool is_chrome); /*virtual*/ void setRect(const LLRect &rect); void setIsSingleInstance(bool is_single_instance); - bool getIsSingleInstance() { return mSingleInstance; } + bool getIsSingleInstance() const { return mSingleInstance; } void initFloater(const Params& p); @@ -274,17 +274,17 @@ public: static bool isShown(const LLFloater* floater); static bool isVisible(const LLFloater* floater); static bool isMinimized(const LLFloater* floater); - bool isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts + bool isFirstLook() const { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts virtual bool isFrontmost(); - bool isDependent() { return !mDependeeHandle.isDead(); } + bool isDependent() const { return !mDependeeHandle.isDead(); } void setCanMinimize(bool can_minimize); void setCanClose(bool can_close); void setCanTearOff(bool can_tear_off); virtual void setCanResize(bool can_resize); void setCanDrag(bool can_drag); - bool getCanDrag(); + bool getCanDrag() const; void setHost(LLMultiFloater* host); - bool isResizable() const { return mResizable; } + bool isResizable() const { return mResizable; } void setResizeLimits( S32 min_width, S32 min_height ); void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } @@ -347,7 +347,7 @@ public: virtual void setDocked(bool docked, bool pop_on_undock = true); virtual void setTornOff(bool torn_off) { mTornOff = torn_off; } - bool isTornOff() {return mTornOff;} + bool isTornOff() const { return mTornOff; } void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;} @@ -377,6 +377,10 @@ public: void enableResizeCtrls(bool enable, bool width = true, bool height = true); bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mPositioning); } + + void setAutoFocus(bool focus) { mAutoFocus = focus; } // whether to automatically take focus when opened + bool getAutoFocus() const { return mAutoFocus; } + protected: void applyControlsAndPosition(LLFloater* other); @@ -401,8 +405,6 @@ protected: void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized const LLRect& getExpandedRect() const { return mExpandedRect; } - void setAutoFocus(bool focus) { mAutoFocus = focus; } // whether to automatically take focus when opened - bool getAutoFocus() const { return mAutoFocus; } LLDragHandle* getDragHandle() const { return mDragHandle; } void destroy(); // Don't call this directly. You probably want to call closeFloater() @@ -423,7 +425,6 @@ protected: private: void setForeground(bool b); // called only by floaterview void cleanupHandles(); // remove handles to dead floaters - void createMinimizeButton(); void buildButtons(const Params& p); // Images and tooltips are named in the XML, but we want to look them diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 94a67c8d8b..24d1476dda 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -30,8 +30,8 @@ #include "llrect.h" #include "llsd.h" +#include <functional> #include <list> -#include <boost/function.hpp> //******************************************************* // @@ -41,7 +41,7 @@ class LLFloater; class LLUICtrl; -typedef boost::function<LLFloater* (const LLSD& key)> LLFloaterBuildFunc; +typedef std::function<LLFloater* (const LLSD& key)> LLFloaterBuildFunc; class LLFloaterReg { diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h index a36072892c..28f6e7c66b 100644 --- a/indra/llui/llfloaterreglistener.h +++ b/indra/llui/llfloaterreglistener.h @@ -30,7 +30,6 @@ #define LL_LLFLOATERREGLISTENER_H #include "lleventapi.h" -#include <string> class LLSD; diff --git a/indra/llui/llflyoutbutton.h b/indra/llui/llflyoutbutton.h index 7a49501318..73190fc984 100644 --- a/indra/llui/llflyoutbutton.h +++ b/indra/llui/llflyoutbutton.h @@ -54,7 +54,7 @@ protected: LLFlyoutButton(const Params&); friend class LLUICtrlFactory; public: - virtual void draw(); + void draw() override; void setToggleState(bool state); diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 0d7c98294f..7544a44478 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -32,11 +32,11 @@ const F32 FOCUS_FADE_TIME = 0.3f; -LLFocusableElement::LLFocusableElement() -: mFocusLostCallback(NULL), - mFocusReceivedCallback(NULL), - mFocusChangedCallback(NULL), - mTopLostCallback(NULL) +LLFocusableElement::LLFocusableElement() : + mFocusLostCallback(nullptr), + mFocusReceivedCallback(nullptr), + mFocusChangedCallback(nullptr), + mTopLostCallback(nullptr) { } diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index 1fa0ac137e..89fee5c9f1 100644 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -97,7 +97,7 @@ public: LLFocusableElement* getLastKeyboardFocus() const { return mLastKeyboardFocus; } bool childHasKeyboardFocus( const LLView* parent ) const; void removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus ); - bool getKeystrokesOnly() { return mKeystrokesOnly; } + bool getKeystrokesOnly() const { return mKeystrokesOnly; } void setKeystrokesOnly(bool keystrokes_only) { mKeystrokesOnly = keystrokes_only; } F32 getFocusFlashAmt() const; diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index b664065532..db4ab8487e 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1510,6 +1510,7 @@ bool LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) && ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible !hide_folder_menu) { + LL_INFOS("Inventory") << "Opening inventory menu from path: " << getPathname() << LL_ENDL; if (mCallbackRegistrar) { mCallbackRegistrar->pushScope(); diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 7ed10d9223..368a86ea84 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -124,11 +124,11 @@ public: void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } - bool getAllowMultiSelect() { return mAllowMultiSelect; } - bool getAllowDrag() { return mAllowDrag; } + bool getAllowMultiSelect() const { return mAllowMultiSelect; } + bool getAllowDrag() const { return mAllowDrag; } void setSingleFolderMode(bool is_single_mode) { mSingleFolderMode = is_single_mode; } - bool isSingleFolderMode() { return mSingleFolderMode; } + bool isSingleFolderMode() const { return mSingleFolderMode; } // Close all folders in the view void closeAllFolders(); @@ -142,7 +142,7 @@ public: virtual S32 getItemHeight() const; void arrangeAll() { mArrangeGeneration++; } - S32 getArrangeGeneration() { return mArrangeGeneration; } + S32 getArrangeGeneration() const { return mArrangeGeneration; } // applies filters to control visibility of items virtual void filter( LLFolderViewFilter& filter); @@ -221,33 +221,34 @@ public: void scrollToShowSelection(); void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } + LLScrollContainer* getScrollContainer() { return mScrollContainer; } LLRect getVisibleRect(); bool search(LLFolderViewItem* first_item, const std::string &search_string, bool backward); void setShowSelectionContext(bool show) { mShowSelectionContext = show; } bool getShowSelectionContext(); void setShowSingleSelection(bool show); - bool getShowSingleSelection() { return mShowSingleSelection; } - F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } - bool getUseEllipses() { return mUseEllipses; } - S32 getSelectedCount() { return (S32)mSelectedItems.size(); } + bool getShowSingleSelection() const { return mShowSingleSelection; } + F32 getSelectionFadeElapsedTime() const { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } + bool getUseEllipses() const { return mUseEllipses; } + S32 getSelectedCount() const { return (S32)mSelectedItems.size(); } - void update(); // needs to be called periodically (e.g. once per frame) + void update(); // needs to be called periodically (e.g. once per frame) - bool needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } - bool needsAutoRename() { return mNeedsAutoRename; } + bool needsAutoSelect() const { return mNeedsAutoSelect && !mAutoSelectOverride; } + bool needsAutoRename() const { return mNeedsAutoRename; } void setNeedsAutoRename(bool val) { mNeedsAutoRename = val; } void setPinningSelectedItem(bool val) { mPinningSelectedItem = val; } void setAutoSelectOverride(bool val) { mAutoSelectOverride = val; } - bool showItemLinkOverlays() { return mShowItemLinkOverlays; } + bool showItemLinkOverlays() const { return mShowItemLinkOverlays; } void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; } void setForceArrange(bool force) { mForceArrange = force; } - LLPanel* getParentPanel() { return mParentPanel.get(); } + LLPanel* getParentPanel() const { return mParentPanel.get(); } // DEBUG only void dumpSelectionInformation(); @@ -255,7 +256,7 @@ public: void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; } - bool useLabelSuffix() { return mUseLabelSuffix; } + bool useLabelSuffix() const { return mUseLabelSuffix; } virtual void updateMenu(); void finishRenamingItem( void ); @@ -391,7 +392,7 @@ public: virtual ~LLSelectFirstFilteredItem() {} virtual void doFolder(LLFolderViewFolder* folder); virtual void doItem(LLFolderViewItem* item); - bool wasItemSelected() { return mItemSelected || mFolderSelected; } + bool wasItemSelected() const { return mItemSelected || mFolderSelected; } protected: bool mItemSelected; bool mFolderSelected; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 18bde344a0..878f1cb856 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -23,7 +23,7 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#include "../newview/llviewerprecompiledheaders.h" +#include "linden_common.h" #include "llflashtimer.h" @@ -31,11 +31,12 @@ #include "llfolderviewitem.h" #include "llfolderview.h" #include "llfolderviewmodel.h" -#include "llpanel.h" #include "llcallbacklist.h" #include "llcriticaldamp.h" #include "llclipboard.h" #include "llfocusmgr.h" // gFocusMgr +#include "llnotificationsutil.h" +#include "llpanel.h" #include "lltrans.h" #include "llwindow.h" @@ -60,7 +61,11 @@ LLUIColor LLFolderViewItem::sSearchStatusColor; S32 LLFolderViewItem::sTopPad = 0; LLUIImagePtr LLFolderViewItem::sFolderArrowImg; LLUIImagePtr LLFolderViewItem::sSelectionImg; +LLUIImagePtr LLFolderViewItem::sFavoriteImg; +LLUIImagePtr LLFolderViewItem::sFavoriteContentImg; LLFontGL* LLFolderViewItem::sSuffixFont = nullptr; +LLUIColor LLFolderViewItem::sFavoriteColor; +bool LLFolderViewItem::sColorSetInitialized = false; // only integers can be initialized in header const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; @@ -68,6 +73,9 @@ const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; const LLColor4U DEFAULT_WHITE(255, 255, 255); +constexpr S32 FAVORITE_IMAGE_SIZE = 14; +constexpr S32 FAVORITE_IMAGE_PAD = 3; + //static LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) @@ -102,6 +110,8 @@ void LLFolderViewItem::initClass() sTopPad = default_params.item_top_pad; sFolderArrowImg = default_params.folder_arrow_image; sSelectionImg = default_params.selection_image; + sFavoriteImg = default_params.favorite_image; + sFavoriteContentImg = default_params.favorite_content_image; sSuffixFont = getLabelFontForStyle(LLFontGL::NORMAL); sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); @@ -121,6 +131,8 @@ void LLFolderViewItem::cleanupClass() sFonts.clear(); sFolderArrowImg = nullptr; sSelectionImg = nullptr; + sFavoriteImg = nullptr; + sFavoriteContentImg = nullptr; sSuffixFont = nullptr; } @@ -129,13 +141,15 @@ void LLFolderViewItem::cleanupClass() LLFolderViewItem::Params::Params() : root(), listener(), + favorite_image("favorite_image"), + favorite_content_image("favorite_content_image"), folder_arrow_image("folder_arrow_image"), folder_indentation("folder_indentation"), selection_image("selection_image"), item_height("item_height"), item_top_pad("item_top_pad"), creation_date(), - allow_wear("allow_wear", true), + marketplace_item("marketplace_item", false), allow_drop("allow_drop", true), font_color("font_color"), font_highlight_color("font_highlight_color"), @@ -155,6 +169,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) : LLView(p), mLabelWidth(0), mLabelWidthDirty(false), + mIsFavorite(false), + mHasFavorites(false), mSuffixNeedsRefresh(false), mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), mParentFolder( NULL ), @@ -175,7 +191,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mRoot(p.root), mViewModelItem(p.listener), mIsMouseOverTitle(false), - mAllowWear(p.allow_wear), + mMarketplaceItem(p.marketplace_item), mAllowDrop(p.allow_drop), mFontColor(p.font_color), mFontHighlightColor(p.font_highlight_color), @@ -189,6 +205,21 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mMaxFolderItemOverlap(p.max_folder_item_overlap), mDoubleClickOverride(p.double_click_override) { + if (!sColorSetInitialized) + { + sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); + sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + sFavoriteColor = LLUIColorTable::instance().getColor("InventoryFavoriteColor", DEFAULT_WHITE); + sColorSetInitialized = true; + } + if (mViewModelItem) { mViewModelItem->setFolderViewItem(this); @@ -211,6 +242,7 @@ bool LLFolderViewItem::postBuild() // getDisplayName() is expensive (due to internal getLabelSuffix() and name building) // it also sets search strings so it requires a filter reset mLabel = utf8str_to_wstring(vmi->getDisplayName()); + mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash(); setToolTip(vmi->getName()); // Dirty the filter flag of the model from the view (CHUI-849) @@ -325,6 +357,7 @@ void LLFolderViewItem::refresh() mLabel = utf8str_to_wstring(vmi.getDisplayName()); mLabelFontBuffer.reset(); + mIsFavorite = vmi.isFavorite() && !vmi.isItemInTrash(); setToolTip(vmi.getName()); // icons are slightly expensive to get, can be optimized // see LLInventoryIcon::getIcon() @@ -359,6 +392,8 @@ void LLFolderViewItem::refreshSuffix() mIconOpen = vmi->getIconOpen(); mIconOverlay = vmi->getIconOverlay(); + mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash(); + if (mRoot->useLabelSuffix()) { // Very Expensive! @@ -428,6 +463,10 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) } mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel.c_str()) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix.c_str()) + mLabelPaddingRight; mLabelWidthDirty = false; + if (mIsFavorite) + { + mLabelWidth += FAVORITE_IMAGE_SIZE + FAVORITE_IMAGE_PAD; + } } *width = llmax(*width, mLabelWidth); @@ -554,10 +593,15 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) void LLFolderViewItem::openItem( void ) { - if (mAllowWear || !getViewModelItem()->isItemWearable()) + if (!mMarketplaceItem || !getViewModelItem()->isItemWearable()) { getViewModelItem()->openItem(); } + else if (mMarketplaceItem) + { + // Wearing an object from any listing, active or not, is verbotten + LLNotificationsUtil::add("AlertMerchantListingCannotWear"); + } } void LLFolderViewItem::rename(const std::string& new_name) @@ -771,6 +815,45 @@ void LLFolderViewItem::drawOpenFolderArrow() } } +void LLFolderViewItem::drawFavoriteIcon() +{ + static LLUICachedControl<bool> draw_star("InventoryFavoritesUseStar", true); + static LLUICachedControl<bool> draw_hollow_star("InventoryFavoritesUseHollowStar", true); + + LLUIImage* favorite_image = nullptr; + if (draw_star && mIsFavorite) + { + favorite_image = sFavoriteImg; + } + else if (draw_hollow_star && mHasFavorites && !isOpen()) + { + favorite_image = sFavoriteContentImg; + } + + if (favorite_image) + { + S32 x_offset = 0; + LLScrollContainer* scroll = mRoot->getScrollContainer(); + if (scroll) + { + S32 width = scroll->getVisibleContentRect().getWidth(); + S32 offset = scroll->getDocPosHorizontal(); + x_offset = width + offset; + } + else + { + x_offset = getRect().getWidth(); + } + gl_draw_scaled_image( + x_offset - FAVORITE_IMAGE_SIZE - FAVORITE_IMAGE_PAD, + getRect().getHeight() - mItemHeight + FAVORITE_IMAGE_PAD, + FAVORITE_IMAGE_SIZE, + FAVORITE_IMAGE_SIZE, + favorite_image->getImage(), + sFgColor); + } +} + /*virtual*/ bool LLFolderViewItem::isHighlightAllowed() { return mIsSelected; @@ -928,6 +1011,7 @@ void LLFolderViewItem::draw() { drawOpenFolderArrow(); } + drawFavoriteIcon(); drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); @@ -999,7 +1083,20 @@ void LLFolderViewItem::draw() } } - LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; + static LLUICachedControl<bool> highlight_color("InventoryFavoritesColorText", true); + LLColor4 color; + if (mIsSelected && filled) + { + color = mFontHighlightColor; + } + else if (mIsFavorite && highlight_color) + { + color = sFavoriteColor; + } + else + { + color = mFontColor; + } if (isFadeItem()) { @@ -1093,7 +1190,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): 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) + mLastCalculatedWidth(0), + mFavoritesDirtyFlags(0) { } @@ -1119,6 +1217,11 @@ LLFolderViewFolder::~LLFolderViewFolder( void ) // The LLView base class takes care of object destruction. make sure that we // don't have mouse or keyboard focus gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() + + if (mFavoritesDirtyFlags) + { + gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this); + } } // addToFolder() returns true if it succeeds. false otherwise @@ -1762,6 +1865,148 @@ bool LLFolderViewFolder::isMovable() return true; } +void LLFolderViewFolder::updateHasFavorites(bool new_childs_value) +{ + if (mFavoritesDirtyFlags == 0) + { + gIdleCallbacks.addFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this); + } + if (new_childs_value) + { + mFavoritesDirtyFlags |= FAVORITE_ADDED; + } + else + { + mFavoritesDirtyFlags |= FAVORITE_REMOVED; + } +} + +void LLFolderViewFolder::onIdleUpdateFavorites(void* data) +{ + LLFolderViewFolder* self = reinterpret_cast<LLFolderViewFolder*>(data); + if (self->mFavoritesDirtyFlags == FAVORITE_CLEANUP) + { + // parent or child already processed the update, clean the callback + self->mFavoritesDirtyFlags = 0; + gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, data); + return; + } + + if (self->mFavoritesDirtyFlags == 0) + { + llassert(false); // should not happen, everything that sets to 0 should clean callback + gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, data); + return; + } + + if (self->getViewModelItem()->isItemInTrash()) + { + // do not display favorite-stars in trash + self->mFavoritesDirtyFlags = 0; + gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self); + return; + } + + if (self->mFavoritesDirtyFlags == FAVORITE_ADDED) + { + if (!self->mHasFavorites) + { + // propagate up, exclude root + LLFolderViewFolder* parent = self; + while (parent + && (!parent->hasFavorites() || parent->mFavoritesDirtyFlags) + && !parent->getViewModelItem()->isAgentInventoryRoot()) + { + parent->setHasFavorites(true); + if (parent->mFavoritesDirtyFlags) + { + // Parent will remove onIdleUpdateFavorites later, don't remove now, + // We are inside gIdleCallbacks. Removing 'self' callback is safe, + // but removing 'parent' can invalidate following iterator + parent->mFavoritesDirtyFlags = FAVORITE_CLEANUP; + } + parent = parent->getParentFolder(); + } + } + else + { + // already up to date + self->mFavoritesDirtyFlags = 0; + gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self); + } + } + else if (self->mFavoritesDirtyFlags > FAVORITE_ADDED) + { + // full check + LLFolderViewFolder* parent = self; + while (parent && !parent->getViewModelItem()->isAgentInventoryRoot()) + { + bool has_favorites = false; + for (items_t::iterator iter = parent->mItems.begin(); + iter != parent->mItems.end();) + { + items_t::iterator iit = iter++; + if ((*iit)->isFavorite()) + { + has_favorites = true; + break; + } + } + + for (folders_t::iterator iter = parent->mFolders.begin(); + iter != parent->mFolders.end() && !has_favorites;) + { + folders_t::iterator fit = iter++; + if ((*fit)->isFavorite() || (*fit)->hasFavorites()) + { + has_favorites = true; + break; + } + } + + if (!has_favorites) + { + if (parent->hasFavorites()) + { + parent->setHasFavorites(false); + } + else + { + // Nothing changed + break; + } + } + else + { + // propagate up, exclude root + while (parent + && (!parent->hasFavorites() || parent->mFavoritesDirtyFlags) + && !parent->getViewModelItem()->isAgentInventoryRoot()) + { + parent->setHasFavorites(true); + if (parent->mFavoritesDirtyFlags) + { + // Parent will remove onIdleUpdateFavorites later, don't remove now, + // We are inside gIdleCallbacks. Removing 'self' callback is safe, + // but removing 'parent' can invalidate following iterator + parent->mFavoritesDirtyFlags = FAVORITE_CLEANUP; + } + parent = parent->getParentFolder(); + } + break; + } + if (parent->mFavoritesDirtyFlags) + { + // Parent will remove onIdleUpdateFavorites later, don't remove now. + // We are inside gIdleCallbacks. Removing 'self' callback is safe, + // but removing 'parent' can invalidate following iterator + parent->mFavoritesDirtyFlags = FAVORITE_CLEANUP; + } + parent = parent->getParentFolder(); + } + } +} + bool LLFolderViewFolder::isRemovable() { @@ -1869,10 +2114,14 @@ void LLFolderViewFolder::setOpen(bool openitem) { // navigateToFolder can destroy this view // delay it in case setOpen was called from click or key processing - doOnIdleOneTime([this]() - { - getViewModelItem()->navigateToFolder(); - }); + LLPointer<LLFolderViewModelItem> view_model_item = mViewModelItem; + doOnIdleOneTime([view_model_item]() + { + if (view_model_item.notNull()) + { + view_model_item.get()->navigateToFolder(); + } + }); } else { diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index cc8a7d934c..23d794bf26 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -50,7 +50,9 @@ class LLFolderViewItem : public LLView public: struct Params : public LLInitParam::Block<Params, LLView::Params> { - Optional<LLUIImage*> folder_arrow_image, + Optional<LLUIImage*> favorite_image, + favorite_content_image, + folder_arrow_image, selection_image; Mandatory<LLFolderView*> root; Mandatory<LLFolderViewModelItem*> listener; @@ -60,7 +62,7 @@ public: item_top_pad; Optional<time_t> creation_date; - Optional<bool> allow_wear; + Optional<bool> marketplace_item; Optional<bool> allow_drop; Optional<LLUIColor> font_color; @@ -93,6 +95,8 @@ protected: LLWString mLabel; S32 mLabelWidth; bool mLabelWidthDirty; + bool mIsFavorite; + bool mHasFavorites; S32 mLabelPaddingRight; LLFolderViewFolder* mParentFolder; LLPointer<LLFolderViewModelItem> mViewModelItem; @@ -122,7 +126,7 @@ protected: mIsCurSelection, mDragAndDropTarget, mIsMouseOverTitle, - mAllowWear, + mMarketplaceItem, mAllowDrop, mSingleFolderMode, mDoubleClickOverride, @@ -133,6 +137,7 @@ protected: LLUIColor mFontColor; LLUIColor mFontHighlightColor; + static bool sColorSetInitialized; // For now assuming all colors are the same in derived classes. static LLUIColor sFgColor; @@ -145,6 +150,8 @@ protected: static LLUIColor sFilterTextColor; static LLUIColor sSuffixColor; static LLUIColor sSearchStatusColor; + static LLUIColor sFavoriteColor; + // this is an internal method used for adding items to folders. A // no-op at this level, but reimplemented in derived classes. @@ -154,7 +161,7 @@ protected: virtual bool isHighlightActive(); virtual bool isFadeItem(); virtual bool isFlashing() { return false; } - virtual void setFlashState(bool) { } + virtual void setFlashState(bool, bool) { } static LLFontGL* getLabelFontForStyle(U8 style); const LLFontGL* getLabelFont(); @@ -208,6 +215,8 @@ public: // Returns true is this object and all of its children can be moved virtual bool isMovable(); + bool isFavorite() const { return mIsFavorite; } + // destroys this item recursively virtual void destroyView(); @@ -282,7 +291,7 @@ public: // Does not need filter update virtual void refreshSuffix(); - bool isSingleFolderMode() { return mSingleFolderMode; } + bool isSingleFolderMode() const { return mSingleFolderMode; } // LLView functionality virtual bool handleRightMouseDown( S32 x, S32 y, MASK mask ); @@ -298,6 +307,7 @@ public: // virtual void handleDropped(); virtual void draw(); void drawOpenFolderArrow(); + void drawFavoriteIcon(); void drawHighlight(bool showContent, bool hasKeyboardFocus, const LLUIColor& selectColor, const LLUIColor& flashColor, const LLUIColor& outlineColor, const LLUIColor& mouseOverColor); void drawLabel(const LLFontGL* font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, @@ -311,6 +321,8 @@ private: static S32 sTopPad; static LLUIImagePtr sFolderArrowImg; static LLUIImagePtr sSelectionImg; + static LLUIImagePtr sFavoriteImg; + static LLUIImagePtr sFavoriteContentImg; static LLFontGL* sSuffixFont; LLFontVertexBuffer mLabelFontBuffer; @@ -400,6 +412,19 @@ public: // Returns true is this object and all of its children can be moved virtual bool isMovable(); + bool isFavorite() const { return mIsFavorite; } + bool hasFavorites() const { return mHasFavorites; } + void setHasFavorites(bool val) { mHasFavorites = val; } + void updateHasFavorites(bool new_childs_value); +private: + static void onIdleUpdateFavorites(void* data); + + constexpr static S32 FAVORITE_ADDED = 1; + constexpr static S32 FAVORITE_REMOVED = 2; + constexpr static S32 FAVORITE_CLEANUP = 4; + S32 mFavoritesDirtyFlags { 0 }; +public: + // destroys this folder, and all children virtual void destroyView(); void destroyRoot(); @@ -415,9 +440,6 @@ public: // doesn't delete it. virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true); - // This function is called by a child that needs to be resorted. - void resort(LLFolderViewItem* item); - void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } // folders can be opened. This will usually be called by internal diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 9372818ca5..07e8b890b8 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -162,6 +162,7 @@ public: virtual void navigateToFolder(bool new_window = false, bool change_mode = false) = 0; + virtual bool isFavorite() const = 0; virtual bool isItemWearable() const { return false; } virtual bool isItemRenameable() const = 0; @@ -170,7 +171,8 @@ public: virtual bool isItemMovable( void ) const = 0; // Can be moved to another folder virtual void move( LLFolderViewModelItem* parent_listener ) = 0; - virtual bool isItemRemovable( bool check_worn = true ) const = 0; // Can be destroyed + virtual bool isItemRemovable( bool check_worn = true) const = 0; // Can be destroyed + virtual bool isItemInTrash(void) const = 0; virtual bool removeItem() = 0; virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; @@ -183,6 +185,9 @@ public: virtual void pasteFromClipboard() = 0; virtual void pasteLinkFromClipboard() = 0; + virtual bool isAgentInventory() const = 0; + virtual bool isAgentInventoryRoot() const = 0; + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? @@ -219,6 +224,7 @@ public: virtual S32 getSortVersion() = 0; virtual void setSortVersion(S32 version) = 0; virtual void setParent(LLFolderViewModelItem* parent) = 0; + virtual const LLFolderViewModelItem* getParent() = 0; virtual bool hasParent() = 0; protected: @@ -249,14 +255,14 @@ public: mChildren.clear(); } - void requestSort() { mSortVersion = -1; } - S32 getSortVersion() { return mSortVersion; } - void setSortVersion(S32 version) { mSortVersion = version;} + void requestSort() override { mSortVersion = -1; } + S32 getSortVersion() override { return mSortVersion; } + void setSortVersion(S32 version) override { mSortVersion = version;} - S32 getLastFilterGeneration() const { return mLastFilterGeneration; } + S32 getLastFilterGeneration() const override { return mLastFilterGeneration; } S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; } - S32 getMarkedDirtyGeneration() const { return mMarkedDirtyGeneration; } - void dirtyFilter() + S32 getMarkedDirtyGeneration() const override { return mMarkedDirtyGeneration; } + void dirtyFilter() override { if(mMarkedDirtyGeneration < 0) { @@ -271,7 +277,7 @@ public: mParent->dirtyFilter(); } } - void dirtyDescendantsFilter() + void dirtyDescendantsFilter() override { mMostFilteredDescendantGeneration = -1; if (mParent) @@ -279,13 +285,13 @@ public: mParent->dirtyDescendantsFilter(); } } - bool hasFilterStringMatch(); - std::string::size_type getFilterStringOffset(); - std::string::size_type getFilterStringSize(); + bool hasFilterStringMatch() override; + std::string::size_type getFilterStringOffset() override; + std::string::size_type getFilterStringSize() override; - typedef std::list<LLFolderViewModelItem*> child_list_t; + typedef std::list<LLPointer<LLFolderViewModelItem> > child_list_t; - virtual void addChild(LLFolderViewModelItem* child) + virtual void addChild(LLFolderViewModelItem* child) override { mChildren.push_back(child); child->setParent(this); @@ -293,15 +299,15 @@ public: requestSort(); } - virtual void removeChild(LLFolderViewModelItem* child) + virtual void removeChild(LLFolderViewModelItem* child) override final { - mChildren.remove(child); child->setParent(NULL); + mChildren.remove(child); dirtyDescendantsFilter(); dirtyFilter(); } - virtual void clearChildren() + virtual void clearChildren() override { // We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); }); @@ -314,7 +320,7 @@ public: child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); } child_list_t::size_type getChildrenCount() const { return mChildren.size(); } - void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) + void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) override { mPassedFilter = passed; mLastFilterGeneration = filter_generation; @@ -323,20 +329,20 @@ public: mMarkedDirtyGeneration = -1; } - void setPassedFolderFilter(bool passed, S32 filter_generation) + void setPassedFolderFilter(bool passed, S32 filter_generation) override { mPassedFolderFilter = passed; mLastFolderFilterGeneration = filter_generation; } - virtual bool potentiallyVisible() + virtual bool potentiallyVisible() override { return passedFilter() // we've passed the filter || (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet || descendantsPassedFilter(); } - virtual bool passedFilter(S32 filter_generation = -1) + virtual bool passedFilter(S32 filter_generation = -1) override { if (filter_generation < 0) { @@ -347,7 +353,7 @@ public: return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation)); } - virtual bool descendantsPassedFilter(S32 filter_generation = -1) + virtual bool descendantsPassedFilter(S32 filter_generation = -1) override { if (filter_generation < 0) { @@ -356,10 +362,10 @@ public: return mMostFilteredDescendantGeneration >= filter_generation; } - protected: - virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } - virtual bool hasParent() { return mParent != NULL; } + virtual void setParent(LLFolderViewModelItem* parent) override final { mParent = parent; } + virtual const LLFolderViewModelItem* getParent() override { return mParent; }; + virtual bool hasParent() override { return mParent != NULL; } S32 mSortVersion; bool mPassedFilter; @@ -376,7 +382,7 @@ protected: LLFolderViewModelItem* mParent; LLFolderViewModelInterface& mRootViewModel; - void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} + void setFolderViewItem(LLFolderViewItem* folder_view_item) override { mFolderViewItem = folder_view_item;} LLFolderViewItem* mFolderViewItem; }; @@ -390,15 +396,15 @@ public: mFolderView(NULL) {} - virtual void requestSortAll() + virtual void requestSortAll() override { // sort everything mTargetSortVersion++; } - virtual std::string getStatusText(bool is_empty_folder = false); - virtual void filter(); + virtual std::string getStatusText(bool is_empty_folder = false) override; + virtual void filter() override; - void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} + void setFolderView(LLFolderView* folder_view) override { mFolderView = folder_view;} protected: bool needsSort(class LLFolderViewModelItem* item); @@ -426,16 +432,16 @@ public: virtual SortType& getSorter() { return *mSorter; } virtual const SortType& getSorter() const { return *mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter.reset(new SortType(sorter)); requestSortAll(); } + virtual void setSorter(const SortType& sorter) { mSorter = std::make_unique<SortType>(sorter); requestSortAll(); } - virtual FilterType& getFilter() { return *mFilter; } - virtual const FilterType& getFilter() const { return *mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); } + virtual FilterType& getFilter() override { return *mFilter; } + virtual const FilterType& getFilter() const override { return *mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = std::make_unique<FilterType>(filter); } // By default, we assume the content is available. If a network fetch mechanism is implemented for the model, // this method needs to be overloaded and return the relevant fetch status. - virtual bool contentsReady() { return true; } - virtual bool isFolderComplete(LLFolderViewFolder* folder) { return true; } + virtual bool contentsReady() override { return true; } + virtual bool isFolderComplete(LLFolderViewFolder* folder) override { return true; } struct ViewModelCompare { @@ -456,7 +462,7 @@ public: const SortType& mSorter; }; - void sort(LLFolderViewFolder* folder) + void sort(LLFolderViewFolder* folder) override { if (needsSort(folder->getViewModelItem())) { diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index da5570d922..953963b683 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -31,8 +31,6 @@ #include <string> #include <map> -#include <boost/function.hpp> - #include "llsd.h" #include "llsingleton.h" diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 7bf43c22c1..2bea8fb4ed 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -170,7 +170,7 @@ std::string LLKeywords::getAttribute(std::string_view key) return (it != mAttributes.end()) ? it->second : ""; } -LLUIColor LLKeywords::getColorGroup(std::string_view key_in) +LLUIColor LLKeywords::getColorGroup(std::string_view key_in) const { std::string color_group = "ScriptText"; if (key_in == "functions") diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 328561c92a..5892238593 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -111,8 +111,8 @@ public: ~LLKeywords(); void clearLoaded() { mLoaded = false; } - LLUIColor getColorGroup(std::string_view key_in); - bool isLoaded() const { return mLoaded; } + LLUIColor getColorGroup(std::string_view key_in) const; + bool isLoaded() const { return mLoaded; } void findSegments(std::vector<LLTextSegmentPtr> *seg_list, const LLWString& text, diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 1c59938f90..fe0591ce4b 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -36,8 +36,8 @@ #include "lliconctrl.h" #include "boost/foreach.hpp" -static const F32 MIN_FRACTIONAL_SIZE = 0.00001f; -static const F32 MAX_FRACTIONAL_SIZE = 1.f; +static constexpr F32 MIN_FRACTIONAL_SIZE = 0.00001f; +static constexpr F32 MAX_FRACTIONAL_SIZE = 1.f; static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack"); static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel"); diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 8459921c60..9e3536aaff 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -75,9 +75,6 @@ public: /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); /*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true); - - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); - typedef enum e_animate { NO_ANIMATE, @@ -86,7 +83,7 @@ public: void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE); void collapsePanel(LLPanel* panel, bool collapsed = true); - S32 getNumPanels() { return static_cast<S32>(mPanels.size()); } + S32 getNumPanels() const { return static_cast<S32>(mPanels.size()); } void updateLayout(); @@ -190,7 +187,6 @@ public: bool isCollapsed() const { return mCollapsed;} void setOrientation(LLView::EOrientation orientation); - void storeOriginalDim(); void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; } diff --git a/indra/llui/lllazyvalue.h b/indra/llui/lllazyvalue.h index 622e69ce95..fc15ead032 100644 --- a/indra/llui/lllazyvalue.h +++ b/indra/llui/lllazyvalue.h @@ -28,15 +28,16 @@ #ifndef LL_LAZY_VALUE_H #define LL_LAZY_VALUE_H -#include <boost/function.hpp> +#include <functional> +#include <type_traits> // Holds on to a value of type T *or* calls a functor to generate a value of type T template<typename T> class LLLazyValue { public: - typedef typename boost::add_reference<typename boost::add_const<T>::type>::type T_const_ref; - typedef typename boost::function<T_const_ref (void)> function_type; + typedef typename std::add_lvalue_reference<typename std::add_const<T>::type>::type T_const_ref; + typedef typename std::function<T_const_ref (void)> function_type; public: LLLazyValue(const function_type& value) diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 66b274c33f..b534c8d4e8 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -2230,6 +2230,9 @@ void LLLineEditor::clear() { mText.clear(); setCursor(0); + mFontBufferPreSelection.reset(); + mFontBufferSelection.reset(); + mFontBufferPostSelection.reset(); } //virtual @@ -2505,9 +2508,24 @@ void LLLineEditor::resetPreedit() if (hasPreeditString()) { const S32 preedit_pos = mPreeditPositions.front(); - mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos); - mText.insert(preedit_pos, mPreeditOverwrittenWString); - setCursor(preedit_pos); + const S32 end = mPreeditPositions.back(); + const S32 len = end - preedit_pos; + const S32 size = mText.length(); + if (preedit_pos < size + && end <= size + && preedit_pos >= 0 + && len > 0) + { + mText.erase(preedit_pos, len); + mText.insert(preedit_pos, mPreeditOverwrittenWString); + setCursor(preedit_pos); + } + else + { + LL_WARNS() << "Index out of bounds. Start: " << preedit_pos + << ", end:" << end + << ", full string length: " << size << LL_ENDL; + } mPreeditWString.clear(); mPreeditOverwrittenWString.clear(); diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 12fe800acb..3f762822ee 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -60,7 +60,7 @@ class LLLineEditor { public: - typedef boost::function<void (LLLineEditor* caller)> keystroke_callback_t; + typedef std::function<void (LLLineEditor* caller)> keystroke_callback_t; struct MaxLength : public LLInitParam::ChoiceBlock<MaxLength> { @@ -259,7 +259,7 @@ public: void setSelectAllonCommit(bool b) { mSelectAllonCommit = b; } void onKeystroke(); - typedef boost::function<void (LLLineEditor* caller, void* user_data)> callback_t; + typedef std::function<void (LLLineEditor* caller, void* user_data)> callback_t; void setKeystrokeCallback(callback_t callback, void* user_data); void setMaxTextLength(S32 max_text_length); @@ -306,8 +306,6 @@ public: S32 calcCursorPos(S32 mouse_x); bool handleSpecialKey(KEY key, MASK mask); bool handleSelectionKey(KEY key, MASK mask); - bool handleControlKey(KEY key, MASK mask); - S32 handleCommitKey(KEY key, MASK mask); void updateTextPadding(); // Draw the background image depending on enabled/focused state. @@ -444,7 +442,7 @@ private: mText = ed->getText(); } - void doRollback( LLLineEditor* ed ) + void doRollback(LLLineEditor* ed) const { ed->mCursorPos = mCursorPos; ed->mScrollHPos = mScrollHPos; @@ -455,7 +453,7 @@ private: ed->mPrevText = mText; } - std::string getText() { return mText; } + std::string getText() const { return mText; } private: std::string mText; diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index a77ae7dae7..3f96b28246 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -65,8 +65,8 @@ public: boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb ); - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleKeyHere(KEY key, MASK mask ); + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleKeyHere(KEY key, MASK mask) override; void hideMenu(); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 69ffa9a94f..6ba31c251e 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -46,6 +46,7 @@ #include "llfocusmgr.h" #include "llcoord.h" #include "llwindow.h" +#include "llemojihelper.h" #include "llcriticaldamp.h" #include "lluictrlfactory.h" @@ -508,7 +509,7 @@ void LLMenuItemGL::draw( void ) // Highlight if needed if( ll::ui::SearchableControl::getHighlighted() ) - color = ll::ui::SearchableControl::getHighlightColor(); + color = ll::ui::SearchableControl::getHighlightFontColor(); // Draw the text on top. if (mBriefItem) @@ -1411,6 +1412,7 @@ void LLMenuItemBranchDownGL::openMenu( void ) } else { + LLEmojiHelper::instance().hideHelper(nullptr, true); if (branch->getTornOff()) { LLFloater * branch_parent = dynamic_cast<LLFloater *>(branch->getParent()); @@ -4402,3 +4404,17 @@ bool LLContextMenu::addChild(LLView* view, S32 tab_group) return addContextChild(view, tab_group); } +void LLContextMenu::deleteAllChildren() +{ + mHoverItem = nullptr; + LLMenuGL::deleteAllChildren(); +} + +void LLContextMenu::removeChild(LLView* ctrl) +{ + if (ctrl == mHoverItem) + { + mHoverItem = nullptr; + } + LLMenuGL::removeChild(ctrl); +} diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 66f84393fe..bca0a731fc 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -37,7 +37,8 @@ #include "llfloater.h" #include "lluistring.h" #include "llview.h" -#include <boost/function.hpp> + +#include <boost/bind.hpp> extern S32 MENU_BAR_HEIGHT; extern S32 MENU_BAR_WIDTH; @@ -439,8 +440,6 @@ protected: public: virtual ~LLMenuGL( void ); - void parseChildXML(LLXMLNodePtr child, LLView* parent); - // LLView Functionality /*virtual*/ bool handleUnicodeCharHere( llwchar uni_char ); /*virtual*/ bool handleHover( S32 x, S32 y, MASK mask ); @@ -731,6 +730,8 @@ public: virtual bool handleRightMouseUp ( S32 x, S32 y, MASK mask ); virtual bool addChild (LLView* view, S32 tab_group = 0); + /*virtual*/ void deleteAllChildren(); + /*virtual*/ void removeChild(LLView* ctrl); LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); } diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index c5c31f7252..225ff607ad 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -28,6 +28,7 @@ #include "llmodaldialog.h" +#include "llemojihelper.h" #include "llfocusmgr.h" #include "v4color.h" #include "v2math.h" @@ -35,6 +36,7 @@ #include "llwindow.h" #include "llkeyboard.h" #include "llmenugl.h" + // static std::list<LLModalDialog*> LLModalDialog::sModalStack; @@ -98,7 +100,7 @@ void LLModalDialog::onOpen(const LLSD& key) { if (mModal) { - // If Modal, Hide the active modal dialog + // If Modal, hide the active modal dialog if (!sModalStack.empty()) { LLModalDialog* front = sModalStack.front(); @@ -155,6 +157,12 @@ void LLModalDialog::setVisible( bool visible ) { if( visible ) { + // Hide all menus currently shown + LLMenuGL::sMenuContainer->hideMenus(); + + // Hide EmojiPicker if it is shown + LLEmojiHelper::instance().hideHelper(nullptr, true); + // This is a modal dialog. It sucks up all mouse and keyboard operations. gFocusMgr.setMouseCapture( this ); @@ -301,7 +309,6 @@ void LLModalDialog::centerOnScreen() centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY]))); } - // static void LLModalDialog::onAppFocusLost() { @@ -333,6 +340,7 @@ void LLModalDialog::onAppFocusGained() } } +// static void LLModalDialog::shutdownModals() { // This method is only for use during app shutdown. ~LLModalDialog() diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index a7f9b8b2d9..f53e22c349 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -390,7 +390,7 @@ LLFloater* LLMultiFloater::getActiveFloater() return (LLFloater*)mTabContainer->getCurrentPanel(); } -S32 LLMultiFloater::getFloaterCount() +S32 LLMultiFloater::getFloaterCount() const { return mTabContainer->getTabCount(); } diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index eb0f917695..e0cd58aa3f 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -66,7 +66,7 @@ public: virtual LLFloater* getActiveFloater(); virtual bool isFloaterFlashing(LLFloater* floaterp); - virtual S32 getFloaterCount(); + virtual S32 getFloaterCount() const; virtual void setFloaterFlashing(LLFloater* floaterp, bool flashing); virtual bool closeAllFloaters(); //Returns false if the floater could not be closed due to pending confirmation dialogs diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index b2bfc8bc84..af255bcc8f 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -117,10 +117,10 @@ public: /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) override; /*virtual*/ void draw() override; - S32 getMaxNumSliders() { return mMaxNumSliders; } - S32 getCurNumSliders() { return static_cast<S32>(mValue.size()); } - F32 getOverlapThreshold() { return mOverlapThreshold; } - bool canAddSliders() { return mValue.size() < mMaxNumSliders; } + S32 getMaxNumSliders() const { return mMaxNumSliders; } + S32 getCurNumSliders() const { return static_cast<S32>(mValue.size()); } + F32 getOverlapThreshold() const { return mOverlapThreshold; } + bool canAddSliders() const { return mValue.size() < mMaxNumSliders; } protected: diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index dec6cb48b9..2c2bc5e4d9 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -124,10 +124,10 @@ public: F32 getMinValue() const { return mMultiSlider->getMinValue(); } F32 getMaxValue() const { return mMultiSlider->getMaxValue(); } - S32 getMaxNumSliders() { return mMultiSlider->getMaxNumSliders(); } - S32 getCurNumSliders() { return mMultiSlider->getCurNumSliders(); } - F32 getOverlapThreshold() { return mMultiSlider->getOverlapThreshold(); } - bool canAddSliders() { return mMultiSlider->canAddSliders(); } + S32 getMaxNumSliders() const { return mMultiSlider->getMaxNumSliders(); } + S32 getCurNumSliders() const { return mMultiSlider->getCurNumSliders(); } + F32 getOverlapThreshold() const { return mMultiSlider->getOverlapThreshold(); } + bool canAddSliders() const { return mMultiSlider->canAddSliders(); } void setLabel(const std::string& label) { if (mLabelBox) mLabelBox->setText(label); } void setLabelColor(const LLUIColor& c) { mTextEnabledColor = c; } @@ -147,7 +147,6 @@ public: static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); - static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); private: void updateText(); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 7405413a3d..0ffe6cff5e 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -457,7 +457,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mTags.push_back(tag.value); } - mForm = LLNotificationFormPtr(new LLNotificationForm(p.name, p.form_ref.form)); + mForm = std::make_shared<LLNotificationForm>(p.name, p.form_ref.form); } LLNotificationVisibilityRule::LLNotificationVisibilityRule(const LLNotificationVisibilityRule::Rule &p) @@ -614,6 +614,13 @@ void LLNotification::cancel() LLSD LLNotification::getResponseTemplate(EResponseTemplateType type) { LLSD response = LLSD::emptyMap(); + + if (!mForm) + { + LL_WARNS("Notifications") << "Null form when getting response template for notification " << getName() << LL_ENDL; + return response; + } + for (S32 element_idx = 0; element_idx < mForm->getNumElements(); ++element_idx) @@ -868,7 +875,7 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele // TODO: something like this so that a missing alert is sensible: //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions); - mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm)); + mForm = std::make_shared<LLNotificationForm>(*mTemplatep->mForm); mForm->append(form_elements); // apply substitution to form labels @@ -1242,16 +1249,33 @@ LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything), mIgnoreAllNotifications(false) { - mListener.reset(new LLNotificationsListener(*this)); + mListener = std::make_unique<LLNotificationsListener>(*this); LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); // touch the instance tracker for notification channels, so that it will still be around in our destructor LLInstanceTracker<LLNotificationChannel, std::string>::instanceCount(); } + +LLNotifications::~LLNotifications() +{ + // Clear explicitly, something in ~LLNotifications() crashes so narrowing down suspects + pHistoryChannel = nullptr; + pExpirationChannel = nullptr; + mGlobalStrings.clear(); + mTemplates.clear(); + mVisibilityRules.clear(); + mUniqueNotifications.clear(); + mListener = nullptr; +} + void LLNotifications::clear() { - mDefaultChannels.clear(); + mDefaultChannels.clear(); + // At this point mTemplates still gets used by lingering notifications + // to do responses (ex: group notice will call forceResponse()), but + // since network should be down and everything save, it's questionable + // whether it should stay that way } // The expiration channel gets all notifications that are cancelled @@ -1463,7 +1487,14 @@ bool LLNotifications::templateExists(std::string_view name) void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option) { - LLNotificationPtr temp_notify(new LLNotification(params)); + LLNotificationPtr temp_notify = std::make_shared<LLNotification>(params); + + if (!temp_notify->getForm()) + { + LL_WARNS("Notifications") << "Cannot force response for notification with null form: " << (std::string)params.name << LL_ENDL; + return; + } + LLSD response = temp_notify->getResponseTemplate(); LLSD selected_item = temp_notify->getForm()->getElement(option); @@ -1622,7 +1653,7 @@ bool LLNotifications::loadTemplates() replaceFormText(notification.form_ref.form, "$ignoretext", notification.form_ref.form_template.ignore_text); } } - mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification)); + mTemplates[notification.name] = std::make_shared<LLNotificationTemplate>(notification); } LL_INFOS("Notifications") << "...done" << LL_ENDL; @@ -1652,7 +1683,7 @@ bool LLNotifications::loadVisibilityRules() for (const LLNotificationVisibilityRule::Rule& rule : params.rules) { - mVisibilityRules.push_back(LLNotificationVisibilityRulePtr(new LLNotificationVisibilityRule(rule))); + mVisibilityRules.push_back(std::make_shared<LLNotificationVisibilityRule>(rule)); } return true; @@ -1695,7 +1726,7 @@ LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& subs // generalized add function that takes a parameter block object for more complex instantiations LLNotificationPtr LLNotifications::add(const LLNotification::Params& p) { - LLNotificationPtr pNotif(new LLNotification(p)); + LLNotificationPtr pNotif = std::make_shared<LLNotification>(p); add(pNotif); return pNotif; } @@ -1803,7 +1834,7 @@ void LLNotifications::update(const LLNotificationPtr pNotif) LLNotificationPtr LLNotifications::find(LLUUID uuid) { - LLNotificationPtr target = LLNotificationPtr(new LLNotification(LLNotification::Params().id(uuid))); + LLNotificationPtr target = std::make_shared<LLNotification>(LLNotification::Params().id(uuid)); LLNotificationSet::iterator it=mItems.find(target); if (it == mItems.end()) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 46286457cf..d56c459560 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -75,6 +75,7 @@ * */ +#include <functional> #include <string> #include <list> #include <vector> @@ -83,8 +84,6 @@ #include <iomanip> #include <sstream> -#include <boost/utility.hpp> -#include <boost/type_traits.hpp> #include <boost/signals2.hpp> #include <boost/range.hpp> #include <boost/intrusive_ptr.hpp> @@ -129,7 +128,7 @@ public: virtual void fromLLSD(const LLSD& params) = 0; }; -typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder; +typedef std::function<void (const LLSD&, const LLSD&)> LLNotificationResponder; typedef std::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr; @@ -247,7 +246,6 @@ public: LLNotificationForm(const LLSD& sd); LLNotificationForm(const std::string& name, const Params& p); - void fromLLSD(const LLSD& sd); LLSD asLLSD() const; S32 getNumElements() { return static_cast<S32>(mFormData.size()); } @@ -266,8 +264,8 @@ public: bool getIgnored(); void setIgnored(bool ignored); - EIgnoreType getIgnoreType() { return mIgnore; } - std::string getIgnoreMessage() { return mIgnoreMsg; } + EIgnoreType getIgnoreType()const { return mIgnore; } + std::string getIgnoreMessage() const { return mIgnoreMsg; } private: LLSD mFormData; @@ -304,7 +302,6 @@ typedef std::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRu * shared pointer. */ class LLNotification : - boost::noncopyable, public std::enable_shared_from_this<LLNotification> { LOG_CLASS(LLNotification); @@ -430,6 +427,10 @@ private: public: LLNotification(const LLSDParamAdapter<Params>& p); + // Non-copyable + LLNotification(const LLNotification&) = delete; + LLNotification& operator=(const LLNotification&) = delete; + void setResponseFunctor(std::string const &responseFunctorName); void setResponseFunctor(const LLNotificationFunctorRegistry::ResponseFunctor& cb); @@ -667,8 +668,8 @@ namespace LLNotificationFilters template<typename T> struct filterBy { - typedef boost::function<T (LLNotificationPtr)> field_t; - typedef typename boost::remove_reference<T>::type value_t; + typedef std::function<T (LLNotificationPtr)> field_t; + typedef typename std::remove_reference<T>::type value_t; filterBy(field_t field, value_t value, EComparison comparison = EQUAL) : mField(field), @@ -713,7 +714,7 @@ namespace LLNotificationComparators }; }; -typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter; +typedef std::function<bool (LLNotificationPtr)> LLNotificationFilter; typedef std::set<LLNotificationPtr, LLNotificationComparators::orderByUUID> LLNotificationSet; typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap; @@ -818,10 +819,9 @@ typedef boost::intrusive_ptr<LLNotificationChannel> LLNotificationChannelPtr; // manages a list of notifications // Note that if this is ever copied around, we might find ourselves with multiple copies // of a queue with notifications being added to different nonequivalent copies. So we -// make it inherit from boost::noncopyable, and then create a map of LLPointer to manage it. +// delete the copy operator and constructor, and then create a map of LLPointer to manage it. // class LLNotificationChannel : - boost::noncopyable, public LLNotificationChannelBase, public LLInstanceTracker<LLNotificationChannel, std::string> { @@ -844,6 +844,10 @@ public: virtual ~LLNotificationChannel(); typedef LLNotificationSet::iterator Iterator; + // Non-copyable + LLNotificationChannel(const LLNotificationChannel&) = delete; + LLNotificationChannel& operator=(const LLNotificationChannel&) = delete; + std::string getName() const { return mName; } typedef std::vector<std::string>::const_iterator parents_iter; boost::iterator_range<parents_iter> getParents() const @@ -855,7 +859,7 @@ public: S32 size() const; size_t size(); - typedef boost::function<void(LLNotificationPtr)> NotificationProcess; + typedef std::function<void(LLNotificationPtr)> NotificationProcess; void forEachNotification(NotificationProcess process); std::string summarize(); @@ -887,7 +891,7 @@ class LLNotifications : { LLSINGLETON(LLNotifications); LOG_CLASS(LLNotifications); - virtual ~LLNotifications() {} + virtual ~LLNotifications(); public: @@ -971,8 +975,6 @@ private: /*virtual*/ void initSingleton() override; /*virtual*/ void cleanupSingleton() override; - void loadPersistentNotifications(); - bool expirationFilter(LLNotificationPtr pNotification); bool expirationHandler(const LLSD& payload); bool uniqueFilter(LLNotificationPtr pNotification); diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 9c1fc27c51..d07d42bdba 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -266,7 +266,7 @@ void LLNotificationsListener::forward(const LLSD& params) entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first); if (! entry->second) { - entry->second.reset(new Forwarder(mNotifications, channel)); + entry->second = std::make_shared<Forwarder>(mNotifications, channel); } // Now, whether this Forwarder is brand-new or not, update it with the new // request info. diff --git a/indra/llui/llnotificationsutil.cpp b/indra/llui/llnotificationsutil.cpp index c1cad431c5..6b570d043f 100644 --- a/indra/llui/llnotificationsutil.cpp +++ b/indra/llui/llnotificationsutil.cpp @@ -71,7 +71,7 @@ LLNotificationPtr LLNotificationsUtil::add(const std::string& name, LLNotificationPtr LLNotificationsUtil::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, - boost::function<void (const LLSD&, const LLSD&)> functor) + std::function<void (const LLSD&, const LLSD&)> functor) { LLNotification::Params::Functor functor_p; functor_p.function = functor; diff --git a/indra/llui/llnotificationsutil.h b/indra/llui/llnotificationsutil.h index f21d93a50e..73e64e47ba 100644 --- a/indra/llui/llnotificationsutil.h +++ b/indra/llui/llnotificationsutil.h @@ -32,7 +32,7 @@ #include "llnotificationptr.h" #include "lluuid.h" -#include <boost/function.hpp> +#include <functional> class LLSD; @@ -55,7 +55,7 @@ namespace LLNotificationsUtil LLNotificationPtr add(const std::string& name, const LLSD& substitutions, const LLSD& payload, - boost::function<void (const LLSD&, const LLSD&)> functor); + std::function<void (const LLSD&, const LLSD&)> functor); S32 getSelectedOption(const LLSD& notification, const LLSD& response); diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index db314cae0f..2100b23783 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -662,12 +662,12 @@ bool LLPanel::childHasFocus(std::string_view id) // Prefer getChild<LLUICtrl>("foo")->setCommitCallback(boost:bind(...)), // which takes a generic slot. Or use mCommitCallbackRegistrar.add() with // a named callback and reference it in XML. -void LLPanel::childSetCommitCallback(std::string_view id, boost::function<void (LLUICtrl*,void*)> cb, void* data) +void LLPanel::childSetCommitCallback(std::string_view id, std::function<void (LLUICtrl*,void*)> cb, void* data) { LLUICtrl* child = findChild<LLUICtrl>(id); if (child) { - child->setCommitCallback(boost::bind(cb, child, data)); + child->setCommitCallback(std::bind(cb, child, data)); } } @@ -759,12 +759,12 @@ void LLPanel::childSetAction(std::string_view id, const commit_signal_t::slot_ty } } -void LLPanel::childSetAction(std::string_view id, boost::function<void(void*)> function, void* value) +void LLPanel::childSetAction(std::string_view id, std::function<void(void*)> function, void* value) { LLButton* button = findChild<LLButton>(id); if (button) { - button->setClickedCallback(boost::bind(function, value)); + button->setClickedCallback(std::bind(function, value)); } } diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index f085c123c1..fe861dc719 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -191,7 +191,7 @@ public: // Prefer getChild<LLUICtrl>("foo")->setCommitCallback(boost:bind(...)), // which takes a generic slot. Or use mCommitCallbackRegistrar.add() with // a named callback and reference it in XML. - void childSetCommitCallback(std::string_view id, boost::function<void (LLUICtrl*,void*)> cb, void* data); + void childSetCommitCallback(std::string_view id, std::function<void (LLUICtrl*,void*)> cb, void* data); void childSetColor(std::string_view id, const LLUIColor& color); LLCtrlSelectionInterface* childGetSelectionInterface(std::string_view id) const; @@ -208,7 +208,7 @@ public: bool childSetLabelArg(std::string_view id, const std::string& key, const LLStringExplicit& text); // LLButton - void childSetAction(std::string_view id, boost::function<void(void*)> function, void* value); + void childSetAction(std::string_view id, std::function<void(void*)> function, void* value); void childSetAction(std::string_view id, const commit_signal_t::slot_type& function); static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); @@ -262,7 +262,7 @@ extern template class LLPanel* LLView::getChild<class LLPanel>( std::string_view name, bool recurse) const; #endif -typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc; +typedef std::function<LLPanel* (void)> LLPanelClassCreatorFunc; // local static instance for registering a particular panel class diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h index 0d5d32cf21..7245bbf1cf 100644 --- a/indra/llui/llprogressbar.h +++ b/indra/llui/llprogressbar.h @@ -48,9 +48,9 @@ public: LLProgressBar(const Params&); virtual ~LLProgressBar(); - void setValue(const LLSD& value); + void setValue(const LLSD& value) override; - /*virtual*/ void draw(); + void draw() override; private: F32 mPercentDone; diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 4b0f435834..d95536c360 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -61,8 +61,8 @@ public: void setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; } void setEnableSnapping(bool enable) { mSnappingEnabled = enable; } void setAllowDoubleClickSnapping(bool allow) { mAllowDoubleClickSnapping = allow; } - bool canResize() { return getEnabled() && mMaxSize > mMinSize; } - void setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;} + bool canResize() const { return getEnabled() && mMaxSize > mMinSize; } + void setResizeListener(std::function<void(void*)> listener) { mResizeListener = listener; } void setImagePanel(LLPanel * panelp); LLPanel * getImagePanel() const; @@ -78,7 +78,7 @@ private: bool mSnappingEnabled, mAllowDoubleClickSnapping; LLView* mResizingView; - boost::function<void(void*)> mResizeListener; + std::function<void(void*)> mResizeListener; LLPointer<LLUIImage> mDragHandleImage; LLPanel * mImagePanel; }; diff --git a/indra/llui/llresizehandle.h b/indra/llui/llresizehandle.h index 9cc4123544..caec33405c 100644 --- a/indra/llui/llresizehandle.h +++ b/indra/llui/llresizehandle.h @@ -50,10 +50,10 @@ protected: LLResizeHandle(const LLResizeHandle::Params&); friend class LLUICtrlFactory; public: - virtual void draw(); - virtual bool handleHover(S32 x, S32 y, MASK mask); - virtual bool handleMouseDown(S32 x, S32 y, MASK mask); - virtual bool handleMouseUp(S32 x, S32 y, MASK mask); + void draw() override; + bool handleHover(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; void setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; } @@ -71,8 +71,8 @@ private: const ECorner mCorner; }; -const S32 RESIZE_HANDLE_HEIGHT = 11; -const S32 RESIZE_HANDLE_WIDTH = 11; +constexpr S32 RESIZE_HANDLE_HEIGHT = 11; +constexpr S32 RESIZE_HANDLE_WIDTH = 11; #endif // LL_RESIZEHANDLE_H diff --git a/indra/llui/llrngwriter.h b/indra/llui/llrngwriter.h index 33ec049a1a..2c39472607 100644 --- a/indra/llui/llrngwriter.h +++ b/indra/llui/llrngwriter.h @@ -37,7 +37,7 @@ public: void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); void addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block); - /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } + std::string getCurrentElementName() override { return LLStringUtil::null; } LLRNGWriter(); diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h index 9607355a9d..c49d2b534a 100644 --- a/indra/llui/llscrollbar.h +++ b/indra/llui/llscrollbar.h @@ -40,7 +40,7 @@ class LLScrollbar { public: - typedef boost::function<void (S32, LLScrollbar*)> callback_t; + typedef std::function<void (S32, LLScrollbar*)> callback_t; struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index a3108d77e8..bdf88768c3 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -98,6 +98,7 @@ const LLSD LLScrollListCell::getAltValue() const LLScrollListIcon::LLScrollListIcon(const LLScrollListCell::Params& p) : LLScrollListCell(p), mIcon(LLUI::getUIImage(p.value().asString())), + mIconSize(0), mColor(p.color), mAlignment(p.font_halign) {} @@ -140,20 +141,32 @@ void LLScrollListIcon::setValue(const LLSD& value) } } - void LLScrollListIcon::setColor(const LLColor4& color) { mColor = color; } +void LLScrollListIcon::setIconSize(S32 size) +{ + mIconSize = size; +} + S32 LLScrollListIcon::getWidth() const { // if no specified fix width, use width of icon - if (LLScrollListCell::getWidth() == 0 && mIcon.notNull()) + if (LLScrollListCell::getWidth() != 0) + { + return LLScrollListCell::getWidth(); + } + if (mIconSize != 0) + { + return mIconSize; + } + if (mIcon.notNull()) { return mIcon->getWidth(); } - return LLScrollListCell::getWidth(); + return 0; } @@ -161,16 +174,23 @@ void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_col { if (mIcon) { + S32 draw_width = mIcon->getWidth(); + S32 draw_height = mIcon->getHeight(); + if (mIconSize != 0) + { + draw_width = mIconSize; + draw_height = mIconSize; + } // else will draw full icon even if cell is smaller switch(mAlignment) { case LLFontGL::LEFT: - mIcon->draw(0, 0, mColor); + mIcon->draw(0, 0, draw_width, draw_height, mColor); break; case LLFontGL::RIGHT: - mIcon->draw(getWidth() - mIcon->getWidth(), 0, mColor); + mIcon->draw(getWidth() - draw_width, 0, draw_width, draw_height, mColor); break; case LLFontGL::HCENTER: - mIcon->draw((getWidth() - mIcon->getWidth()) / 2, 0, mColor); + mIcon->draw((getWidth() - draw_width) / 2, 0, draw_width, draw_height, mColor); break; default: break; diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index e7ff5c8424..f0a0f216b4 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -105,7 +105,7 @@ public: 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 const std::string& getToolTip() const { return mToolTip; } virtual void setToolTip(const std::string &str) { mToolTip = str; } virtual bool getVisible() const { return true; } virtual void setWidth(S32 width) { mWidth = width; } @@ -197,11 +197,13 @@ public: /*virtual*/ const LLSD getValue() const; /*virtual*/ void setColor(const LLColor4&); /*virtual*/ void setValue(const LLSD& value); + void setIconSize(S32 size); private: LLPointer<LLUIImage> mIcon; LLColor4 mColor; LLFontGL::HAlign mAlignment; + S32 mIconSize; }; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 93bd3c6bed..b459c67dad 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -190,19 +190,19 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mColumnsDirty(false), mMaxItemCount(INT_MAX), mBorderThickness( 2 ), - mOnDoubleClickCallback( NULL ), - mOnMaximumSelectCallback( NULL ), - mOnSortChangedCallback( NULL ), + mOnDoubleClickCallback(nullptr), + mOnMaximumSelectCallback(nullptr), + mOnSortChangedCallback(nullptr), mHighlightedItem(-1), - mBorder(NULL), - mSortCallback(NULL), + mBorder(nullptr), + mSortCallback(nullptr), mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), mTotalColumnPadding(0), mSorted(false), mDirty(false), mOriginalSelection(-1), - mLastSelected(NULL), + mLastSelected(nullptr), mHeadingHeight(p.heading_height), mAllowMultipleSelection(p.multi_select), mDisplayColumnHeaders(p.draw_heading), @@ -222,7 +222,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mRowPadding(p.row_padding), mAlternateSort(false), mContextMenuType(MENU_NONE), - mIsFriendSignal(NULL) + mIsFriendSignal(nullptr) { mItemListRect.setOriginAndSize( mBorderThickness, @@ -1007,7 +1007,7 @@ void LLScrollListCtrl::deleteItems(const LLSD& sd) void LLScrollListCtrl::deleteSelectedItems() { item_list::iterator iter; - for (iter = mItemList.begin(); iter < mItemList.end(); ) + for (iter = mItemList.begin(); iter != mItemList.end(); ) { LLScrollListItem* itemp = *iter; if (itemp->getSelected()) @@ -3394,7 +3394,7 @@ bool LLScrollListCtrl::highlightMatchingItems(const std::string& filter_str) bool res = false; - setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red)); + setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightBgColor", LLColor4::red4)); std::string filter_str_lc(filter_str); LLStringUtil::toLower(filter_str_lc); diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index c24784338a..d3735c5052 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -77,7 +77,7 @@ public: }; // *TODO: Add callbacks to Params - typedef boost::function<void (void)> callback_t; + typedef std::function<void (void)> callback_t; template<typename T> struct maximum { @@ -165,7 +165,6 @@ public: void deleteAllItems() { clearRows(); } // Sets an array of column descriptors - void setColumnHeadings(const LLSD& headings); void sortByColumnIndex(U32 column, bool ascending); // LLCtrlListInterface functions @@ -242,7 +241,7 @@ public: void setMaximumSelectCallback( callback_t cb) { mOnMaximumSelectCallback = cb; } void setSortChangedCallback( callback_t cb) { mOnSortChangedCallback = cb; } // Convenience function; *TODO: replace with setter above + boost::bind() in calling code - void setDoubleClickCallback( boost::function<void (void* userdata)> cb, void* userdata) { mOnDoubleClickCallback = boost::bind(cb, userdata); } + void setDoubleClickCallback( std::function<void (void* userdata)> cb, void* userdata) { mOnDoubleClickCallback = std::bind(cb, userdata); } void swapWithNext(S32 index); void swapWithPrevious(S32 index); @@ -318,7 +317,7 @@ public: void setAllowKeyboardMovement(bool b) { mAllowKeyboardMovement = b; } void setMaxSelectable(U32 max_selected) { mMaxSelectable = max_selected; } - S32 getMaxSelectable() { return mMaxSelectable; } + S32 getMaxSelectable() const { return mMaxSelectable; } virtual S32 getScrollPos() const; @@ -334,7 +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; } + ContextMenuType getContextMenuType() const { return mContextMenuType; } // Overridden from LLView /*virtual*/ void draw(); @@ -362,7 +361,6 @@ public: virtual void fitContents(S32 max_width, S32 max_height); virtual LLRect getRequiredRect(); - static bool rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row); LLRect getItemListRect() { return mItemListRect; } @@ -384,7 +382,6 @@ public: * then display all items. */ void setPageLines(S32 page_lines ); - void setCollapseEmptyColumns(bool collapse); LLScrollListItem* hitItem(S32 x,S32 y); virtual void scrollToShowSelected(); @@ -401,7 +398,7 @@ public: void setNumDynamicColumns(S32 num) { mNumDynamicWidthColumns = num; } void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width); - S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; } + S32 getTotalStaticColumnWidth() const { return mTotalStaticColumnWidth; } std::string getSortColumnName(); bool getSortAscending() { return mSortColumns.empty() ? true : mSortColumns.back().second; } diff --git a/indra/llui/llsearchablecontrol.h b/indra/llui/llsearchablecontrol.h index 119852b763..bae85fe9a5 100644 --- a/indra/llui/llsearchablecontrol.h +++ b/indra/llui/llsearchablecontrol.h @@ -43,9 +43,15 @@ namespace ll virtual ~SearchableControl() { } - const LLColor4& getHighlightColor( ) const + const LLColor4& getHighlightBgColor( ) const { - static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red); + static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightBgColor", LLColor4::red4); + return highlight_color.get(); + } + + const LLColor4& getHighlightFontColor() const + { + static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightFontColor", LLColor4::red4); return highlight_color.get(); } diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp index a0c1e9d0c0..244faf8fe9 100644 --- a/indra/llui/llsearcheditor.cpp +++ b/indra/llui/llsearcheditor.cpp @@ -106,12 +106,12 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p) LLSearchEditor::~LLSearchEditor() { - mKeystrokeCallback = NULL; - mTextChangedCallback = NULL; + mKeystrokeCallback = nullptr; + mTextChangedCallback = nullptr; setCommitOnFocusLost(false); - mSearchButton = NULL; - mClearButton = NULL; + mSearchButton = nullptr; + mClearButton = nullptr; mSearchEditor->deleteAllChildren(); deleteAllChildren(); } diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h index 311377a61f..23ce8fd955 100644 --- a/indra/llui/llsliderctrl.h +++ b/indra/llui/llsliderctrl.h @@ -132,7 +132,6 @@ public: static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); - static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); protected: virtual std::string _getSearchText() const diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h index 58b38dc630..4ba8c97c63 100644 --- a/indra/llui/llspinctrl.h +++ b/indra/llui/llspinctrl.h @@ -94,7 +94,6 @@ public: void onEditorCommit(const LLSD& data); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); static void onEditorLostFocus(LLFocusableElement* caller, void *userdata); - static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); void onUpBtn(const LLSD& data); void onDownBtn(const LLSD& data); diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h index c36a138566..bbbf0b3a19 100644 --- a/indra/llui/llstatbar.h +++ b/indra/llui/llstatbar.h @@ -67,7 +67,7 @@ public: void setStat(const std::string& stat_name); void setRange(F32 bar_min, F32 bar_max); - void getRange(F32& bar_min, F32& bar_max) { bar_min = mTargetMinBar; bar_max = mTargetMaxBar; } + void getRange(F32& bar_min, F32& bar_max) const { bar_min = mTargetMinBar; bar_max = mTargetMaxBar; } /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. diff --git a/indra/llui/llstatgraph.cpp b/indra/llui/llstatgraph.cpp index d97051247e..0af717d447 100644 --- a/indra/llui/llstatgraph.cpp +++ b/indra/llui/llstatgraph.cpp @@ -36,7 +36,6 @@ #include "llglheaders.h" #include "lltracerecording.h" #include "lltracethreadrecorder.h" -//#include "llviewercontrol.h" /////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/llui/llstatgraph.h b/indra/llui/llstatgraph.h index c254821870..6d9e3d1064 100644 --- a/indra/llui/llstatgraph.h +++ b/indra/llui/llstatgraph.h @@ -99,9 +99,7 @@ public: void setMin(const F32 min); void setMax(const F32 max); - virtual void draw(); - - /*virtual*/ void setValue(const LLSD& value); + void draw() override; private: LLTrace::StatType<LLTrace::CountAccumulator>* mNewStatFloatp; @@ -133,9 +131,6 @@ private: }; typedef std::vector<Threshold> threshold_vec_t; threshold_vec_t mThresholds; - //S32 mNumThresholds; - //F32 mThresholds[4]; - //LLColor4 mThresholdColors[4]; }; #endif // LL_LLSTATGRAPH_H diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index b5187f886d..a396773057 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -29,7 +29,6 @@ #include "llstatbar.h" #include "llcontainerview.h" -#include <vector> class LLStatBar; diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp index 4714665e8b..7a0e620d61 100644 --- a/indra/llui/llstyle.cpp +++ b/indra/llui/llstyle.cpp @@ -38,11 +38,13 @@ LLStyle::Params::Params() color("color", LLColor4::black), readonly_color("readonly_color", LLColor4::black), selected_color("selected_color", LLColor4::black), + highlight_bg_color("highlight_bg_color", LLColor4::green), alpha("alpha", 1.f), font("font", LLStyle::getDefaultFont()), image("image"), link_href("href"), - is_link("is_link") + is_link("is_link"), + draw_highlight_bg("draw_highlight_bg", false) {} @@ -51,12 +53,14 @@ LLStyle::LLStyle(const LLStyle::Params& p) mColor(p.color), mReadOnlyColor(p.readonly_color), mSelectedColor(p.selected_color), + mHighlightBgColor(p.highlight_bg_color), mFont(p.font()), mLink(p.link_href), mIsLink(p.is_link.isProvided() ? p.is_link : !p.link_href().empty()), mDropShadow(p.drop_shadow), mImagep(p.image()), - mAlpha(p.alpha) + mAlpha(p.alpha), + mDrawHighlightBg(p.draw_highlight_bg) {} void LLStyle::setFont(const LLFontGL* font) diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h index 0c78fe5a9f..71c3f88109 100644 --- a/indra/llui/llstyle.h +++ b/indra/llui/llstyle.h @@ -43,15 +43,25 @@ public: Optional<LLFontGL::ShadowType> drop_shadow; Optional<LLUIColor> color, readonly_color, - selected_color; + selected_color, + highlight_bg_color; Optional<F32> alpha; Optional<const LLFontGL*> font; Optional<LLUIImage*> image; Optional<std::string> link_href; Optional<bool> is_link; + Optional<bool> draw_highlight_bg; Params(); }; LLStyle(const Params& p = Params()); + + enum EUnderlineLink + { + UNDERLINE_ALWAYS = 0, + UNDERLINE_ON_HOVER, + UNDERLINE_NEVER + }; + public: const LLUIColor& getColor() const { return mColor; } void setColor(const LLUIColor &color) { mColor = color; } @@ -84,6 +94,9 @@ public: bool isImage() const { return mImagep.notNull(); } + bool getDrawHighlightBg() const { return mDrawHighlightBg; } + const LLUIColor& getHighlightBgColor() const { return mHighlightBgColor; } + bool operator==(const LLStyle &rhs) const { return @@ -91,11 +104,13 @@ public: && mColor == rhs.mColor && mReadOnlyColor == rhs.mReadOnlyColor && mSelectedColor == rhs.mSelectedColor + && mHighlightBgColor == rhs.mHighlightBgColor && mFont == rhs.mFont && mLink == rhs.mLink && mImagep == rhs.mImagep && mDropShadow == rhs.mDropShadow - && mAlpha == rhs.mAlpha; + && mAlpha == rhs.mAlpha + && mDrawHighlightBg == rhs.mDrawHighlightBg; } bool operator!=(const LLStyle& rhs) const { return !(*this == rhs); } @@ -112,11 +127,13 @@ private: LLUIColor mColor; LLUIColor mReadOnlyColor; LLUIColor mSelectedColor; + LLUIColor mHighlightBgColor; const LLFontGL* mFont; LLPointer<LLUIImage> mImagep; F32 mAlpha; bool mVisible; bool mIsLink; + bool mDrawHighlightBg; }; typedef LLPointer<LLStyle> LLStyleSP; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 595ab0bd2b..5e0985c79c 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1370,17 +1370,17 @@ LLPanel* LLTabContainer::getCurrentPanel() return NULL; } -S32 LLTabContainer::getCurrentPanelIndex() +S32 LLTabContainer::getCurrentPanelIndex() const { return mCurrentTabIdx; } -S32 LLTabContainer::getTabCount() +S32 LLTabContainer::getTabCount() const { return static_cast<S32>(mTabList.size()); } -LLPanel* LLTabContainer::getPanelByIndex(S32 index) +LLPanel* LLTabContainer::getPanelByIndex(S32 index) const { if (index >= 0 && index < (S32)mTabList.size()) { @@ -1389,7 +1389,7 @@ LLPanel* LLTabContainer::getPanelByIndex(S32 index) return NULL; } -S32 LLTabContainer::getIndexForPanel(LLPanel* panel) +S32 LLTabContainer::getIndexForPanel(LLPanel* panel) const { for (S32 index = 0; index < (S32)mTabList.size(); index++) { @@ -1401,7 +1401,7 @@ S32 LLTabContainer::getIndexForPanel(LLPanel* panel) return -1; } -S32 LLTabContainer::getPanelIndexByTitle(std::string_view title) +S32 LLTabContainer::getPanelIndexByTitle(std::string_view title) const { for (S32 index = 0 ; index < (S32)mTabList.size(); index++) { diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 40f272ffa8..4ac7e73d25 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -182,15 +182,15 @@ public: void removeTabPanel( LLPanel* child ); void lockTabs(S32 num_tabs = 0); void unlockTabs(); - S32 getNumLockedTabs() { return mLockedTabCount; } + S32 getNumLockedTabs() const { return mLockedTabCount; } void enableTabButton(S32 which, bool enable); void deleteAllTabs(); LLPanel* getCurrentPanel(); - S32 getCurrentPanelIndex(); - S32 getTabCount(); - LLPanel* getPanelByIndex(S32 index); - S32 getIndexForPanel(LLPanel* panel); - S32 getPanelIndexByTitle(std::string_view title); + S32 getCurrentPanelIndex() const; + S32 getTabCount() const; + LLPanel* getPanelByIndex(S32 index) const; + S32 getIndexForPanel(LLPanel* panel) const; + S32 getPanelIndexByTitle(std::string_view title) const; LLPanel* getPanelByName(std::string_view name); S32 getTotalTabWidth() const; void setCurrentTabName(const std::string& name); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index fae22fd248..2079ff17fc 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -185,6 +185,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mURLClickSignal(NULL), mIsFriendSignal(NULL), mIsObjectBlockedSignal(NULL), + mIsObjectReachableSignal(NULL), mMaxTextByteLength( p.max_text_length ), mFont(p.font), mFontShadow(p.font_shadow), @@ -290,6 +291,7 @@ LLTextBase::~LLTextBase() delete mURLClickSignal; delete mIsFriendSignal; delete mIsObjectBlockedSignal; + delete mIsObjectReachableSignal; } void LLTextBase::initFromParams(const LLTextBase::Params& p) @@ -460,6 +462,62 @@ std::vector<LLRect> LLTextBase::getSelectionRects() return selection_rects; } +std::vector<std::pair<LLRect, LLUIColor>> LLTextBase::getHighlightedBgRects() +{ + std::vector<std::pair<LLRect, LLUIColor>> highlight_rects; + + LLRect content_display_rect = getVisibleDocumentRect(); + + // binary search for line that starts before top of visible buffer + line_list_t::const_iterator line_iter = + std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom()); + line_list_t::const_iterator end_iter = + std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top()); + + for (; line_iter != end_iter; ++line_iter) + { + segment_set_t::iterator segment_iter; + S32 segment_offset; + getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset); + + // Use F32 otherwise a string of multiple segments + // will accumulate a large error + F32 left_precise = (F32)line_iter->mRect.mLeft; + F32 right_precise = (F32)line_iter->mRect.mLeft; + + for (; segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0) + { + LLTextSegmentPtr segmentp = *segment_iter; + + S32 segment_line_start = segmentp->getStart() + segment_offset; + S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd); + + if (segment_line_start > segment_line_end) + break; + + F32 segment_width = 0; + S32 segment_height = 0; + + S32 num_chars = segment_line_end - segment_line_start; + segmentp->getDimensionsF32(segment_offset, num_chars, segment_width, segment_height); + right_precise += segment_width; + + if (segmentp->getStyle()->getDrawHighlightBg()) + { + LLRect selection_rect; + selection_rect.mLeft = (S32)left_precise; + selection_rect.mRight = (S32)right_precise; + selection_rect.mBottom = line_iter->mRect.mBottom; + selection_rect.mTop = line_iter->mRect.mTop; + + highlight_rects.push_back(std::pair(selection_rect, segmentp->getStyle()->getHighlightBgColor())); + } + left_precise += segment_width; + } + } + return highlight_rects; +} + // Draws the black box behind the selected text void LLTextBase::drawSelectionBackground() { @@ -529,6 +587,71 @@ void LLTextBase::drawSelectionBackground() } } +void LLTextBase::drawHighlightedBackground() +{ + if (!mLineInfoList.empty()) + { + std::vector<std::pair<LLRect, LLUIColor>> highlight_rects = getHighlightedBgRects(); + + if (highlight_rects.empty()) + return; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLRect content_display_rect = getVisibleDocumentRect(); + + for (std::vector<std::pair<LLRect, LLUIColor>>::iterator rect_it = highlight_rects.begin(); + rect_it != highlight_rects.end(); ++rect_it) + { + LLRect selection_rect = rect_it->first; + const LLColor4& color = rect_it->second; + 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, color); + } + } +} + void LLTextBase::drawCursor() { F32 alpha = getDrawContext().mAlpha; @@ -915,8 +1038,37 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s { LLStyleSP emoji_style; LLEmojiDictionary* ed = LLEmojiDictionary::instanceExists() ? LLEmojiDictionary::getInstance() : NULL; + LLTextSegment* segmentp = nullptr; + segment_vec_t::iterator seg_iter; + if (segments && segments->size() > 0) + { + seg_iter = segments->begin(); + segmentp = *seg_iter; + } for (S32 text_kitty = 0, text_len = static_cast<S32>(wstr.size()); text_kitty < text_len; text_kitty++) { + if (segmentp) + { + if (segmentp->getEnd() <= pos + text_kitty) + { + seg_iter++; + if (seg_iter != segments->end()) + { + segmentp = *seg_iter; + } + else + { + segmentp = nullptr; + } + } + if (segmentp && !segmentp->getPermitsEmoji()) + { + // Some segments, like LLInlineViewSegment do not permit splitting + // and should not be interrupted by emoji segments + continue; + } + } + llwchar code = wstr[text_kitty]; bool isEmoji = ed ? ed->isEmoji(code) : LLStringOps::isEmoji(code); if (isEmoji) @@ -948,6 +1100,14 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length) { + S32 text_length = (S32)getLength(); + if (pos >= text_length || pos < 0) + { + return 0; // nothing to remove + } + // Clamp length to not go past the end of the text + length = std::min(length, text_length - pos); + beforeValueChange(); segment_set_t::iterator seg_iter = getSegIterContaining(pos); while(seg_iter != mSegments.end()) @@ -1317,6 +1477,8 @@ void LLTextBase::reshape(S32 width, S32 height, bool called_from_parent) // up-to-date mVisibleTextRect updateRects(); + // Todo: This might be wrong. updateRects already sets needsReflow conditionaly. + // Reflow is expensive and doing it at any twith can be too much. needsReflow(); } } @@ -1378,7 +1540,7 @@ void LLTextBase::draw() // Draw highlighted if needed if( ll::ui::SearchableControl::getHighlighted() ) { - const LLColor4& bg_color = ll::ui::SearchableControl::getHighlightColor(); + const LLColor4& bg_color = ll::ui::SearchableControl::getHighlightBgColor(); LLRect bg_rect = mVisibleTextRect; if( mScroller ) bg_rect.intersectWith( text_rect ); @@ -1399,6 +1561,7 @@ void LLTextBase::draw() drawChild(mDocumentView); } + drawHighlightedBackground(); drawSelectionBackground(); drawText(); drawCursor(); @@ -2105,7 +2268,9 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_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.ZoomInObject", boost::bind(&LLUrlAction::zoomInObject, url)); registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); + registrar.add("Url.ShowParcelOnMap", boost::bind(&LLUrlAction::showParcelOnMap, url)); registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url)); registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url)); @@ -2149,6 +2314,15 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) unblockButton->setVisible(is_blocked); } } + + if (mIsObjectReachableSignal) + { + bool is_reachable = *(*mIsObjectReachableSignal)(LLUUID(LLUrlAction::getObjectId(url))); + if (LLView* zoom_btn = menu->getChild<LLView>("zoom_in")) + { + zoom_btn->setEnabled(is_reachable); + } + } menu->show(x, y); LLMenuGL::showPopup(this, menu, x, y); } @@ -2200,20 +2374,20 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name) } -void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params) +void LLTextBase::appendTextImpl(const std::string& new_text, const LLStyle::Params& input_params, bool force_slurl) { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; LLStyle::Params style_params(getStyleParams()); style_params.overwriteFrom(input_params); S32 part = (S32)LLTextParser::WHOLE; - if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358). + if ((mParseHTML || force_slurl) && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358). { 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() || mAlwaysShowIcons)) + boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3), isContentTrusted() || mAlwaysShowIcons, force_slurl)) { start = match.getStart(); end = match.getEnd()+1; @@ -2245,7 +2419,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para } // output the styled Url - appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.underlineOnHoverOnly()); + appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.getUnderline()); bool tooltip_required = !match.getTooltip().empty(); // set the tooltip for the Url label @@ -2260,7 +2434,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para { link_params.color = LLColor4::grey; link_params.readonly_color = LLColor4::grey; - appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly()); + appendAndHighlightTextImpl(label, part, link_params, match.getUnderline()); // set the tooltip for the query part of url if (tooltip_required) @@ -2428,7 +2602,7 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s insertStringNoUndo(getLength(), widget_wide_text, &segments); } -void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only) +void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, e_underline underline_link) { // Save old state S32 selection_start = mSelectionStart; @@ -2458,7 +2632,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig S32 cur_length = getLength(); LLStyleConstSP sp(new LLStyle(highlight_params)); LLTextSegmentPtr segmentp; - if (underline_on_hover_only || mSkipLinkUnderline) + if ((underline_link == e_underline::UNDERLINE_ON_HOVER) || mSkipLinkUnderline) { highlight_params.font.style("NORMAL"); LLStyleConstSP normal_sp(new LLStyle(highlight_params)); @@ -2482,7 +2656,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig S32 segment_start = old_length; S32 segment_end = old_length + static_cast<S32>(wide_text.size()); LLStyleConstSP sp(new LLStyle(style_params)); - if (underline_on_hover_only || mSkipLinkUnderline) + if ((underline_link == e_underline::UNDERLINE_ON_HOVER) || mSkipLinkUnderline) { LLStyle::Params normal_style_params(style_params); normal_style_params.font.style("NORMAL"); @@ -2516,7 +2690,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig } } -void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only) +void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, e_underline underline_link) { if (new_text.empty()) { @@ -2531,7 +2705,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig if (pos != start) { std::string str = std::string(new_text,start,pos-start); - appendAndHighlightTextImpl(str, highlight_part, style_params, underline_on_hover_only); + appendAndHighlightTextImpl(str, highlight_part, style_params, underline_link); } appendLineBreakSegment(style_params); start = pos+1; @@ -2539,7 +2713,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig } std::string str = std::string(new_text, start, new_text.length() - start); - appendAndHighlightTextImpl(str, highlight_part, style_params, underline_on_hover_only); + appendAndHighlightTextImpl(str, highlight_part, style_params, underline_link); } @@ -3255,6 +3429,15 @@ boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_bloc return mIsObjectBlockedSignal->connect(cb); } +boost::signals2::connection LLTextBase::setIsObjectReachableCallback(const is_obj_reachable_signal_t::slot_type& cb) +{ + if (!mIsObjectReachableSignal) + { + mIsObjectReachableSignal = new is_obj_reachable_signal_t(); + } + return mIsObjectReachableSignal->connect(cb); +} + // // LLTextSegment // @@ -3336,6 +3519,12 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e mLastGeneration(-1) { mFontHeight = mStyle->getFont()->getLineHeight(); + mCanEdit = !mStyle->getDrawHighlightBg(); + if (!mCanEdit) + { + // Emoji shouldn't split the segment with the mention. + mPermitsEmoji = false; + } LLUIImagePtr image = mStyle->getImage(); if (image.notNull()) @@ -3632,7 +3821,7 @@ bool LLNormalTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& w { height = 0; width = 0; - if (num_chars > 0) + if (num_chars > 0 && (mStart + first_char >= 0)) { height = mFontHeight; const LLWString &text = getWText(); @@ -3856,6 +4045,7 @@ LLInlineViewSegment::LLInlineViewSegment(const Params& p, S32 start, S32 end) mTopPad(p.top_pad), mBottomPad(p.bottom_pad) { + mPermitsEmoji = false; } LLInlineViewSegment::~LLInlineViewSegment() diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 76d4e160af..3ab5e905e3 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -35,6 +35,7 @@ #include "llstyle.h" #include "llkeywords.h" #include "llpanel.h" +#include "llurlmatch.h" #include <string> #include <vector> @@ -60,13 +61,15 @@ class LLTextSegment public: LLTextSegment(S32 start, S32 end) : mStart(start), - mEnd(end) + mEnd(end), + mPermitsEmoji(true) {} virtual ~LLTextSegment(); virtual LLTextSegmentPtr clone(LLTextBase& terget) const { return new LLTextSegment(mStart, mEnd); } static LLStyleSP cloneStyle(LLTextBase& target, const LLStyle* source); bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; + bool getPermitsEmoji() const { return mPermitsEmoji; }; virtual bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const; virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; @@ -124,6 +127,8 @@ public: protected: S32 mStart; S32 mEnd; + + bool mPermitsEmoji; }; class LLNormalTextSegment : public LLTextSegment @@ -139,13 +144,12 @@ public: /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const; /*virtual*/ void updateLayout(const class LLTextBase& editor); /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); - /*virtual*/ bool canEdit() const { return true; } + /*virtual*/ bool canEdit() const { return mCanEdit; } /*virtual*/ const LLUIColor& getColor() const { return mStyle->getColor(); } /*virtual*/ LLStyleConstSP getStyle() const { return mStyle; } /*virtual*/ void setStyle(LLStyleConstSP style) { mStyle = style; } /*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; } /*virtual*/ LLKeywordToken* getToken() const { return mToken; } - /*virtual*/ bool getToolTip( std::string& msg ) const; /*virtual*/ void setToolTip(const std::string& tooltip); /*virtual*/ void dump() const; @@ -162,6 +166,8 @@ protected: virtual const LLWString& getWText() const; virtual const S32 getLength() const; + void setAllowEdit(bool can_edit) { mCanEdit = can_edit; } + protected: class LLTextBase& mEditor; LLStyleConstSP mStyle; @@ -170,6 +176,8 @@ protected: std::string mTooltip; boost::signals2::connection mImageLoadedConnection; + bool mCanEdit { true }; + // font rendering LLFontVertexBuffer mFontBufferPreSelection; LLFontVertexBuffer mFontBufferSelection; @@ -251,6 +259,7 @@ public: /*virtual*/ void updateLayout(const class LLTextBase& editor); /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); /*virtual*/ bool canEdit() const { return false; } + /*virtual*/ bool getPermitsEmoji() const { return false; } /*virtual*/ void unlinkFromDocument(class LLTextBase* editor); /*virtual*/ void linkToDocument(class LLTextBase* editor); @@ -321,6 +330,7 @@ public: typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t; typedef boost::signals2::signal<bool (const LLUUID& blocked_id, const std::string from)> is_blocked_signal_t; + typedef boost::signals2::signal<bool (const LLUUID& obj_id)> is_obj_reachable_signal_t; struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams> { @@ -450,7 +460,7 @@ public: virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style /*virtual*/ const std::string& getText() const override; void setMaxTextLength(S32 length) { mMaxTextByteLength = length; } - S32 getMaxTextLength() { return mMaxTextByteLength; } + S32 getMaxTextLength() const { return mMaxTextByteLength; } // wide-char versions void setWText(const LLWString& text); @@ -489,10 +499,10 @@ public: LLRect getTextBoundingRect(); LLRect getVisibleDocumentRect() const; - S32 getVPad() { return mVPad; } - S32 getHPad() { return mHPad; } - F32 getLineSpacingMult() { return mLineSpacingMult; } - S32 getLineSpacingPixels() { return mLineSpacingPixels; } // only for multiline + S32 getVPad() const { return mVPad; } + S32 getHPad() const { return mHPad; } + F32 getLineSpacingMult() const { return mLineSpacingMult; } + S32 getLineSpacingPixels() const { return mLineSpacingPixels; } // only for multiline S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, bool round, bool hit_past_end_of_line = true) const; LLRect getLocalRectFromDocIndex(S32 pos) const; @@ -502,7 +512,7 @@ public: bool getReadOnly() const { return mReadOnly; } void setSkipLinkUnderline(bool skip_link_underline) { mSkipLinkUnderline = skip_link_underline; } - bool getSkipLinkUnderline() { return mSkipLinkUnderline; } + bool getSkipLinkUnderline() const { return mSkipLinkUnderline; } void setParseURLs(bool parse_urls) { mParseHTML = parse_urls; } @@ -516,8 +526,8 @@ public: void endOfLine(); void startOfDoc(); void endOfDoc(); - void changePage( S32 delta ); - void changeLine( S32 delta ); + void changePage(S32 delta); + void changeLine(S32 delta); bool scrolledToStart(); bool scrolledToEnd(); @@ -531,6 +541,7 @@ public: boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb); boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb); boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb); + boost::signals2::connection setIsObjectReachableCallback(const is_obj_reachable_signal_t::slot_type& cb); void setWordWrap(bool wrap); LLScrollContainer* getScrollContainer() const { return mScroller; } @@ -607,6 +618,7 @@ protected: bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const; }; typedef std::multiset<LLTextSegmentPtr, compare_segment_end> segment_set_t; + typedef LLStyle::EUnderlineLink e_underline; // member functions LLTextBase(const Params &p); @@ -620,12 +632,13 @@ protected: virtual void drawSelectionBackground(); // draws the black box behind the selected text void drawCursor(); void drawText(); + void drawHighlightedBackground(); // modify contents S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted S32 removeStringNoUndo(S32 pos, S32 length); S32 overwriteCharNoUndo(S32 pos, llwchar wc); - void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, bool underline_on_hover_only = false); + void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, e_underline underline_link = e_underline::UNDERLINE_ALWAYS); // manage segments @@ -673,8 +686,8 @@ protected: // avatar names are looked up. void replaceUrl(const std::string &url, const std::string &label, const std::string& icon); - void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); - void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false); + void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params(), bool force_slurl = false); + void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, e_underline underline_link = e_underline::UNDERLINE_ALWAYS); S32 normalizeUri(std::string& uri); protected: @@ -685,6 +698,7 @@ protected: } std::vector<LLRect> getSelectionRects(); + std::vector<std::pair<LLRect, LLUIColor>> getHighlightedBgRects(); protected: // text segmentation and flow @@ -776,6 +790,7 @@ protected: // Used to check if user with given ID is avatar's friend is_friend_signal_t* mIsFriendSignal; is_blocked_signal_t* mIsObjectBlockedSignal; + is_obj_reachable_signal_t* mIsObjectReachableSignal; LLUIString mLabel; // text label that is visible when no user text provided }; diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 9f945d3735..d2a21998a6 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -43,7 +43,7 @@ template class LLTextBox* LLView::getChild<class LLTextBox>( LLTextBox::LLTextBox(const LLTextBox::Params& p) : LLTextBase(p), - mClickedCallback(NULL), + mClickedCallback(nullptr), mShowCursorHand(true) { mSkipTripleClick = true; @@ -135,9 +135,9 @@ void LLTextBox::setText(const LLStringExplicit& text , const LLStyle::Params& in LLTextBase::setText(mText.getString(), input_params ); } -void LLTextBox::setClickedCallback( boost::function<void (void*)> cb, void* userdata /*= NULL */ ) +void LLTextBox::setClickedCallback(std::function<void (void*)> cb, void* userdata /*= nullptr */) { - mClickedCallback = boost::bind(cb, userdata); + mClickedCallback = std::bind(cb, userdata); } S32 LLTextBox::getTextPixelWidth() diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index a3cde45cd0..8716917ced 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -36,7 +36,7 @@ class LLTextBox : public: // *TODO: Add callback to Params - typedef boost::function<void (void)> callback_t; + typedef std::function<void (void)> callback_t; struct Params : public LLInitParam::Block<Params, LLTextBase::Params> {}; @@ -46,36 +46,42 @@ protected: friend class LLUICtrlFactory; public: - virtual ~LLTextBox(); + ~LLTextBox() override; - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; + bool handleHover(S32 x, S32 y, MASK mask) override; - /*virtual*/ void setEnabled(bool enabled); + void setEnabled(bool enabled) override; - /*virtual*/ void setText( const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params() ); + void setText(const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params()) override; - void setRightAlign() { mHAlign = LLFontGL::RIGHT; } - void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } - void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ); + void setRightAlign() { mHAlign = LLFontGL::RIGHT; } + void setHAlign(LLFontGL::HAlign align) { mHAlign = align; } + void setClickedCallback(std::function<void(void*)> cb, void* userdata = nullptr); - void reshapeToFitText(bool called_from_parent = false); + void reshapeToFitText(bool called_from_parent = false); - S32 getTextPixelWidth(); - S32 getTextPixelHeight(); + S32 getTextPixelWidth(); + S32 getTextPixelHeight(); - /*virtual*/ LLSD getValue() const; - /*virtual*/ bool setTextArg( const std::string& key, const LLStringExplicit& text ); + LLSD getValue() const override; + bool setTextArg(const std::string& key, const LLStringExplicit& text) override; - void setShowCursorHand(bool show_cursor) { mShowCursorHand = show_cursor; } + void setShowCursorHand(bool show_cursor) { mShowCursorHand = show_cursor; } protected: - void onUrlLabelUpdated(const std::string &url, const std::string &label); + void onUrlLabelUpdated(const std::string& url, const std::string& label); LLUIString mText; callback_t mClickedCallback; bool mShowCursorHand; + +protected: + virtual std::string _getSearchText() const override + { + return LLTextBase::_getSearchText() + mText.getString(); + } }; // Build time optimization, generate once in .cpp file diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3537c764b9..fcdf3782ae 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -60,6 +60,7 @@ #include "llurlregistry.h" #include "lltooltip.h" #include "llmenugl.h" +#include "llchatmentionhelper.h" #include <queue> #include "llcombobox.h" @@ -209,8 +210,15 @@ public: } virtual bool execute( LLTextBase* editor, S32* delta ) { - mWString = editor->getWText().substr(getPosition(), mLen); - *delta = remove(editor, getPosition(), mLen ); + try + { + mWString = editor->getWText().substr(getPosition(), mLen); + *delta = remove(editor, getPosition(), mLen); + } + catch (std::out_of_range&) + { + return false; + } return (*delta != 0); } virtual S32 undo( LLTextBase* editor ) @@ -263,9 +271,12 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mPrevalidator(p.prevalidator()), mShowContextMenu(p.show_context_menu), mShowEmojiHelper(p.show_emoji_helper), + mShowChatMentionPicker(false), mEnableTooltipPaste(p.enable_tooltip_paste), mPassDelete(false), - mKeepSelectionOnReturn(false) + mKeepSelectionOnReturn(false), + mSelectAllOnFocusReceived(false), + mSelectedOnFocusReceived(false) { mSourceID.generate(); @@ -389,6 +400,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, bool case_insen setCursorPos(loc); mIsSelecting = true; + mSelectedOnFocusReceived = false; mSelectionEnd = mCursorPos; mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size())); } @@ -668,6 +680,13 @@ bool LLTextEditor::canSelectAll() const return true; } +//virtual +void LLTextEditor::deselect() +{ + LLTextBase::deselect(); + mSelectedOnFocusReceived = false; +} + // virtual void LLTextEditor::selectAll() { @@ -685,6 +704,11 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p endSelection(); } +void LLTextEditor::setSelectAllOnFocusReceived(bool b) +{ + mSelectAllOnFocusReceived = b; +} + void LLTextEditor::insertEmoji(llwchar emoji) { LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL; @@ -707,6 +731,30 @@ void LLTextEditor::handleEmojiCommit(llwchar emoji) } } +void LLTextEditor::handleMentionCommit(std::string name_url) +{ + S32 mention_start_pos; + if (LLChatMentionHelper::instance().isCursorInNameMention(getWText(), mCursorPos, &mention_start_pos)) + { + remove(mention_start_pos, mCursorPos - mention_start_pos, true); + insert(mention_start_pos, utf8str_to_wstring(name_url), false, LLTextSegmentPtr()); + + std::string new_text(wstring_to_utf8str(getConvertedText())); + clear(); + appendTextImpl(new_text, LLStyle::Params(), true); + + segment_set_t::const_iterator it = getSegIterContaining(mention_start_pos); + if (it != mSegments.end()) + { + setCursorPos((*it)->getEnd() + 1); + } + else + { + setCursorPos(mention_start_pos); + } + } +} + bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) { bool handled = false; @@ -762,8 +810,16 @@ bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) // Delay cursor flashing resetCursorBlink(); + mSelectedOnFocusReceived = false; if (handled && !gFocusMgr.getMouseCapture()) { + if (!mask && mSelectAllOnFocusReceived) + { + mIsSelecting = false; + mSelectionStart = getLength(); + mSelectionEnd = 0; + mSelectedOnFocusReceived = true; + } gFocusMgr.setMouseCapture( this ); } return handled; @@ -1096,6 +1152,7 @@ void LLTextEditor::removeCharOrTab() } tryToShowEmojiHelper(); + tryToShowMentionHelper(); } else { @@ -1121,6 +1178,7 @@ void LLTextEditor::removeChar() setCursorPos(mCursorPos - 1); removeChar(mCursorPos); tryToShowEmojiHelper(); + tryToShowMentionHelper(); } else { @@ -1182,8 +1240,9 @@ void LLTextEditor::addChar(llwchar wc) setCursorPos(mCursorPos + addChar( mCursorPos, wc )); tryToShowEmojiHelper(); + tryToShowMentionHelper(); - if (!mReadOnly && mAutoreplaceCallback != NULL) + if (!mReadOnly && mAutoreplaceCallback != nullptr) { // autoreplace the text, if necessary S32 replacement_start; @@ -1211,6 +1270,14 @@ void LLTextEditor::showEmojiHelper() LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, LLStringUtil::null, cb); } +void LLTextEditor::hideEmojiHelper() +{ + if (mShowEmojiHelper) + { + LLEmojiHelper::instance().hideHelper(this); + } +} + void LLTextEditor::tryToShowEmojiHelper() { if (mReadOnly || !mShowEmojiHelper) @@ -1232,6 +1299,31 @@ void LLTextEditor::tryToShowEmojiHelper() } } +void LLTextEditor::tryToShowMentionHelper() +{ + if (mReadOnly || !mShowChatMentionPicker) + return; + + S32 mention_start_pos; + LLWString text(getWText()); + if (LLChatMentionHelper::instance().isCursorInNameMention(text, mCursorPos, &mention_start_pos)) + { + const LLRect cursor_rect(getLocalRectFromDocIndex(mention_start_pos)); + std::string name_part(wstring_to_utf8str(text.substr(mention_start_pos, mCursorPos - mention_start_pos))); + name_part.erase(0, 1); + auto cb = [this](std::string name_url) + { + handleMentionCommit(name_url); + }; + LLChatMentionHelper::instance().showHelper(this, cursor_rect.mLeft, cursor_rect.mTop, name_part, cb); + } + else + { + LLChatMentionHelper::instance().hideHelper(); + } +} + + void LLTextEditor::addLineBreakChar(bool group_together) { if( !getEnabled() ) @@ -1858,7 +1950,7 @@ bool LLTextEditor::handleKeyHere(KEY key, MASK mask ) // not handled and let the parent take care of field movement. if (KEY_TAB == key && mTabsToNextField) { - return false; + return mShowChatMentionPicker && LLChatMentionHelper::instance().handleKey(this, key, mask); } if (mReadOnly && mScroller) @@ -1869,9 +1961,13 @@ bool LLTextEditor::handleKeyHere(KEY key, MASK mask ) } else { - if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask)) + if (!mReadOnly) { - return true; + if ((mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask)) || + (mShowChatMentionPicker && LLChatMentionHelper::instance().handleKey(this, key, mask))) + { + return true; + } } if (mEnableTooltipPaste && @@ -2127,6 +2223,11 @@ void LLTextEditor::focusLostHelper() gEditMenuHandler = NULL; } + if (mSelectedOnFocusReceived) + { + deselect(); + } + if (mCommitOnFocusLost) { onCommit(); @@ -3068,3 +3169,21 @@ S32 LLTextEditor::spacesPerTab() { return SPACES_PER_TAB; } + +LLWString LLTextEditor::getConvertedText() const +{ + LLWString text = getWText(); + S32 diff = 0; + for (auto segment : mSegments) + { + if (segment && segment->getStyle() && segment->getStyle()->getDrawHighlightBg()) + { + S32 seg_length = segment->getEnd() - segment->getStart(); + std::string slurl = segment->getStyle()->getLinkHREF(); + + text.replace(segment->getStart() + diff, seg_length, utf8str_to_wstring(slurl)); + diff += (S32)slurl.size() - seg_length; + } + } + return text; +} diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index e9e7070414..d9742db34d 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -95,6 +95,8 @@ public: void insertEmoji(llwchar emoji); void handleEmojiCommit(llwchar emoji); + void handleMentionCommit(std::string name_url); + // mousehandler overrides virtual bool handleMouseDown(S32 x, S32 y, MASK mask); virtual bool handleMouseUp(S32 x, S32 y, MASK mask); @@ -142,8 +144,10 @@ public: virtual bool canDoDelete() const; virtual void selectAll(); virtual bool canSelectAll() const; + virtual void deselect(); void selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos); + void setSelectAllOnFocusReceived(bool b); virtual bool canLoadOrSaveToFile(); @@ -160,7 +164,7 @@ public: bool allowsEmbeddedItems() const { return mAllowEmbeddedItems; } // Autoreplace (formerly part of LLLineEditor) - typedef boost::function<void(S32&, S32&, LLWString&, S32&, const LLWString&)> autoreplace_callback_t; + typedef std::function<void(S32&, S32&, LLWString&, S32&, const LLWString&)> autoreplace_callback_t; autoreplace_callback_t mAutoreplaceCallback; void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; } @@ -200,24 +204,24 @@ 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; } bool getShowContextMenu() const { return mShowContextMenu; } void showEmojiHelper(); + void hideEmojiHelper(); void setShowEmojiHelper(bool show); bool getShowEmojiHelper() const { return mShowEmojiHelper; } void setPassDelete(bool b) { mPassDelete = b; } + LLWString getConvertedText() const; + protected: void showContextMenu(S32 x, S32 y); void drawPreeditMarker(); - void assignEmbedded(const std::string &s); - void removeCharOrTab(); void indentSelectedLines( S32 spaces ); @@ -237,7 +241,6 @@ protected: void autoIndent(); - void findEmbeddedItemSegments(S32 start, S32 end); void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const; virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; } @@ -257,6 +260,7 @@ protected: S32 remove(S32 pos, S32 length, bool group_with_next_op); void tryToShowEmojiHelper(); + void tryToShowMentionHelper(); void focusLostHelper(); void updateAllowingLanguageInput(); bool hasPreeditString() const; @@ -294,6 +298,7 @@ protected: bool mAutoIndent; bool mParseOnTheFly; + bool mShowChatMentionPicker; void updateLinkSegments(); void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; } @@ -304,7 +309,7 @@ private: // Methods // void pasteHelper(bool is_primary); - void cleanStringForPaste(LLWString & clean_string); + void cleanStringForPaste(LLWString& clean_string); void pasteTextWithLinebreaks(LLWString & clean_string); void onKeyStroke(); @@ -333,6 +338,8 @@ private: bool mEnableTooltipPaste; bool mPassDelete; bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter + bool mSelectAllOnFocusReceived; + bool mSelectedOnFocusReceived; LLUUID mSourceID; diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp index 8ffce1b8b4..1454de34c7 100644 --- a/indra/llui/lltextutil.cpp +++ b/indra/llui/lltextutil.cpp @@ -30,7 +30,7 @@ #include "lltextbox.h" #include "llurlmatch.h" -boost::function<bool(LLUrlMatch*,LLTextBase*)> LLTextUtil::TextHelpers::iconCallbackCreationFunction = 0; +std::function<bool(LLUrlMatch*, LLTextBase*)> LLTextUtil::TextHelpers::iconCallbackCreationFunction = nullptr; void LLTextUtil::textboxSetHighlightedVal(LLTextBox *txtbox, const LLStyle::Params& normal_style, const std::string& text, const std::string& hl) { diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h index f3838e59fa..6328ff133f 100644 --- a/indra/llui/lltextutil.h +++ b/indra/llui/lltextutil.h @@ -74,7 +74,7 @@ namespace LLTextUtil //we need this special callback since we need to create LLAvataIconCtrls while parsing //avatar/group url but can't create LLAvataIconCtrl from LLUI public: - static boost::function<bool(LLUrlMatch*,LLTextBase*)> iconCallbackCreationFunction; + static std::function<bool(LLUrlMatch*,LLTextBase*)> iconCallbackCreationFunction; }; diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h index a4ff144d82..096c28b448 100644 --- a/indra/llui/lltextvalidate.h +++ b/indra/llui/lltextvalidate.h @@ -30,7 +30,6 @@ #include "llstring.h" #include "llinitparam.h" -#include <boost/function.hpp> namespace LLTextValidate { diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 5955a28fa3..785dc85448 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -99,8 +99,8 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p) mWrap(p.wrap), mNeedsLayout(false), mModified(false), - mButtonPanel(NULL), - mCenteringStack(NULL), + mButtonPanel(nullptr), + mCenteringStack(nullptr), mPadLeft(p.pad_left), mPadRight(p.pad_right), mPadTop(p.pad_top), @@ -108,17 +108,17 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p) mPadBetween(p.pad_between), mMinGirth(p.min_girth), mPopupMenuHandle(), - mRightMouseTargetButton(NULL), - mStartDragItemCallback(NULL), - mHandleDragItemCallback(NULL), - mHandleDropCallback(NULL), - mButtonAddSignal(NULL), - mButtonEnterSignal(NULL), - mButtonLeaveSignal(NULL), - mButtonRemoveSignal(NULL), + mRightMouseTargetButton(nullptr), + mStartDragItemCallback(nullptr), + mHandleDragItemCallback(nullptr), + mHandleDropCallback(nullptr), + mButtonAddSignal(nullptr), + mButtonEnterSignal(nullptr), + mButtonLeaveSignal(nullptr), + mButtonRemoveSignal(nullptr), mDragAndDropTarget(false), - mCaretIcon(NULL), - mCenterPanel(NULL) + mCaretIcon(nullptr), + mCenterPanel(nullptr) { mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_WITH_TEXT] = p.button_icon_and_text; mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_ONLY] = p.button_icon; @@ -1054,7 +1054,7 @@ bool LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, // if drop is set, it's time to call the callback to get the operation done if (handled && drop) { - handled = mHandleDropCallback(cargo_data, x, y, this); + handled = mHandleDropCallback(cargo_data, cargo_type, x, y, this); } // We accept only single tool drop on toolbars @@ -1097,12 +1097,12 @@ LLToolBarButton::LLToolBarButton(const Params& p) mWidthRange(p.button_width), mDesiredHeight(p.desired_height), mId(""), - mIsEnabledSignal(NULL), - mIsRunningSignal(NULL), - mIsStartingSignal(NULL), + mIsEnabledSignal(nullptr), + mIsRunningSignal(nullptr), + mIsStartingSignal(nullptr), mIsDragged(false), - mStartDragItemCallback(NULL), - mHandleDragItemCallback(NULL), + mStartDragItemCallback(nullptr), + mHandleDragItemCallback(nullptr), mOriginalImageSelected(p.image_selected), mOriginalImageUnselected(p.image_unselected), mOriginalImagePressed(p.image_pressed), @@ -1256,7 +1256,7 @@ void LLToolBar::LLCenterLayoutPanel::handleReshape(const LLRect& rect, bool by_u { LLLayoutPanel::handleReshape(rect, by_user); - if (!mReshapeCallback.empty()) + if (mReshapeCallback != nullptr) { LLRect r; localRectToOtherView(mButtonPanel->getRect(), &r, gFloaterView); diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h index c57c979525..abf44f259a 100644 --- a/indra/llui/lltoolbar.h +++ b/indra/llui/lltoolbar.h @@ -39,9 +39,9 @@ class LLToolBar; class LLToolBarButton; class LLIconCtrl; -typedef boost::function<void (S32 x, S32 y, LLToolBarButton* button)> tool_startdrag_callback_t; -typedef boost::function<bool (S32 x, S32 y, const LLUUID& uuid, LLAssetType::EType type)> tool_handledrag_callback_t; -typedef boost::function<bool (void* data, S32 x, S32 y, LLToolBar* toolbar)> tool_handledrop_callback_t; +typedef std::function<void (S32 x, S32 y, LLToolBarButton* button)> tool_startdrag_callback_t; +typedef std::function<bool (S32 x, S32 y, const LLUUID& uuid, LLAssetType::EType type)> tool_handledrag_callback_t; +typedef std::function<bool (void* data, EDragAndDropType cargo_type, S32 x, S32 y, LLToolBar* toolbar)> tool_handledrop_callback_t; class LLToolBarButton : public LLButton { @@ -68,7 +68,7 @@ public: void reshape(S32 width, S32 height, bool called_from_parent = true); void setEnabled(bool enabled); void setCommandId(const LLCommandId& id) { mId = id; } - LLCommandId getCommandId() { return mId; } + LLCommandId getCommandId() const { return mId; } void setStartDragCallback(tool_startdrag_callback_t cb) { mStartDragItemCallback = cb; } void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; } @@ -167,7 +167,7 @@ public: class LLCenterLayoutPanel : public LLLayoutPanel { public: - typedef boost::function<void(LLToolBarEnums::EToolBarLocation tb, const LLRect& rect)> reshape_callback_t; + typedef std::function<void(LLToolBarEnums::EToolBarLocation tb, const LLRect& rect)> reshape_callback_t; virtual ~LLCenterLayoutPanel() {} /*virtual*/ void handleReshape(const LLRect& rect, bool by_user); @@ -256,7 +256,7 @@ public: // Methods used in loading and saving toolbar settings void setButtonType(LLToolBarEnums::ButtonType button_type); - LLToolBarEnums::ButtonType getButtonType() { return mButtonType; } + LLToolBarEnums::ButtonType getButtonType() const { return mButtonType; } command_id_list_t& getCommandsList() { return mButtonCommands; } void clearCommandsList(); diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 86525c2f7e..74f03618cf 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -390,22 +390,22 @@ void LLToolTip::draw() } } -bool LLToolTip::isFading() +bool LLToolTip::isFading() const { return mFadeTimer.getStarted(); } -F32 LLToolTip::getVisibleTime() +F32 LLToolTip::getVisibleTime() const { return mVisibleTimer.getStarted() ? mVisibleTimer.getElapsedTimeF32() : 0.f; } -bool LLToolTip::hasClickCallback() +bool LLToolTip::hasClickCallback() const { return mHasClickCallback; } -void LLToolTip::getToolTipMessage(std::string & message) +void LLToolTip::getToolTipMessage(std::string& message) const { if (mTextBox) { diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 8515504e3b..c9d6937c1a 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -44,15 +44,15 @@ public: Params(); }; LLToolTipView(const LLToolTipView::Params&); - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMiddleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleScrollWheel( S32 x, S32 y, S32 clicks ); + bool handleHover(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleMiddleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleRightMouseDown(S32 x, S32 y, MASK mask) override; + bool handleScrollWheel( S32 x, S32 y, S32 clicks ) override; void drawStickyRect(); - /*virtual*/ void draw(); + void draw() override; }; class LLToolTip : public LLPanel @@ -67,8 +67,8 @@ public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> { - typedef boost::function<void(void)> click_callback_t; - typedef boost::function<LLToolTip*(LLToolTip::Params)> create_callback_t; + typedef std::function<void(void)> click_callback_t; + typedef std::function<LLToolTip*(LLToolTip::Params)> create_callback_t; Optional<std::string> message; Multiple<StyledText> styled_message; @@ -98,20 +98,20 @@ public: Params(); }; - /*virtual*/ void draw(); - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); - /*virtual*/ void setVisible(bool visible); + void draw() override; + bool handleHover(S32 x, S32 y, MASK mask) override; + void onMouseLeave(S32 x, S32 y, MASK mask) override; + void setVisible(bool visible) override; - bool isFading(); - F32 getVisibleTime(); - bool hasClickCallback(); + bool isFading() const; + F32 getVisibleTime() const; + bool hasClickCallback() const; LLToolTip(const Params& p); virtual void initFromParams(const LLToolTip::Params& params); - void getToolTipMessage(std::string & message); - bool isTooltipPastable() { return mIsTooltipPastable; } + void getToolTipMessage(std::string & message) const; + bool isTooltipPastable() const { return mIsTooltipPastable; } protected: void updateTextBox(); diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index e7dea79eaa..179d1dcaff 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -213,13 +213,8 @@ void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& rem void LLUI::setMousePositionScreen(S32 x, S32 y) { -#if defined(LL_DARWIN) - S32 screen_x = ll_round(((F32)x * getScaleFactor().mV[VX]) / LLView::getWindow()->getSystemUISize()); - S32 screen_y = ll_round(((F32)y * getScaleFactor().mV[VY]) / LLView::getWindow()->getSystemUISize()); -#else S32 screen_x = ll_round((F32)x * getScaleFactor().mV[VX]); S32 screen_y = ll_round((F32)y * getScaleFactor().mV[VY]); -#endif LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert()); } diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 375cd539b7..2ef64baaf6 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -31,8 +31,6 @@ #include "llrect.h" #include "llcoord.h" #include "llcontrol.h" -#include "llcoord.h" -#include "llcontrol.h" #include "llinitparam.h" #include "llregistry.h" #include "llrender2dutils.h" @@ -156,7 +154,7 @@ public: sanitizeRange(); } - S32 clamp(S32 input) + S32 clamp(S32 input) const { if (input < mMin) return mMin; if (input > mMax) return mMax; @@ -170,8 +168,8 @@ public: sanitizeRange(); } - S32 getMin() { return mMin; } - S32 getMax() { return mMax; } + S32 getMin() const { return mMin; } + S32 getMax() const { return mMax; } bool operator==(const RangeS32& other) const { @@ -225,7 +223,7 @@ public: mValue = clamp(value); } - S32 get() + S32 get() const { return mValue; } @@ -243,9 +241,9 @@ public: // // Methods // - typedef boost::function<void(LLView*)> add_popup_t; - typedef boost::function<void(LLView*)> remove_popup_t; - typedef boost::function<void(void)> clear_popups_t; + typedef std::function<void(LLView*)> add_popup_t; + typedef std::function<void(LLView*)> remove_popup_t; + typedef std::function<void(void)> clear_popups_t; void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& ); @@ -255,7 +253,7 @@ public: static std::string getLanguage(); // static for lldateutil_test compatibility //helper functions (should probably move free standing rendering helper functions here) - LLView* getRootView() { return mRootView; } + LLView* getRootView() const { return mRootView; } void setRootView(LLView* view) { mRootView = view; } /** * Walk the LLView tree to resolve a path @@ -298,7 +296,7 @@ public: LLControlGroup& getControlControlGroup (std::string_view controlname); F32 getMouseIdleTime() { return mMouseIdleTimer.getElapsedTimeF32(); } void resetMouseIdleTimer() { mMouseIdleTimer.reset(); } - LLWindow* getWindow() { return mWindow; } + LLWindow* getWindow() const { return mWindow; } void addPopup(LLView*); void removePopup(LLView*); diff --git a/indra/llui/lluiconstants.h b/indra/llui/lluiconstants.h index 5fdfd37c6e..a317c66008 100644 --- a/indra/llui/lluiconstants.h +++ b/indra/llui/lluiconstants.h @@ -28,23 +28,23 @@ #define LL_LLUICONSTANTS_H // spacing for small font lines of text, like LLTextBoxes -const S32 LINE = 16; +constexpr S32 LINE = 16; // spacing for larger lines of text -const S32 LINE_BIG = 24; +constexpr S32 LINE_BIG = 24; // default vertical padding -const S32 VPAD = 4; +constexpr S32 VPAD = 4; // default horizontal padding -const S32 HPAD = 4; +constexpr S32 HPAD = 4; // Account History, how far to look into past -const S32 SUMMARY_INTERVAL = 7; // one week -const S32 SUMMARY_MAX = 8; // -const S32 DETAILS_INTERVAL = 1; // one day -const S32 DETAILS_MAX = 30; // one month -const S32 TRANSACTIONS_INTERVAL = 1;// one day -const S32 TRANSACTIONS_MAX = 30; // one month +constexpr S32 SUMMARY_INTERVAL = 7; // one week +constexpr S32 SUMMARY_MAX = 8; // +constexpr S32 DETAILS_INTERVAL = 1; // one day +constexpr S32 DETAILS_MAX = 30; // one month +constexpr S32 TRANSACTIONS_INTERVAL = 1;// one day +constexpr S32 TRANSACTIONS_MAX = 30; // one month #endif diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index cbabb5a933..05461edd82 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -999,15 +999,16 @@ bool LLUICtrl::findHelpTopic(std::string& help_topic_out) } // *TODO: Deprecate; for backwards compatability only: -boost::signals2::connection LLUICtrl::setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data) +boost::signals2::connection LLUICtrl::setCommitCallback( std::function<void (LLUICtrl*,void*)> cb, void* data) { - return setCommitCallback( boost::bind(cb, _1, data)); + return setCommitCallback( std::bind(cb, std::placeholders::_1, data)); } -boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb ) + +boost::signals2::connection LLUICtrl::setValidateBeforeCommit( std::function<bool (const LLSD& data)> cb ) { if (!mValidateSignal) mValidateSignal = new enable_signal_t(); - return mValidateSignal->connect(boost::bind(cb, _2)); + return mValidateSignal->connect(std::bind(cb, std::placeholders::_2)); } // virtual diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 8cd9950917..749999bbfe 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -31,7 +31,8 @@ //#include "llboost.h" #include "llrect.h" #include "llsd.h" -#include <boost/function.hpp> +#include <functional> +#include <boost/bind.hpp> #include <boost/signals2.hpp> #include "llinitparam.h" @@ -39,20 +40,20 @@ #include "llviewmodel.h" // *TODO move dependency to .cpp file #include "llsearchablecontrol.h" -const bool TAKE_FOCUS_YES = true; -const bool TAKE_FOCUS_NO = false; -const S32 DROP_SHADOW_FLOATER = 5; +constexpr bool TAKE_FOCUS_YES = true; +constexpr bool TAKE_FOCUS_NO = false; +constexpr S32 DROP_SHADOW_FLOATER = 5; class LLUICtrl : public LLView, public boost::signals2::trackable { public: - typedef boost::function<void (LLUICtrl* ctrl, const LLSD& param)> commit_callback_t; + typedef std::function<void (LLUICtrl* ctrl, const LLSD& param)> commit_callback_t; typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> commit_signal_t; // *TODO: add xml support for this type of signal in the future typedef boost::signals2::signal<void (LLUICtrl* ctrl, S32 x, S32 y, MASK mask)> mouse_signal_t; - typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> enable_callback_t; + typedef std::function<bool (LLUICtrl* ctrl, const LLSD& param)> enable_callback_t; typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t; struct CallbackParam : public LLInitParam::Block<CallbackParam> @@ -258,8 +259,8 @@ public: boost::signals2::connection setDoubleClickCallback( const mouse_signal_t::slot_type& cb ); // *TODO: Deprecate; for backwards compatability only: - boost::signals2::connection setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data); - boost::signals2::connection setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb ); + boost::signals2::connection setCommitCallback( std::function<void (LLUICtrl*,void*)> cb, void* data); + boost::signals2::connection setValidateBeforeCommit( std::function<bool (const LLSD& data)> cb ); LLUICtrl* findRootMostFocusRoot(); diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index a2a6d661ff..9abccfd9a0 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -100,16 +100,19 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa std::string base_filename = search_paths.front(); if (!base_filename.empty()) { - LLUICtrlFactory::instance().pushFileName(base_filename); + LLUICtrlFactory *factory = LLUICtrlFactory::getInstance(); + factory->mFileNames.push_back(base_filename); - if (!LLXMLNode::getLayeredXMLNode(root_node, search_paths)) + if (LLXMLNode::getLayeredXMLNode(root_node, search_paths)) + { + LLXUIParser parser; + parser.readXUI(root_node, block, base_filename); + } + else { LL_WARNS() << "Couldn't parse widget from: " << base_filename << LL_ENDL; - return; } - LLXUIParser parser; - parser.readXUI(root_node, block, base_filename); - LLUICtrlFactory::instance().popFileName(); + factory->mFileNames.pop_back(); } } diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 75e7e396bc..fc069c078f 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -184,7 +184,7 @@ fail: template<class T> static T* getDefaultWidget(std::string_view name) { - typename T::Params widget_params; + typename T::Params widget_params{}; widget_params.name = std::string(name); return create<T>(widget_params); } @@ -311,7 +311,7 @@ LLUICtrlFactory::ParamDefaults<LLInitParam::BaseBlock, DUMMY>::ParamDefaults() { template<typename DERIVED> template<typename T> LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreatorFunc func) -: LLChildRegistry<DERIVED>::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func) +: LLChildRegistry<DERIVED>::StaticRegistrar(tag, func == nullptr ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func) { // add this widget to various registries LLUICtrlFactory::instance().registerWidget(&typeid(T), &typeid(typename T::Params), tag); diff --git a/indra/llui/llundo.h b/indra/llui/llundo.h index dc40702be0..990745e530 100644 --- a/indra/llui/llundo.h +++ b/indra/llui/llundo.h @@ -42,7 +42,7 @@ public: LLUndoAction(): mClusterID(0) {}; virtual ~LLUndoAction(){}; private: - S32 mClusterID; + S32 mClusterID; }; LLUndoBuffer( LLUndoAction (*create_func()), S32 initial_count ); @@ -51,8 +51,8 @@ public: LLUndoAction *getNextAction(bool setClusterBegin = true); bool undoAction(); bool redoAction(); - bool canUndo() { return (mNextAction != mFirstAction); } - bool canRedo() { return (mNextAction != mLastAction); } + bool canUndo() const { return (mNextAction != mFirstAction); } + bool canRedo() const { return (mNextAction != mLastAction); } void flushActions(); diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index b6b450c2a1..8b320b59cc 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -30,6 +30,7 @@ #include "llview.h" #include "llwindow.h" #include "llurlregistry.h" +#include "v3dmath.h" // global state for the callback functions @@ -116,6 +117,16 @@ void LLUrlAction::teleportToLocation(std::string url) } } +void LLUrlAction::zoomInObject(std::string url) +{ + LLUrlMatch match; + std::string object_id = getObjectId(url); + if (LLUUID::validate(object_id) && LLUrlRegistry::instance().findUrl(url, match)) + { + executeSLURL("secondlife:///app/object/" + object_id + "/zoomin/" + match.getLocation()); + } +} + void LLUrlAction::showLocationOnMap(std::string url) { LLUrlMatch match; @@ -128,6 +139,23 @@ void LLUrlAction::showLocationOnMap(std::string url) } } +void LLUrlAction::showParcelOnMap(std::string url) +{ + LLSD path_array = LLURI(url).pathArray(); + auto path_parts = path_array.size(); + + if (path_parts < 3) // no parcel id + { + LL_WARNS() << "Global coordinates are missing in url: [" << url << "]" << LL_ENDL; + return; + } + + LLVector3d parcel_pos = LLUrlEntryParcel::getParcelPos(LLUUID(LLURI::unescape(path_array[2]))); + std::ostringstream pos; + pos << parcel_pos.mdV[VX] << '/' << parcel_pos.mdV[VY] << '/' << parcel_pos.mdV[VZ]; + executeSLURL("secondlife:///app/worldmap_global/" + pos.str()); +} + void LLUrlAction::copyURLToClipboard(std::string url) { LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url)); @@ -142,6 +170,16 @@ void LLUrlAction::copyLabelToClipboard(std::string url) } } +std::string LLUrlAction::getURLLabel(std::string url) +{ + LLUrlMatch match; + if (LLUrlRegistry::instance().findUrl(url, match)) + { + return match.getLabel(); + } + return ""; +} + void LLUrlAction::showProfile(std::string url) { // Get id from 'secondlife:///app/{cmd}/{id}/{action}' diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index 0f54b66299..c4cfd0f3fb 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -28,8 +28,8 @@ #ifndef LL_LLURLACTION_H #define LL_LLURLACTION_H +#include <functional> #include <string> -#include <boost/function.hpp> /// /// The LLUrlAction class provides a number of static functions that @@ -45,8 +45,6 @@ class LLUrlAction { public: - LLUrlAction(); - /// load a Url in the user's preferred web browser static void openURL(std::string url); @@ -62,9 +60,15 @@ public: /// if the Url specifies an SL location, teleport there static void teleportToLocation(std::string url); + /// If the Url specifies an object id, attempt to zoom in. + /// If not possible to zoom in, show on map + static void zoomInObject(std::string url); + /// if the Url specifies an SL location, show it on a map static void showLocationOnMap(std::string url); + static void showParcelOnMap(std::string url); + /// perform the appropriate action for left-clicking on a Url static void clickAction(std::string url, bool trusted_content); @@ -74,6 +78,8 @@ public: /// copy a Url to the clipboard static void copyURLToClipboard(std::string url); + static std::string getURLLabel(std::string url); + /// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile static void showProfile(std::string url); static std::string getUserID(std::string url); @@ -87,8 +93,8 @@ public: static void unblockObject(std::string url); /// specify the callbacks to enable this class's functionality - typedef boost::function<void (const std::string&)> url_callback_t; - typedef boost::function<bool(const std::string& url, bool trusted_content)> execute_url_callback_t; + typedef std::function<void (const std::string&)> url_callback_t; + typedef std::function<bool(const std::string& url, bool trusted_content)> execute_url_callback_t; static void setOpenURLCallback(url_callback_t cb); static void setOpenURLInternalCallback(url_callback_t cb); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 3cc0c05ffa..bba80dd20e 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -29,7 +29,6 @@ #include "llurlentry.h" #include "lluictrl.h" #include "lluri.h" -#include "llurlmatch.h" #include "llurlregistry.h" #include "lluriparser.h" @@ -42,13 +41,12 @@ #include "lluicolortable.h" #include "message.h" #include "llexperiencecache.h" - -#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" +#include "v3dmath.h" // Utility functions std::string localize_slapp_label(const std::string& url, const std::string& full_name); - +LLUUID LLUrlEntryBase::sAgentID(LLUUID::null); LLUrlEntryBase::LLUrlEntryBase() { } @@ -68,7 +66,7 @@ std::string LLUrlEntryBase::getIcon(const std::string &url) return mIcon; } -LLStyle::Params LLUrlEntryBase::getStyle() const +LLStyle::Params LLUrlEntryBase::getStyle(const std::string &url) const { LLStyle::Params style_params; style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); @@ -221,12 +219,22 @@ bool LLUrlEntryBase::isWikiLinkCorrect(const std::string &labeled_url) const }, L'\u002F'); // Solidus + std::replace_if(wlabel.begin(), + wlabel.end(), + [](const llwchar& chr) + { + return // Not a decomposition, but suficiently similar + (chr == L'\u04BA') // "Cyrillic Capital Letter Shha" + || (chr == L'\u04BB'); // "Cyrillic Small Letter Shha" + }, + L'\u0068'); // "Latin Small Letter H" + 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; + label = "https://" + label; } return !LLUrlRegistry::instance().hasUrl(label); @@ -307,7 +315,7 @@ std::string LLUrlEntryHTTP::getUrl(const std::string &string) const { if (string.find("://") == std::string::npos) { - return "http://" + escapeUrl(string); + return "https://" + escapeUrl(string); } return escapeUrl(string); } @@ -621,6 +629,11 @@ LLUUID LLUrlEntryAgent::getID(const std::string &string) const return LLUUID(getIDStringFromUrl(string)); } +bool LLUrlEntryAgent::isAgentID(const std::string& url) const +{ + return sAgentID == getID(url); +} + std::string LLUrlEntryAgent::getTooltip(const std::string &string) const { // return a tooltip corresponding to the URL type instead of the generic one @@ -657,10 +670,14 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const return LLTrans::getString("TooltipAgentUrl"); } -bool LLUrlEntryAgent::underlineOnHoverOnly(const std::string &string) const +LLStyle::EUnderlineLink LLUrlEntryAgent::getUnderline(const std::string& string) const { std::string url = getUrl(string); - return LLStringUtil::endsWith(url, "/about") || LLStringUtil::endsWith(url, "/inspect"); + if (LLStringUtil::endsWith(url, "/about") || LLStringUtil::endsWith(url, "/inspect")) + { + return LLStyle::EUnderlineLink::UNDERLINE_ON_HOVER; + } + return LLStyle::EUnderlineLink::UNDERLINE_ALWAYS; } std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb) @@ -702,11 +719,12 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa } } -LLStyle::Params LLUrlEntryAgent::getStyle() const +LLStyle::Params LLUrlEntryAgent::getStyle(const std::string &url) const { - LLStyle::Params style_params = LLUrlEntryBase::getStyle(); + LLStyle::Params style_params = LLUrlEntryBase::getStyle(url); style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); + return style_params; } @@ -741,6 +759,10 @@ std::string localize_slapp_label(const std::string& url, const std::string& full { return LLTrans::getString("SLappAgentRemoveFriend") + " " + full_name; } + if (LLStringUtil::endsWith(url, "/mention")) + { + return "@" + full_name; + } return full_name; } @@ -752,6 +774,36 @@ std::string LLUrlEntryAgent::getIcon(const std::string &url) return mIcon; } +/// +/// LLUrlEntryAgentMention Describes a chat mention Url, e.g., +/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/mention +/// +LLUrlEntryAgentMention::LLUrlEntryAgentMention() +{ + mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/mention", boost::regex::perl | boost::regex::icase); + mMenuName = "menu_url_agent.xml"; + mIcon = std::string(); +} + +LLStyle::EUnderlineLink LLUrlEntryAgentMention::getUnderline(const std::string& string) const +{ + return LLStyle::EUnderlineLink::UNDERLINE_NEVER; +} + +LLStyle::Params LLUrlEntryAgentMention::getStyle(const std::string& url) const +{ + LLStyle::Params style_params = LLUrlEntryAgent::getStyle(url); + style_params.color = LLUIColorTable::instance().getColor("ChatMentionFont"); + style_params.readonly_color = LLUIColorTable::instance().getColor("ChatMentionFont"); + style_params.font.style = "NORMAL"; + style_params.draw_highlight_bg = true; + + LLUUID agent_id(getIDStringFromUrl(url)); + style_params.highlight_bg_color = LLUIColorTable::instance().getColor((agent_id == sAgentID) ? "ChatSelfMentionHighlight" : "ChatMentionHighlight"); + + return style_params; +} + // // LLUrlEntryAgentName describes a Second Life agent name Url, e.g., // secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username) @@ -813,7 +865,7 @@ std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLab } } -LLStyle::Params LLUrlEntryAgentName::getStyle() const +LLStyle::Params LLUrlEntryAgentName::getStyle(const std::string &url) const { // don't override default colors return LLStyle::Params().is_link(false); @@ -949,9 +1001,9 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa } } -LLStyle::Params LLUrlEntryGroup::getStyle() const +LLStyle::Params LLUrlEntryGroup::getStyle(const std::string &url) const { - LLStyle::Params style_params = LLUrlEntryBase::getStyle(); + LLStyle::Params style_params = LLUrlEntryBase::getStyle(url); style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); return style_params; @@ -1027,11 +1079,11 @@ std::string LLUrlEntryChat::getLabel(const std::string &url, const LLUrlLabelCal } // LLUrlEntryParcel statics. -LLUUID LLUrlEntryParcel::sAgentID(LLUUID::null); LLUUID LLUrlEntryParcel::sSessionID(LLUUID::null); LLHost LLUrlEntryParcel::sRegionHost; bool LLUrlEntryParcel::sDisconnected(false); std::set<LLUrlEntryParcel*> LLUrlEntryParcel::sParcelInfoObservers; +std::map<LLUUID, LLVector3d> LLUrlEntryParcel::sParcelPos; /// /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g., @@ -1124,6 +1176,20 @@ void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data) url_entry->onParcelInfoReceived(parcel_data.parcel_id.asString(), label); } } + if (sParcelPos.find(parcel_data.parcel_id) == sParcelPos.end()) + { + sParcelPos[parcel_data.parcel_id] = LLVector3d(parcel_data.global_x, parcel_data.global_y, parcel_data.global_z); + } +} + +// static +LLVector3d LLUrlEntryParcel::getParcelPos(const LLUUID& parcel_id) +{ + if (sParcelPos.find(parcel_id) != sParcelPos.end()) + { + return sParcelPos[parcel_id]; + } + return LLVector3d(); } // @@ -1361,17 +1427,17 @@ std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const return LLUrlEntryBase::getTooltip(string); } -bool LLUrlEntrySLLabel::underlineOnHoverOnly(const std::string &string) const +LLStyle::EUnderlineLink LLUrlEntrySLLabel::getUnderline(const std::string& string) const { std::string url = getUrl(string); - LLUrlMatch match; + LLUrlMatch match; if (LLUrlRegistry::instance().findUrl(url, match)) { - return match.underlineOnHoverOnly(); + return match.getUnderline(); } // unrecognized URL? should not happen - return LLUrlEntryBase::underlineOnHoverOnly(string); + return LLUrlEntryBase::getUnderline(string); } // @@ -1435,7 +1501,7 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC return getUrl(url); } -LLStyle::Params LLUrlEntryNoLink::getStyle() const +LLStyle::Params LLUrlEntryNoLink::getStyle(const std::string &url) const { // Don't render as URL (i.e. no context menu or hand cursor). return LLStyle::Params().is_link(false); diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index fffee88496..efb5081103 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -41,6 +41,9 @@ #include <map> class LLAvatarName; +class LLVector3d; + +#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" typedef boost::signals2::signal<void (const std::string& url, const std::string& label, @@ -85,7 +88,7 @@ public: virtual std::string getIcon(const std::string &url); /// Return the style to render the displayed text - virtual LLStyle::Params getStyle() const; + virtual LLStyle::Params getStyle(const std::string &url) const; /// Given a matched Url, return a tooltip string for the hyperlink virtual std::string getTooltip(const std::string &string) const { return mTooltip; } @@ -96,12 +99,14 @@ public: /// Return the name of a SL location described by this Url, if any virtual std::string getLocation(const std::string &url) const { return ""; } - /// Should this link text be underlined only when mouse is hovered over it? - virtual bool underlineOnHoverOnly(const std::string &string) const { return false; } + virtual LLStyle::EUnderlineLink getUnderline(const std::string& string) const { return LLStyle::EUnderlineLink::UNDERLINE_ALWAYS; } virtual bool isTrusted() const { return false; } + virtual bool getSkipProfileIcon(const std::string& string) const { return false; } + virtual LLUUID getID(const std::string &string) const { return LLUUID::null; } + virtual bool isAgentID(const std::string& url) const { return false; } bool isLinkDisabled() const; @@ -109,6 +114,8 @@ public: virtual bool isSLURLvalid(const std::string &url) const { return true; }; + static void setAgentID(const LLUUID& id) { sAgentID = id; } + protected: std::string getIDStringFromUrl(const std::string &url) const; std::string escapeUrl(const std::string &url) const; @@ -130,6 +137,8 @@ protected: std::string mMenuName; std::string mTooltip; std::multimap<std::string, LLUrlEntryObserver> mObservers; + + static LLUUID sAgentID; }; /// @@ -224,9 +233,13 @@ public: /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); /*virtual*/ std::string getIcon(const std::string &url); /*virtual*/ std::string getTooltip(const std::string &string) const; - /*virtual*/ LLStyle::Params getStyle() const; + /*virtual*/ LLStyle::Params getStyle(const std::string &url) const; /*virtual*/ LLUUID getID(const std::string &string) const; - /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const; + + bool isAgentID(const std::string& url) const; + + LLStyle::EUnderlineLink getUnderline(const std::string& string) const; + protected: /*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon); private: @@ -237,6 +250,19 @@ private: }; /// +/// LLUrlEntryAgentMention Describes a chat mention Url, e.g., +/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/mention +class LLUrlEntryAgentMention : public LLUrlEntryAgent +{ +public: + LLUrlEntryAgentMention(); + + LLStyle::Params getStyle(const std::string& url) const; + LLStyle::EUnderlineLink getUnderline(const std::string& string) const; + bool getSkipProfileIcon(const std::string& string) const { return true; }; +}; + +/// /// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g., /// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username) /// that displays various forms of user name @@ -257,7 +283,7 @@ public: mAvatarNameCacheConnections.clear(); } /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ LLStyle::Params getStyle() const; + /*virtual*/ LLStyle::Params getStyle(const std::string &url) const; protected: // override this to pull out relevant name fields virtual std::string getName(const LLAvatarName& avatar_name) = 0; @@ -339,7 +365,7 @@ class LLUrlEntryGroup : public LLUrlEntryBase public: LLUrlEntryGroup(); /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ LLStyle::Params getStyle() const; + /*virtual*/ LLStyle::Params getStyle(const std::string &url) const; /*virtual*/ LLUUID getID(const std::string &string) const; private: void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group); @@ -411,21 +437,22 @@ public: // Processes parcel label and triggers notifying observers. static void processParcelInfo(const LLParcelData& parcel_data); - // Next 4 setters are used to update agent and viewer connection information + static LLVector3d getParcelPos(const LLUUID& parcel_id); + + // Next setters are used to update agent and viewer connection information // upon events like user login, viewer disconnect and user changing region host. // These setters are made public to be accessible from newview and should not be // used in other cases. - static void setAgentID(const LLUUID& id) { sAgentID = id; } static void setSessionID(const LLUUID& id) { sSessionID = id; } static void setRegionHost(const LLHost& host) { sRegionHost = host; } static void setDisconnected(bool disconnected) { sDisconnected = disconnected; } private: - static LLUUID sAgentID; static LLUUID sSessionID; static LLHost sRegionHost; static bool sDisconnected; static std::set<LLUrlEntryParcel*> sParcelInfoObservers; + static std::map<LLUUID, LLVector3d> sParcelPos; }; /// @@ -486,7 +513,7 @@ public: /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); /*virtual*/ std::string getUrl(const std::string &string) const; /*virtual*/ std::string getTooltip(const std::string &string) const; - /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const; + LLStyle::EUnderlineLink getUnderline(const std::string& string) const; }; /// @@ -510,7 +537,7 @@ public: LLUrlEntryNoLink(); /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); /*virtual*/ std::string getUrl(const std::string &string) const; - /*virtual*/ LLStyle::Params getStyle() const; + /*virtual*/ LLStyle::Params getStyle(const std::string &url) const; }; /// diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp index bfa3b167b1..f093934ca9 100644 --- a/indra/llui/llurlmatch.cpp +++ b/indra/llui/llurlmatch.cpp @@ -37,8 +37,9 @@ LLUrlMatch::LLUrlMatch() : mIcon(""), mMenuName(""), mLocation(""), - mUnderlineOnHoverOnly(false), - mTrusted(false) + mUnderline(e_underline::UNDERLINE_ALWAYS), + mTrusted(false), + mSkipProfileIcon(false) { } @@ -46,7 +47,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url, const std const std::string& query, const std::string &tooltip, const std::string &icon, const LLStyle::Params& style, const std::string &menu, const std::string &location, - const LLUUID& id, bool underline_on_hover_only, bool trusted) + const LLUUID& id, e_underline underline, bool trusted, bool skip_icon) { mStart = start; mEnd = end; @@ -60,6 +61,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url, const std mMenuName = menu; mLocation = location; mID = id; - mUnderlineOnHoverOnly = underline_on_hover_only; + mUnderline = underline; mTrusted = trusted; + mSkipProfileIcon = skip_icon; } diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h index ba822fbda6..418a21f963 100644 --- a/indra/llui/llurlmatch.h +++ b/indra/llui/llurlmatch.h @@ -31,7 +31,6 @@ //#include "linden_common.h" #include <string> -#include <vector> #include "llstyle.h" /// @@ -80,18 +79,20 @@ public: /// return the SL location that this Url describes, or "" if none. std::string getLocation() const { return mLocation; } - /// Should this link text be underlined only when mouse is hovered over it? - bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; } + typedef LLStyle::EUnderlineLink e_underline; + e_underline getUnderline() const { return mUnderline; } /// Return true if Url is trusted. bool isTrusted() const { return mTrusted; } + bool getSkipProfileIcon() const { return mSkipProfileIcon; } + /// Change the contents of this match object (used by LLUrlRegistry) void setValues(U32 start, U32 end, const std::string &url, const std::string &label, const std::string& query, const std::string &tooltip, const std::string &icon, const LLStyle::Params& style, const std::string &menu, const std::string &location, const LLUUID& id, - bool underline_on_hover_only = false, bool trusted = false); + e_underline underline = e_underline::UNDERLINE_ALWAYS, bool trusted = false, bool skip_icon = false); const LLUUID& getID() const { return mID; } private: @@ -106,8 +107,9 @@ private: std::string mLocation; LLUUID mID; LLStyle::Params mStyle; - bool mUnderlineOnHoverOnly; + e_underline mUnderline; bool mTrusted; + bool mSkipProfileIcon; }; #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index cec1ddfc57..cb101d325d 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -62,6 +62,8 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(new LLUrlEntryAgentUserName()); // LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since // LLUrlEntryAgent is a less specific (catchall for agent urls) + mUrlEntryAgentMention = new LLUrlEntryAgentMention(); + registerUrl(mUrlEntryAgentMention); registerUrl(new LLUrlEntryAgent()); registerUrl(new LLUrlEntryChat()); registerUrl(new LLUrlEntryGroup()); @@ -155,7 +157,7 @@ static bool stringHasUrl(const std::string &text) text.find("@") != std::string::npos); } -bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted) +bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted, bool skip_non_mentions) { // avoid costly regexes if there is clearly no URL in the text if (! stringHasUrl(text)) @@ -176,6 +178,11 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL continue; } + if (skip_non_mentions && (mUrlEntryAgentMention != *it)) + { + continue; + } + LLUrlEntryBase *url_entry = *it; U32 start = 0, end = 0; @@ -233,12 +240,13 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL match_entry->getQuery(url), match_entry->getTooltip(url), match_entry->getIcon(url), - match_entry->getStyle(), + match_entry->getStyle(url), match_entry->getMenuName(), match_entry->getLocation(url), match_entry->getID(url), - match_entry->underlineOnHoverOnly(url), - match_entry->isTrusted()); + match_entry->getUnderline(url), + match_entry->isTrusted(), + match_entry->getSkipProfileIcon(url)); return true; } @@ -274,7 +282,9 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr match.getMenuName(), match.getLocation(), match.getID(), - match.underlineOnHoverOnly()); + match.getUnderline(), + false, + match.getSkipProfileIcon()); return true; } return false; @@ -317,3 +327,30 @@ void LLUrlRegistry::setKeybindingHandler(LLKeyBindingToStringHandler* handler) LLUrlEntryKeybinding *entry = (LLUrlEntryKeybinding*)mUrlEntryKeybinding; entry->setHandler(handler); } + +bool LLUrlRegistry::containsAgentMention(const std::string& text) +{ + // avoid costly regexes if there is clearly no URL in the text + if (!stringHasUrl(text)) + { + return false; + } + + try + { + boost::sregex_iterator it(text.begin(), text.end(), mUrlEntryAgentMention->getPattern()); + boost::sregex_iterator end; + for (; it != end; ++it) + { + if (mUrlEntryAgentMention->isAgentID(it->str())) + { + return true; + } + } + } + catch (boost::regex_error&) + { + LL_INFOS() << "Regex error for: " << text << LL_ENDL; + } + return false; +} diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 64cfec3960..592e422487 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -34,7 +34,6 @@ #include "llstring.h" #include <string> -#include <vector> class LLKeyBindingToStringHandler; @@ -76,7 +75,7 @@ public: /// your callback is invoked if the matched Url's label changes in the future bool findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback, - bool is_content_trusted = false); + bool is_content_trusted = false, bool skip_non_mentions = false); /// a slightly less efficient version of findUrl for wide strings bool findUrl(const LLWString &text, LLUrlMatch &match, @@ -93,6 +92,8 @@ public: // Set handler for url registry to be capable of parsing and populating keybindings void setKeybindingHandler(LLKeyBindingToStringHandler* handler); + bool containsAgentMention(const std::string& text); + private: std::vector<LLUrlEntryBase *> mUrlEntry; LLUrlEntryBase* mUrlEntryTrusted; @@ -102,6 +103,7 @@ private: LLUrlEntryBase* mUrlEntrySLLabel; LLUrlEntryBase* mUrlEntryNoLink; LLUrlEntryBase* mUrlEntryKeybinding; + LLUrlEntryBase* mUrlEntryAgentMention; }; #endif diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 710ec3d05e..d747ef9555 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -48,23 +48,22 @@ #include "lltreeiterators.h" #include "llfocusmgr.h" +#include <functional> #include <list> -#include <boost/function.hpp> -#include <boost/noncopyable.hpp> class LLSD; -const U32 FOLLOWS_NONE = 0x00; -const U32 FOLLOWS_LEFT = 0x01; -const U32 FOLLOWS_RIGHT = 0x02; -const U32 FOLLOWS_TOP = 0x10; -const U32 FOLLOWS_BOTTOM = 0x20; -const U32 FOLLOWS_ALL = 0x33; +constexpr U32 FOLLOWS_NONE = 0x00; +constexpr U32 FOLLOWS_LEFT = 0x01; +constexpr U32 FOLLOWS_RIGHT = 0x02; +constexpr U32 FOLLOWS_TOP = 0x10; +constexpr U32 FOLLOWS_BOTTOM = 0x20; +constexpr U32 FOLLOWS_ALL = 0x33; -const bool MOUSE_OPAQUE = true; -const bool NOT_MOUSE_OPAQUE = false; +constexpr bool MOUSE_OPAQUE = true; +constexpr bool NOT_MOUSE_OPAQUE = false; -const U32 GL_NAME_UI_RESERVED = 2; +constexpr U32 GL_NAME_UI_RESERVED = 2; // maintains render state during traversal of UI tree @@ -241,7 +240,7 @@ public: void setUseBoundingRect( bool use_bounding_rect ); bool getUseBoundingRect() const; - ECursorType getHoverCursor() { return mHoverCursor; } + ECursorType getHoverCursor() const { return mHoverCursor; } static F32 getTooltipTimeout(); virtual const std::string getToolTip() const; @@ -265,7 +264,7 @@ public: void setDefaultTabGroup(S32 d) { mDefaultTabGroup = d; } S32 getDefaultTabGroup() const { return mDefaultTabGroup; } - S32 getLastTabGroup() { return mLastTabGroup; } + S32 getLastTabGroup() const { return mLastTabGroup; } bool isInVisibleChain() const; bool isInEnabledChain() const; @@ -627,7 +626,7 @@ private: LLView& getDefaultWidgetContainer() const; // This allows special mouse-event targeting logic for testing. - typedef boost::function<bool(const LLView*, S32 x, S32 y)> DrilldownFunc; + typedef std::function<bool(const LLView*, S32 x, S32 y)> DrilldownFunc; static DrilldownFunc sDrilldown; public: @@ -637,7 +636,7 @@ public: // LLView::TemporaryDrilldownFunc scoped_func(myfunctor); // // ... test with myfunctor ... // } // exiting block restores original LLView::sDrilldown - class TemporaryDrilldownFunc: public boost::noncopyable + class TemporaryDrilldownFunc { public: TemporaryDrilldownFunc(const DrilldownFunc& func): @@ -651,6 +650,10 @@ public: sDrilldown = mOldDrilldown; } + // Non-copyable + TemporaryDrilldownFunc(const TemporaryDrilldownFunc&) = delete; + TemporaryDrilldownFunc& operator=(const TemporaryDrilldownFunc&) = delete; + private: DrilldownFunc mOldDrilldown; }; diff --git a/indra/llui/llviewborder.h b/indra/llui/llviewborder.h index 1f118a0d20..a4bb748b77 100644 --- a/indra/llui/llviewborder.h +++ b/indra/llui/llviewborder.h @@ -92,7 +92,6 @@ public: private: void drawOnePixelLines(); void drawTwoPixelLines(); - void drawTextures(); EBevel mBevel; EStyle mStyle; diff --git a/indra/llui/llviewereventrecorder.cpp b/indra/llui/llviewereventrecorder.cpp index 6d907d7e45..9eefba1390 100644 --- a/indra/llui/llviewereventrecorder.cpp +++ b/indra/llui/llviewereventrecorder.cpp @@ -34,8 +34,6 @@ LLViewerEventRecorder::LLViewerEventRecorder() { logEvents = false; // Remove any previous event log file std::string old_log_ui_events_to_llsd_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.old"); - LLFile::remove(old_log_ui_events_to_llsd_file, ENOENT); - mLogFilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.llsd"); LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file, ENOENT); diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h index 9e752e8090..5636c068d8 100644 --- a/indra/llui/llviewereventrecorder.h +++ b/indra/llui/llviewereventrecorder.h @@ -61,7 +61,7 @@ public: std::string get_xui(); void update_xui(std::string xui); - bool getLoggingStatus(){return logEvents;}; + bool getLoggingStatus() const { return logEvents; } void setEventLoggingOn(); void setEventLoggingOff(); diff --git a/indra/llui/llvirtualtrackball.h b/indra/llui/llvirtualtrackball.h index 61a78b2398..fbfda04585 100644 --- a/indra/llui/llvirtualtrackball.h +++ b/indra/llui/llvirtualtrackball.h @@ -78,20 +78,20 @@ public: }; - virtual ~LLVirtualTrackball(); - /*virtual*/ bool postBuild(); + ~LLVirtualTrackball() override; + bool postBuild() override; - virtual bool handleHover(S32 x, S32 y, MASK mask); - virtual bool handleMouseUp(S32 x, S32 y, MASK mask); - virtual bool handleMouseDown(S32 x, S32 y, MASK mask); - virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual bool handleKeyHere(KEY key, MASK mask); + bool handleHover(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleRightMouseDown(S32 x, S32 y, MASK mask) override; + bool handleKeyHere(KEY key, MASK mask) override; - virtual void draw(); + void draw() override; - virtual void setValue(const LLSD& value); - void setValue(F32 x, F32 y, F32 z, F32 w); - virtual LLSD getValue() const; + void setValue(const LLSD& value) override; + void setValue(F32 x, F32 y, F32 z, F32 w); + LLSD getValue() const override; void setRotation(const LLQuaternion &value); LLQuaternion getRotation() const; @@ -102,7 +102,6 @@ public: protected: friend class LLUICtrlFactory; LLVirtualTrackball(const Params&); - void onEditChange(); protected: LLTextBox* mNLabel; diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h index da29188943..ee230cd2f6 100644 --- a/indra/llui/llwindowshade.h +++ b/indra/llui/llwindowshade.h @@ -49,7 +49,7 @@ public: }; void show(LLNotificationPtr); - /*virtual*/ void draw(); + void draw() override; void hide(); bool isShown() const; diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp index 8fd85a89a1..8cd11b86b3 100644 --- a/indra/llui/llxuiparser.cpp +++ b/indra/llui/llxuiparser.cpp @@ -30,7 +30,7 @@ #include "llxmlnode.h" #include "llfasttimer.h" -#ifdef LL_USESYSTEMLIBS +#if 1 #include <expat.h> #else #include "expat/expat.h" diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h index f755c12cbf..2179ae54d3 100644 --- a/indra/llui/llxuiparser.h +++ b/indra/llui/llxuiparser.h @@ -31,7 +31,7 @@ #include "llregistry.h" #include "llxmlnode.h" -#include <boost/function.hpp> +#include <functional> #include <iosfwd> #include <stack> #include <set> @@ -47,7 +47,7 @@ class LLWidgetTypeRegistry // global static instance for registering all widget types -typedef boost::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)> LLWidgetCreatorFunc; +typedef std::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)> LLWidgetCreatorFunc; typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t; diff --git a/indra/llui/llxyvector.h b/indra/llui/llxyvector.h index bc41213c13..646771f387 100644 --- a/indra/llui/llxyvector.h +++ b/indra/llui/llxyvector.h @@ -65,18 +65,18 @@ public: }; - virtual ~LLXYVector(); - /*virtual*/ bool postBuild(); + ~LLXYVector() override; + bool postBuild() override; - virtual bool handleHover(S32 x, S32 y, MASK mask); - virtual bool handleMouseUp(S32 x, S32 y, MASK mask); - virtual bool handleMouseDown(S32 x, S32 y, MASK mask); + bool handleHover(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; - virtual void draw(); + void draw() override; - virtual void setValue(const LLSD& value); - void setValue(F32 x, F32 y); - virtual LLSD getValue() const; + void setValue(const LLSD& value) override; + void setValue(F32 x, F32 y); + LLSD getValue() const override; protected: friend class LLUICtrlFactory; |
