summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreyL ProductEngine <alihatskiy@productengine.com>2019-01-03 22:59:49 +0200
committerAndreyL ProductEngine <alihatskiy@productengine.com>2019-01-03 22:59:49 +0200
commit09b750483a2cde7ea3c80a0238f3224a2cf1cb70 (patch)
tree5f9b38b93f916c820cf9308ed689701790b3eef5
parentab428e194eaa144e8dcecc353c3c7ed83d6cee3e (diff)
SL-10293 Firestorm PR: preferences and menu search
-rwxr-xr-xdoc/contributions.txt1
-rw-r--r--indra/llui/CMakeLists.txt1
-rw-r--r--indra/llui/llbutton.cpp4
-rw-r--r--indra/llui/llbutton.h7
-rw-r--r--indra/llui/llcheckboxctrl.h13
-rw-r--r--indra/llui/llmenugl.cpp4
-rw-r--r--indra/llui/llmenugl.h9
-rw-r--r--indra/llui/llsearchablecontrol.h71
-rw-r--r--indra/llui/llsliderctrl.h15
-rw-r--r--indra/llui/lltabcontainer.cpp50
-rw-r--r--indra/llui/lltabcontainer.h2
-rw-r--r--indra/llui/lltextbase.cpp11
-rw-r--r--indra/llui/lltextbase.h8
-rw-r--r--indra/llui/lluictrl.h1
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llfloaterpreference.cpp121
-rw-r--r--indra/newview/llfloaterpreference.h15
-rw-r--r--indra/newview/llsearchableui.cpp154
-rw-r--r--indra/newview/llsearchableui.h121
-rw-r--r--indra/newview/llstatusbar.cpp92
-rw-r--r--indra/newview/llstatusbar.h17
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences.xml42
-rw-r--r--indra/newview/skins/default/xui/en/panel_status_bar.xml40
23 files changed, 789 insertions, 12 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt
index bb910aa838..66323a38c6 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -1070,6 +1070,7 @@ Nicky Dasmijn
STORM-2010
STORM-2082
MAINT-6665
+ SL-10293
Nicky Perian
OPEN-1
STORM-1087
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 8054eb3619..e44f57fa9f 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -200,6 +200,7 @@ set(llui_HEADER_FILES
llresizehandle.h
llresmgr.h
llrngwriter.h
+ llsearchablecontrol.h
llsearcheditor.h
llscrollbar.h
llscrollcontainer.h
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 510a2537b9..6b7a8a8b86 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -769,6 +769,10 @@ void LLButton::draw()
}
}
+ // Highlight if needed
+ if( ll::ui::SearchableControl::getHighlighted() )
+ label_color = ll::ui::SearchableControl::getHighlightColor();
+
// Unselected label assignments
LLWString label = getCurrentLabel();
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 7b4719866d..7629ed1fea 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -62,6 +62,7 @@ class LLUICtrlFactory;
class LLButton
: public LLUICtrl, public LLBadgeOwner
+, public ll::ui::SearchableControl
{
public:
struct Params
@@ -380,6 +381,12 @@ protected:
LLFlashTimer * mFlashingTimer;
bool mForceFlashing; // Stick flashing color even if button is pressed
bool mHandleRightMouse;
+
+protected:
+ virtual std::string _getSearchText() const
+ {
+ return getLabelUnselected() + getToolTip();
+ }
};
// Build time optimization, generate once in .cpp file
diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h
index 71bdc32e66..07ae9c3b18 100644
--- a/indra/llui/llcheckboxctrl.h
+++ b/indra/llui/llcheckboxctrl.h
@@ -47,6 +47,7 @@ class LLViewBorder;
class LLCheckBoxCtrl
: public LLUICtrl
+, public ll::ui::SearchableControl
{
public:
struct Params
@@ -109,6 +110,18 @@ public:
virtual void resetDirty(); // Clear dirty state
protected:
+ virtual std::string _getSearchText() const
+ {
+ return getLabel() + getToolTip();
+ }
+
+ virtual void onSetHighlight() const // When highlight, really do highlight the label
+ {
+ if( mLabel )
+ mLabel->ll::ui::SearchableControl::setHighlighted( ll::ui::SearchableControl::getHighlighted() );
+ }
+
+protected:
// note: value is stored in toggle state of button
LLButton* mButton;
LLTextBox* mLabel;
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 0d42f726fa..92543b952e 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -504,6 +504,10 @@ void LLMenuItemGL::draw( void )
color = mDisabledColor.get();
}
+ // Highlight if needed
+ if( ll::ui::SearchableControl::getHighlighted() )
+ color = ll::ui::SearchableControl::getHighlightColor();
+
// Draw the text on top.
if (mBriefItem)
{
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 69f7d21513..78f688642e 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -48,7 +48,7 @@ extern S32 MENU_BAR_WIDTH;
// The LLMenuItemGL represents a single menu item in a menu.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLMenuItemGL : public LLUICtrl
+class LLMenuItemGL: public LLUICtrl, public ll::ui::SearchableControl
{
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
@@ -175,7 +175,12 @@ protected:
// This function appends the character string representation of
// the current accelerator key and mask to the provided string.
void appendAcceleratorString( std::string& st ) const;
-
+
+ virtual std::string _getSearchText() const
+ {
+ return mLabel.getString();
+ }
+
protected:
KEY mAcceleratorKey;
MASK mAcceleratorMask;
diff --git a/indra/llui/llsearchablecontrol.h b/indra/llui/llsearchablecontrol.h
new file mode 100644
index 0000000000..f7f1ffa0a5
--- /dev/null
+++ b/indra/llui/llsearchablecontrol.h
@@ -0,0 +1,71 @@
+/**
+* @file llsearchablecontrol.h
+*
+* $LicenseInfo:firstyear=2019&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2019, 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$
+*/
+
+#ifndef LL_SEARCHABLE_CONTROL_H
+#define LL_SEARCHABLE_CONTROL_H
+
+#include "lluicolortable.h"
+#include "lluicolor.h"
+
+namespace ll
+{
+ namespace ui
+ {
+ class SearchableControl
+ {
+ mutable bool mIsHighlighed;
+ public:
+ SearchableControl()
+ : mIsHighlighed( false )
+ { }
+ virtual ~SearchableControl()
+ { }
+
+ LLColor4 getHighlightColor( ) const
+ {
+ static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red);
+ return highlight_color.get();
+ }
+
+ void setHighlighted( bool aVal ) const
+ {
+ mIsHighlighed = aVal;
+ onSetHighlight( );
+ }
+ bool getHighlighted( ) const
+ { return mIsHighlighed; }
+
+ std::string getSearchText() const
+ { return _getSearchText(); }
+ protected:
+ virtual std::string _getSearchText() const = 0;
+ virtual void onSetHighlight( ) const
+ { }
+ };
+ }
+}
+
+
+#endif
diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h
index 67cca9ef04..2bb8668b90 100644
--- a/indra/llui/llsliderctrl.h
+++ b/indra/llui/llsliderctrl.h
@@ -35,7 +35,7 @@
#include "lllineeditor.h"
-class LLSliderCtrl : public LLF32UICtrl
+class LLSliderCtrl: public LLF32UICtrl, public ll::ui::SearchableControl
{
public:
struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params>
@@ -131,6 +131,19 @@ public:
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
+protected:
+ virtual std::string _getSearchText() const
+ {
+ std::string strLabel;
+ if( mLabelBox )
+ strLabel = mLabelBox->getLabel();
+ return strLabel + getToolTip();
+ }
+ virtual void onSetHighlight() const // When highlight, really do highlight the label
+ {
+ if( mLabelBox )
+ mLabelBox->ll::ui::SearchableControl::setHighlighted( ll::ui::SearchableControl::getHighlighted() );
+ }
private:
void updateText();
void reportInvalidData();
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 1b2f09cff5..9c8636f936 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -76,7 +76,8 @@ public:
mButton(b),
mOldState(FALSE),
mPlaceholderText(placeholder),
- mPadding(0)
+ mPadding(0),
+ mVisible(true)
{}
LLTabContainer* mTabContainer;
@@ -85,6 +86,8 @@ public:
BOOL mOldState;
LLTextBox* mPlaceholderText;
S32 mPadding;
+
+ mutable bool mVisible;
};
//----------------------------------------------------------------------------
@@ -398,7 +401,10 @@ void LLTabContainer::draw()
{
break;
}
- target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
+
+ if( (*iter)->mVisible )
+ target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
+
cur_scroll_pos--;
}
@@ -467,6 +473,12 @@ void LLTabContainer::draw()
{
LLTabTuple* tuple = *iter;
+ if( !tuple->mVisible )
+ {
+ tuple->mButton->setVisible( false );
+ continue;
+ }
+
tuple->mButton->translate( left ? left - tuple->mButton->getRect().mLeft : 0,
top ? top - tuple->mButton->getRect().mTop : 0 );
if (top) top -= BTN_HEIGHT + tabcntrv_pad;
@@ -1505,7 +1517,7 @@ BOOL LLTabContainer::setTab(S32 which)
}
BOOL is_visible = FALSE;
- if (selected_tuple->mButton->getEnabled())
+ if( selected_tuple->mButton->getEnabled() && selected_tuple->mVisible )
{
setCurrentPanelIndex(which);
@@ -2121,3 +2133,35 @@ S32 LLTabContainer::getTotalTabWidth() const
{
return mTotalTabWidth;
}
+
+void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible )
+{
+ for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr )
+ {
+ LLTabTuple const *pTT = *itr;
+ if( pTT->mTabPanel == aPanel )
+ {
+ pTT->mVisible = aVisible;
+ break;
+ }
+ }
+
+ bool foundTab( false );
+ for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr )
+ {
+ LLTabTuple const *pTT = *itr;
+ if( pTT->mVisible )
+ {
+ this->selectTab( itr - mTabList.begin() );
+ foundTab = true;
+ break;
+ }
+ }
+
+ if( foundTab )
+ this->setVisible( TRUE );
+ else
+ this->setVisible( FALSE );
+
+ updateMaxScrollPos();
+}
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 4a5f08f5d3..6bf963313c 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -216,6 +216,8 @@ public:
S32 getMinTabWidth() const { return mMinTabWidth; }
S32 getMaxTabWidth() const { return mMaxTabWidth; }
+ void setTabVisibility( LLPanel const *aPanel, bool );
+
void startDragAndDropDelayTimer() { mDragAndDropDelayTimer.start(); }
void onTabBtn( const LLSD& data, LLPanel* panel );
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index c570285856..a23741b6dd 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1222,6 +1222,17 @@ void LLTextBase::draw()
gl_rect_2d(text_rect, bg_color % alpha, TRUE);
}
+ // Draw highlighted if needed
+ if( ll::ui::SearchableControl::getHighlighted() )
+ {
+ LLColor4 bg_color = ll::ui::SearchableControl::getHighlightColor();
+ LLRect bg_rect = mVisibleTextRect;
+ if( mScroller )
+ bg_rect.intersectWith( text_rect );
+
+ gl_rect_2d( text_rect, bg_color, TRUE );
+ }
+
bool should_clip = mClip || mScroller != NULL;
{ LLLocalClipRect clip(text_rect, should_clip);
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 5fdde445ef..9831c35858 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -275,7 +275,8 @@ typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
class LLTextBase
: public LLUICtrl,
protected LLEditMenuHandler,
- public LLSpellCheckMenuHandler
+ public LLSpellCheckMenuHandler,
+ public ll::ui::SearchableControl
{
public:
friend class LLTextSegment;
@@ -617,6 +618,11 @@ protected:
void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);
S32 normalizeUri(std::string& uri);
+protected:
+ virtual std::string _getSearchText() const
+ {
+ return mLabel.getString() + getToolTip();
+ }
protected:
// text segmentation and flow
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 550bee5c70..63baed6793 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -37,6 +37,7 @@
#include "llinitparam.h"
#include "llview.h"
#include "llviewmodel.h" // *TODO move dependency to .cpp file
+#include "llsearchablecontrol.h"
const BOOL TAKE_FOCUS_YES = TRUE;
const BOOL TAKE_FOCUS_NO = FALSE;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 33886acb71..a8019ee168 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -532,6 +532,7 @@ set(viewer_SOURCE_FILES
llscrollingpanelparam.cpp
llscrollingpanelparambase.cpp
llsculptidsize.cpp
+ llsearchableui.cpp
llsearchcombobox.cpp
llsearchhistory.cpp
llsecapi.cpp
@@ -1148,6 +1149,7 @@ set(viewer_HEADER_FILES
llscrollingpanelparam.h
llscrollingpanelparambase.h
llsculptidsize.h
+ llsearchableui.h
llsearchcombobox.h
llsearchhistory.h
llsecapi.h
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index ac751a785d..c3dea73c05 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -117,6 +117,8 @@
#include "llfeaturemanager.h"
#include "llviewertexturelist.h"
+#include "llsearchableui.h"
+
const F32 BANDWIDTH_UPDATER_TIMEOUT = 0.5f;
char const* const VISIBILITY_DEFAULT = "default";
char const* const VISIBILITY_HIDDEN = "hidden";
@@ -393,6 +395,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance()));
mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
+ mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // <FS:ND/> Hook up for filtering
}
void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type )
@@ -506,7 +509,10 @@ BOOL LLFloaterPreference::postBuild()
LLSliderCtrl* fov_slider = getChild<LLSliderCtrl>("camera_fov");
fov_slider->setMinValue(LLViewerCamera::getInstance()->getMinView());
fov_slider->setMaxValue(LLViewerCamera::getInstance()->getMaxView());
-
+
+ // Hook up and init for filtering
+ mFilterEdit = getChild<LLSearchEditor>("search_prefs_edit");
+ mFilterEdit->setKeystrokeCallback(boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false));
return TRUE;
}
@@ -786,6 +792,13 @@ void LLFloaterPreference::onOpen(const LLSD& key)
save_btn->setEnabled(started);
delete_btn->setEnabled(started);
exceptions_btn->setEnabled(started);
+
+ collectSearchableItems();
+ if (!mFilterEdit->getText().empty())
+ {
+ mFilterEdit->setText(LLStringExplicit(""));
+ onUpdateFilterTerm(true);
+ }
}
void LLFloaterPreference::onVertexShaderEnable()
@@ -2985,3 +2998,109 @@ void LLFloaterPreferenceProxy::onChangeSocksSettings()
}
+void LLFloaterPreference::onUpdateFilterTerm(bool force)
+{
+ LLWString seachValue = utf8str_to_wstring( mFilterEdit->getValue() );
+ LLWStringUtil::toLower( seachValue );
+
+ if( !mSearchData || (mSearchData->mLastFilter == seachValue && !force))
+ return;
+
+ mSearchData->mLastFilter = seachValue;
+
+ if( !mSearchData->mRootTab )
+ return;
+
+ mSearchData->mRootTab->hightlightAndHide( seachValue );
+ LLTabContainer *pRoot = getChild< LLTabContainer >( "pref core" );
+ if( pRoot )
+ pRoot->selectFirstTab();
+}
+
+void collectChildren( LLView const *aView, ll::prefs::PanelDataPtr aParentPanel, ll::prefs::TabContainerDataPtr aParentTabContainer )
+{
+ if( !aView )
+ return;
+
+ llassert_always( aParentPanel || aParentTabContainer );
+
+ LLView::child_list_const_iter_t itr = aView->beginChild();
+ LLView::child_list_const_iter_t itrEnd = aView->endChild();
+
+ while( itr != itrEnd )
+ {
+ LLView *pView = *itr;
+ ll::prefs::PanelDataPtr pCurPanelData = aParentPanel;
+ ll::prefs::TabContainerDataPtr pCurTabContainer = aParentTabContainer;
+ if( !pView )
+ continue;
+ LLPanel const *pPanel = dynamic_cast< LLPanel const *>( pView );
+ LLTabContainer const *pTabContainer = dynamic_cast< LLTabContainer const *>( pView );
+ ll::ui::SearchableControl const *pSCtrl = dynamic_cast< ll::ui::SearchableControl const *>( pView );
+
+ if( pTabContainer )
+ {
+ pCurPanelData.reset();
+
+ pCurTabContainer = ll::prefs::TabContainerDataPtr( new ll::prefs::TabContainerData );
+ pCurTabContainer->mTabContainer = const_cast< LLTabContainer *>( pTabContainer );
+ pCurTabContainer->mLabel = pTabContainer->getLabel();
+ pCurTabContainer->mPanel = 0;
+
+ if( aParentPanel )
+ aParentPanel->mChildPanel.push_back( pCurTabContainer );
+ if( aParentTabContainer )
+ aParentTabContainer->mChildPanel.push_back( pCurTabContainer );
+ }
+ else if( pPanel )
+ {
+ pCurTabContainer.reset();
+
+ pCurPanelData = ll::prefs::PanelDataPtr( new ll::prefs::PanelData );
+ pCurPanelData->mPanel = pPanel;
+ pCurPanelData->mLabel = pPanel->getLabel();
+
+ llassert_always( aParentPanel || aParentTabContainer );
+
+ if( aParentTabContainer )
+ aParentTabContainer->mChildPanel.push_back( pCurPanelData );
+ else if( aParentPanel )
+ aParentPanel->mChildPanel.push_back( pCurPanelData );
+ }
+ else if( pSCtrl && pSCtrl->getSearchText().size() )
+ {
+ ll::prefs::SearchableItemPtr item = ll::prefs::SearchableItemPtr( new ll::prefs::SearchableItem() );
+ item->mView = pView;
+ item->mCtrl = pSCtrl;
+
+ item->mLabel = utf8str_to_wstring( pSCtrl->getSearchText() );
+ LLWStringUtil::toLower( item->mLabel );
+
+ llassert_always( aParentPanel || aParentTabContainer );
+
+ if( aParentPanel )
+ aParentPanel->mChildren.push_back( item );
+ if( aParentTabContainer )
+ aParentTabContainer->mChildren.push_back( item );
+ }
+ collectChildren( pView, pCurPanelData, pCurTabContainer );
+ ++itr;
+ }
+}
+
+void LLFloaterPreference::collectSearchableItems()
+{
+ mSearchData.reset( nullptr );
+ LLTabContainer *pRoot = getChild< LLTabContainer >( "pref core" );
+ if( mFilterEdit && pRoot )
+ {
+ mSearchData.reset(new ll::prefs::SearchData() );
+
+ ll::prefs::TabContainerDataPtr pRootTabcontainer = ll::prefs::TabContainerDataPtr( new ll::prefs::TabContainerData );
+ pRootTabcontainer->mTabContainer = pRoot;
+ pRootTabcontainer->mLabel = pRoot->getLabel();
+ mSearchData->mRootTab = pRootTabcontainer;
+
+ collectChildren( this, ll::prefs::PanelDataPtr(), pRootTabcontainer );
+ }
+}
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 4e51137df5..d609c42ebe 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -36,6 +36,7 @@
#include "llfloater.h"
#include "llavatarpropertiesprocessor.h"
#include "llconversationlog.h"
+#include "llsearcheditor.h"
class LLConversationLogObserver;
class LLPanelPreference;
@@ -47,6 +48,14 @@ class LLSliderCtrl;
class LLSD;
class LLTextBox;
+namespace ll
+{
+ namespace prefs
+ {
+ struct SearchData;
+ }
+}
+
typedef std::map<std::string, std::string> notifications_map;
typedef enum
@@ -205,6 +214,12 @@ private:
LLAvatarData mAvatarProperties;
std::string mSavedGraphicsPreset;
LOG_CLASS(LLFloaterPreference);
+
+ LLSearchEditor *mFilterEdit;
+ std::unique_ptr< ll::prefs::SearchData > mSearchData;
+
+ void onUpdateFilterTerm( bool force = false );
+ void collectSearchableItems();
};
class LLPanelPreference : public LLPanel
diff --git a/indra/newview/llsearchableui.cpp b/indra/newview/llsearchableui.cpp
new file mode 100644
index 0000000000..6058079ae4
--- /dev/null
+++ b/indra/newview/llsearchableui.cpp
@@ -0,0 +1,154 @@
+/**
+* @file llsearchableui.cpp
+*
+* $LicenseInfo:firstyear=2019&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2019, 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 "llviewerprecompiledheaders.h"
+#include "llsearchableui.h"
+
+#include "llview.h"
+#include "lltabcontainer.h"
+#include "llmenugl.h"
+
+ll::prefs::SearchableItem::~SearchableItem()
+{}
+
+void ll::prefs::SearchableItem::setNotHighlighted()
+{
+ mCtrl->setHighlighted( false );
+}
+
+bool ll::prefs::SearchableItem::hightlightAndHide( LLWString const &aFilter )
+{
+ if( mCtrl->getHighlighted() )
+ return true;
+
+ LLView const *pView = dynamic_cast< LLView const* >( mCtrl );
+ if( pView && !pView->getVisible() )
+ return false;
+
+ if( aFilter.empty() )
+ {
+ mCtrl->setHighlighted( false );
+ return true;
+ }
+
+ if( mLabel.find( aFilter ) != LLWString::npos )
+ {
+ mCtrl->setHighlighted( true );
+ return true;
+ }
+
+ return false;
+}
+
+ll::prefs::PanelData::~PanelData()
+{}
+
+bool ll::prefs::PanelData::hightlightAndHide( LLWString const &aFilter )
+{
+ for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
+ (*itr)->setNotHighlighted( );
+
+ bool bVisible(false);
+ for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
+ bVisible |= (*itr)->hightlightAndHide( aFilter );
+
+ for( tPanelDataList::iterator itr = mChildPanel.begin(); itr != mChildPanel.end(); ++itr )
+ bVisible |= (*itr)->hightlightAndHide( aFilter );
+
+ return bVisible;
+}
+
+bool ll::prefs::TabContainerData::hightlightAndHide( LLWString const &aFilter )
+{
+ for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
+ (*itr)->setNotHighlighted( );
+
+ bool bVisible(false);
+ for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
+ bVisible |= (*itr)->hightlightAndHide( aFilter );
+
+ for( tPanelDataList::iterator itr = mChildPanel.begin(); itr != mChildPanel.end(); ++itr )
+ {
+ bool bPanelVisible = (*itr)->hightlightAndHide( aFilter );
+ if( (*itr)->mPanel )
+ mTabContainer->setTabVisibility( (*itr)->mPanel, bPanelVisible );
+ bVisible |= bPanelVisible;
+ }
+
+ return bVisible;
+}
+
+ll::statusbar::SearchableItem::SearchableItem()
+ : mMenu(0)
+ , mCtrl(0)
+ , mWasHiddenBySearch( false )
+{ }
+
+void ll::statusbar::SearchableItem::setNotHighlighted( )
+{
+ for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
+ (*itr)->setNotHighlighted( );
+
+ if( mCtrl )
+ {
+ mCtrl->setHighlighted( false );
+
+ if( mWasHiddenBySearch )
+ mMenu->setVisible( TRUE );
+ }
+}
+
+bool ll::statusbar::SearchableItem::hightlightAndHide( LLWString const &aFilter )
+{
+ if( mMenu && !mMenu->getVisible() && !mWasHiddenBySearch )
+ return false;
+
+ setNotHighlighted( );
+
+ bool bVisible(false);
+ for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
+ bVisible |= (*itr)->hightlightAndHide( aFilter );
+
+ if( aFilter.empty() )
+ {
+ if( mCtrl )
+ mCtrl->setHighlighted( false );
+ return true;
+ }
+
+ if( mLabel.find( aFilter ) != LLWString::npos )
+ {
+ if( mCtrl )
+ mCtrl->setHighlighted( true );
+ return true;
+ }
+
+ if( mCtrl && !bVisible )
+ {
+ mWasHiddenBySearch = true;
+ mMenu->setVisible(FALSE);
+ }
+ return bVisible;
+}
diff --git a/indra/newview/llsearchableui.h b/indra/newview/llsearchableui.h
new file mode 100644
index 0000000000..42b2866fb6
--- /dev/null
+++ b/indra/newview/llsearchableui.h
@@ -0,0 +1,121 @@
+/**
+* @file llsearchableui.h
+*
+* $LicenseInfo:firstyear=2019&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2019, 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$
+*/
+
+#ifndef LL_SEARCHABLE_UI_H
+#define LL_SEARCHABLE_UI_H
+
+class LLMenuItemGL;
+class LLView;
+class LLPanel;
+class LLTabContainer;
+
+#include "llsearchablecontrol.h"
+
+namespace ll
+{
+ namespace prefs
+ {
+ struct SearchableItem;
+ struct PanelData;
+ struct TabContainerData;
+
+ typedef boost::shared_ptr< SearchableItem > SearchableItemPtr;
+ typedef boost::shared_ptr< PanelData > PanelDataPtr;
+ typedef boost::shared_ptr< TabContainerData > TabContainerDataPtr;
+
+ typedef std::vector< TabContainerData > tTabContainerDataList;
+ typedef std::vector< SearchableItemPtr > tSearchableItemList;
+ typedef std::vector< PanelDataPtr > tPanelDataList;
+
+ struct SearchableItem
+ {
+ LLWString mLabel;
+ LLView const *mView;
+ ll::ui::SearchableControl const *mCtrl;
+
+ std::vector< boost::shared_ptr< SearchableItem > > mChildren;
+
+ virtual ~SearchableItem();
+
+ void setNotHighlighted();
+ virtual bool hightlightAndHide( LLWString const &aFilter );
+ };
+
+ struct PanelData
+ {
+ LLPanel const *mPanel;
+ std::string mLabel;
+
+ std::vector< boost::shared_ptr< SearchableItem > > mChildren;
+ std::vector< boost::shared_ptr< PanelData > > mChildPanel;
+
+ virtual ~PanelData();
+
+ virtual bool hightlightAndHide( LLWString const &aFilter );
+ };
+
+ struct TabContainerData: public PanelData
+ {
+ LLTabContainer *mTabContainer;
+ virtual bool hightlightAndHide( LLWString const &aFilter );
+ };
+
+ struct SearchData
+ {
+ TabContainerDataPtr mRootTab;
+ LLWString mLastFilter;
+ };
+ }
+ namespace statusbar
+ {
+ struct SearchableItem;
+
+ typedef boost::shared_ptr< SearchableItem > SearchableItemPtr;
+
+ typedef std::vector< SearchableItemPtr > tSearchableItemList;
+
+ struct SearchableItem
+ {
+ LLWString mLabel;
+ LLMenuItemGL *mMenu;
+ tSearchableItemList mChildren;
+ ll::ui::SearchableControl const *mCtrl;
+ bool mWasHiddenBySearch;
+
+ SearchableItem();
+
+ void setNotHighlighted( );
+ bool hightlightAndHide( LLWString const &aFilter );
+ };
+
+ struct SearchData
+ {
+ SearchableItemPtr mRootMenu;
+ LLWString mLastFilter;
+ };
+ }
+}
+
+#endif
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index 43c0fbd53a..b893e4a058 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -81,6 +81,8 @@
#include "llparcel.h"
#include "llstring.h"
#include "message.h"
+#include "llsearchableui.h"
+#include "llsearcheditor.h"
// system includes
#include <iomanip>
@@ -113,7 +115,9 @@ LLStatusBar::LLStatusBar(const LLRect& rect)
mBalance(0),
mHealth(100),
mSquareMetersCredit(0),
- mSquareMetersCommitted(0)
+ mSquareMetersCommitted(0),
+ mFilterEdit(NULL), // Edit for filtering
+ mSearchPanel(NULL) // Panel for filtering
{
setRect(rect);
@@ -239,6 +243,16 @@ BOOL LLStatusBar::postBuild()
mPanelNearByMedia->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
mPanelNearByMedia->setVisible(FALSE);
+ // Hook up and init for filtering
+ mFilterEdit = getChild<LLSearchEditor>( "search_menu_edit" );
+ mSearchPanel = getChild<LLPanel>( "menu_search_panel" );
+
+ //mSearchPanel->setVisible(gSavedSettings.getBOOL("MenuSearch"));
+ mFilterEdit->setKeystrokeCallback(boost::bind(&LLStatusBar::onUpdateFilterTerm, this));
+ mFilterEdit->setCommitCallback(boost::bind(&LLStatusBar::onUpdateFilterTerm, this));
+ collectSearchableItems();
+ //gSavedSettings.getControl("MenuSearch")->getCommitSignal()->connect(boost::bind(&LLStatusBar::updateMenuSearchVisibility, this, _2));
+
return TRUE;
}
@@ -318,6 +332,7 @@ void LLStatusBar::setVisibleForMouselook(bool visible)
mMediaToggle->setVisible(visible);
mSGBandwidth->setVisible(visible);
mSGPacketLoss->setVisible(visible);
+ mSearchPanel->setVisible(visible && gSavedSettings.getBOOL("MenuSearch"));
setBackgroundVisible(visible);
mIconPresets->setVisible(visible);
}
@@ -358,6 +373,12 @@ void LLStatusBar::setBalance(S32 balance)
balance_bg_view->setShape(balance_bg_rect);
}
+ // If the search panel is shown, move this according to the new balance width. Parcel text will reshape itself in setParcelInfoText
+ if (mSearchPanel && mSearchPanel->getVisible())
+ {
+ updateMenuSearchPosition();
+ }
+
if (mBalance && (fabs((F32)(mBalance - balance)) > gSavedSettings.getF32("UISndMoneyChangeThreshold")))
{
if (mBalance > balance)
@@ -570,6 +591,75 @@ void LLStatusBar::onVolumeChanged(const LLSD& newvalue)
refresh();
}
+void LLStatusBar::onUpdateFilterTerm()
+{
+ LLWString searchValue = utf8str_to_wstring( mFilterEdit->getValue() );
+ LLWStringUtil::toLower( searchValue );
+
+ if( !mSearchData || mSearchData->mLastFilter == searchValue )
+ return;
+
+ mSearchData->mLastFilter = searchValue;
+
+ mSearchData->mRootMenu->hightlightAndHide( searchValue );
+ gMenuBarView->needsArrange();
+}
+
+void collectChildren( LLMenuGL *aMenu, ll::statusbar::SearchableItemPtr aParentMenu )
+{
+ for( U32 i = 0; i < aMenu->getItemCount(); ++i )
+ {
+ LLMenuItemGL *pMenu = aMenu->getItem( i );
+
+ ll::statusbar::SearchableItemPtr pItem( new ll::statusbar::SearchableItem );
+ pItem->mCtrl = pMenu;
+ pItem->mMenu = pMenu;
+ pItem->mLabel = utf8str_to_wstring( pMenu->ll::ui::SearchableControl::getSearchText() );
+ LLWStringUtil::toLower( pItem->mLabel );
+ aParentMenu->mChildren.push_back( pItem );
+
+ LLMenuItemBranchGL *pBranch = dynamic_cast< LLMenuItemBranchGL* >( pMenu );
+ if( pBranch )
+ collectChildren( pBranch->getBranch(), pItem );
+ }
+
+}
+
+void LLStatusBar::collectSearchableItems()
+{
+ mSearchData.reset( new ll::statusbar::SearchData );
+ ll::statusbar::SearchableItemPtr pItem( new ll::statusbar::SearchableItem );
+ mSearchData->mRootMenu = pItem;
+ collectChildren( gMenuBarView, pItem );
+}
+
+void LLStatusBar::updateMenuSearchVisibility(const LLSD& data)
+{
+ bool visible = data.asBoolean();
+ mSearchPanel->setVisible(visible);
+ if (!visible)
+ {
+ mFilterEdit->setText(LLStringUtil::null);
+ onUpdateFilterTerm();
+ }
+ else
+ {
+ updateMenuSearchPosition();
+ }
+}
+
+void LLStatusBar::updateMenuSearchPosition()
+{
+ const S32 HPAD = 12;
+ LLRect balanceRect = getChildView("balance_bg")->getRect();
+ LLRect searchRect = mSearchPanel->getRect();
+ S32 w = searchRect.getWidth();
+ searchRect.mLeft = balanceRect.mLeft - w - HPAD;
+ searchRect.mRight = searchRect.mLeft + w;
+ mSearchPanel->setShape( searchRect );
+}
+
+
// Implements secondlife:///app/balance/request to request a L$ balance
// update via UDP message system. JC
class LLBalanceHandler : public LLCommandHandler
diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h
index a3326e752a..403d590aca 100644
--- a/indra/newview/llstatusbar.h
+++ b/indra/newview/llstatusbar.h
@@ -45,7 +45,15 @@ class LLPanelPresetsPulldown;
class LLPanelVolumePulldown;
class LLPanelNearByMedia;
class LLIconCtrl;
+class LLSearchEditor;
+namespace ll
+{
+ namespace statusbar
+ {
+ struct SearchData;
+ }
+}
class LLStatusBar
: public LLPanel
{
@@ -99,6 +107,15 @@ private:
static void onClickMediaToggle(void* data);
static void onClickBalance(void* data);
+ LLSearchEditor *mFilterEdit;
+ LLPanel *mSearchPanel;
+ void onUpdateFilterTerm();
+
+ std::unique_ptr< ll::statusbar::SearchData > mSearchData;
+ void collectSearchableItems();
+ void updateMenuSearchVisibility( const LLSD& data );
+ void updateMenuSearchPosition();
+
private:
LLTextBox *mTextTime;
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 845c1efe4d..0e62d50072 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -3,7 +3,7 @@
legacy_header_height="18"
positioning="centered"
default_tab_group="1"
- height="512"
+ height="530"
layout="topleft"
name="Preferences"
help_topic="preferences"
@@ -25,7 +25,7 @@ https://accounts.secondlife.com/change_email/
layout="topleft"
right="-105"
name="OK"
- top="473"
+ top="492"
width="90">
<button.commit_callback
function="Pref.OK" />
@@ -43,6 +43,42 @@ https://accounts.secondlife.com/change_email/
<button.commit_callback
function="Pref.Cancel" />
</button>
+
+ <panel
+ name="search_panel"
+ layout="topleft"
+ follows="left|top|right"
+ left="4"
+ right="-4"
+ top="21"
+ height="18"
+ tab_group="2">
+ <search_editor
+ clear_button_visible="true"
+ follows="left|top|right"
+ height="18"
+ label="Search Settings"
+ layout="topleft"
+ left="0"
+ max_length_bytes="255"
+ name="search_prefs_edit"
+ right="-1"
+ text_pad_left="6"
+ tool_tip="Type the search term you are interested in here. Results will be displayed for partial fulltext matches within the setting's name or comment."
+ top="0">
+ <search_editor.commit_callback
+ function="UpdateFilter" />
+ <search_editor.clear_button
+ rect.height="18"
+ rect.width="18"
+ rect.bottom="-1" />
+ <search_editor.search_button
+ rect.height="12"
+ rect.width="12"
+ rect.bottom="-1" />
+ </search_editor>
+ </panel>
+
<tab_container
follows="all"
halign="left"
@@ -54,7 +90,7 @@ https://accounts.secondlife.com/change_email/
tab_position="left"
tab_width="140"
tab_padding_right="0"
- top="21"
+ top="40"
width="658">
<panel
class="panel_preference"
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index 998f1ce599..52bcce01f7 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -34,6 +34,46 @@
L$ [AMT]
</panel.string>
<panel
+ height="18"
+ left="-458"
+ top="0"
+ width="120"
+ follows="right|top"
+ name="menu_search_panel"
+ background_opaque="true"
+ background_visible="true"
+ bg_opaque_color="MouseGray">
+ <search_editor
+ clear_button_visible="true"
+ follows="left|top"
+ height="18"
+ label="Search Menus"
+ layout="topleft"
+ left="0"
+ max_length_bytes="255"
+ name="search_menu_edit"
+ right="-1"
+ text_pad_left="6"
+ tool_tip="Type the search term you are interested in here. Results will be displayed for partial fulltext matches within the menu."
+ top="0">
+ <search_button
+ top_pad="4"
+ left_pad="4"
+ width="12"
+ height="12"
+ image_unselected="Search"
+ image_selected="Search"/>
+ <clear_button
+ bottom="2"
+ height="12"
+ image_unselected="Icon_Close_Foreground"
+ image_selected="Icon_Close_Press"
+ pad_right="4"
+ pad_left="4"
+ width="12"/>
+ </search_editor>
+ </panel>
+ <panel
height="18"
left="-416"
width="185"