diff options
| author | AndreyL ProductEngine <alihatskiy@productengine.com> | 2019-01-03 22:59:49 +0200 | 
|---|---|---|
| committer | AndreyL ProductEngine <alihatskiy@productengine.com> | 2019-01-03 22:59:49 +0200 | 
| commit | 09b750483a2cde7ea3c80a0238f3224a2cf1cb70 (patch) | |
| tree | 5f9b38b93f916c820cf9308ed689701790b3eef5 /indra | |
| parent | ab428e194eaa144e8dcecc353c3c7ed83d6cee3e (diff) | |
SL-10293 Firestorm PR: preferences and menu search
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llui/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | indra/llui/llbutton.cpp | 4 | ||||
| -rw-r--r-- | indra/llui/llbutton.h | 7 | ||||
| -rw-r--r-- | indra/llui/llcheckboxctrl.h | 13 | ||||
| -rw-r--r-- | indra/llui/llmenugl.cpp | 4 | ||||
| -rw-r--r-- | indra/llui/llmenugl.h | 9 | ||||
| -rw-r--r-- | indra/llui/llsearchablecontrol.h | 71 | ||||
| -rw-r--r-- | indra/llui/llsliderctrl.h | 15 | ||||
| -rw-r--r-- | indra/llui/lltabcontainer.cpp | 50 | ||||
| -rw-r--r-- | indra/llui/lltabcontainer.h | 2 | ||||
| -rw-r--r-- | indra/llui/lltextbase.cpp | 11 | ||||
| -rw-r--r-- | indra/llui/lltextbase.h | 8 | ||||
| -rw-r--r-- | indra/llui/lluictrl.h | 1 | ||||
| -rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/newview/llfloaterpreference.cpp | 121 | ||||
| -rw-r--r-- | indra/newview/llfloaterpreference.h | 15 | ||||
| -rw-r--r-- | indra/newview/llsearchableui.cpp | 154 | ||||
| -rw-r--r-- | indra/newview/llsearchableui.h | 121 | ||||
| -rw-r--r-- | indra/newview/llstatusbar.cpp | 92 | ||||
| -rw-r--r-- | indra/newview/llstatusbar.h | 17 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_preferences.xml | 42 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_status_bar.xml | 40 | 
22 files changed, 788 insertions, 12 deletions
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"  | 
