From a9680462828d99cb482cdb235f14d6bd3c87bc9c Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Thu, 13 May 2010 19:31:50 +0300 Subject: EXT-7158 FIXED Implemented filter in "My Outfits" tab. - Added accordion tab title highlighting setter and title getter. - Added filtered tabs title highlighting. - Tabs which don't pass filter are hidden. - Added applying filter on list refresh event to avoid refreshing list on every filter change. - Moved part of LLTextUtil to llui/lluitextutil to reuse code in llaccordionctrltab. - Fixed passing list size to mRefreshCompleteSignal. - Added list refresh callback to LLInventoryItemsList for checking tab visibility without re-applying filter sub-string. Committed to proceed with dependent tasks. If there are any comments/suggestions related to text utils this part of code may be changed without requiring much effort. Reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/363/ --HG-- branch : product-engine --- indra/llui/llaccordionctrltab.cpp | 51 +++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'indra/llui/llaccordionctrltab.cpp') diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 596da782ce..0db2dca615 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -32,12 +32,13 @@ #include "linden_common.h" -#include "lluictrl.h" -#include "llscrollbar.h" #include "llaccordionctrltab.h" -#include "lllocalcliprect.h" +#include "lllocalcliprect.h" +#include "llscrollbar.h" #include "lltextbox.h" +#include "lluictrl.h" +#include "lluitextutil.h" static const std::string DD_BUTTON_NAME = "dd_button"; static const std::string DD_TEXTBOX_NAME = "dd_textbox"; @@ -72,7 +73,8 @@ public: virtual BOOL postBuild(); - void setTitle(const std::string& title); + std::string getTitle(); + void setTitle(const std::string& title, const std::string& hl); virtual void onMouseEnter(S32 x, S32 y, MASK mask); virtual void onMouseLeave(S32 x, S32 y, MASK mask); @@ -146,10 +148,28 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild() return TRUE; } -void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title) +std::string LLAccordionCtrlTab::LLAccordionCtrlTabHeader::getTitle() { if(mHeaderTextbox) - mHeaderTextbox->setText(title); + { + return mHeaderTextbox->getText(); + } + else + { + return LLStringUtil::null; + } +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title, const std::string& hl) +{ + if(mHeaderTextbox) + { + LLTextUtil::textboxSetHighlightedVal( + mHeaderTextbox, + LLStyle::Params(), + title, + hl); + } } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() @@ -436,12 +456,25 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel) addChild(panel,0); } -void LLAccordionCtrlTab::setTitle(const std::string& title) +std::string LLAccordionCtrlTab::getTitle() +{ + LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); + if (header) + { + return header->getTitle(); + } + else + { + return LLStringUtil::null; + } +} + +void LLAccordionCtrlTab::setTitle(const std::string& title, const std::string& hl) { LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); if (header) { - header->setTitle(title); + header->setTitle(title, hl); } } @@ -903,5 +936,3 @@ BOOL LLAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask) } return LLUICtrl::handleToolTip(x, y, mask); } - - -- cgit v1.3 From 09a58b804bfcc055ce7722bf5aa8a05bfd6ed890 Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Wed, 19 May 2010 01:20:39 +0300 Subject: EXT-7158 FIXED Moved lltextutil from newview to llui library. Reviewed by Richard Nelson and Mike Antipov at https://codereview.productengine.com/secondlife/r/363/ --HG-- branch : product-engine --- indra/llui/CMakeLists.txt | 4 +- indra/llui/llaccordionctrltab.cpp | 2 +- indra/llui/lltextutil.cpp | 79 ++++++++++++++++++++++++++++++++ indra/llui/lltextutil.h | 72 +++++++++++++++++++++++++++++ indra/newview/CMakeLists.txt | 2 - indra/newview/llavatarlist.cpp | 8 ++-- indra/newview/llavatarlistitem.cpp | 2 +- indra/newview/llgrouplist.cpp | 2 +- indra/newview/llimview.cpp | 2 +- indra/newview/llinventoryitemslist.cpp | 2 +- indra/newview/llpanelteleporthistory.cpp | 2 +- 11 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 indra/llui/lltextutil.cpp create mode 100644 indra/llui/lltextutil.h (limited to 'indra/llui/llaccordionctrltab.cpp') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 88a1652671..12df9ccae4 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -91,6 +91,7 @@ set(llui_SOURCE_FILES lltextbox.cpp lltexteditor.cpp lltextparser.cpp + lltextutil.cpp lltextvalidate.cpp lltransutil.cpp lltoggleablemenu.cpp @@ -101,7 +102,6 @@ set(llui_SOURCE_FILES lluictrlfactory.cpp lluiimage.cpp lluistring.cpp - lluitextutil.cpp llundo.cpp llurlaction.cpp llurlentry.cpp @@ -186,6 +186,7 @@ set(llui_HEADER_FILES lltextbox.h lltexteditor.h lltextparser.h + lltextutil.h lltextvalidate.h lltoggleablemenu.h lltooltip.h @@ -198,7 +199,6 @@ set(llui_HEADER_FILES llui.h lluiimage.h lluistring.h - lluitextutil.h llundo.h llurlaction.h llurlentry.h diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 0db2dca615..b09c108ec3 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -37,8 +37,8 @@ #include "lllocalcliprect.h" #include "llscrollbar.h" #include "lltextbox.h" +#include "lltextutil.h" #include "lluictrl.h" -#include "lluitextutil.h" static const std::string DD_BUTTON_NAME = "dd_button"; static const std::string DD_TEXTBOX_NAME = "dd_textbox"; diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp new file mode 100644 index 0000000000..c5f3929fb1 --- /dev/null +++ b/indra/llui/lltextutil.cpp @@ -0,0 +1,79 @@ +/** + * @file lltextutil.cpp + * @brief Misc text-related auxiliary methods + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "lltextutil.h" + +#include "lluicolor.h" +#include "lltextbox.h" + + +void LLTextUtil::textboxSetHighlightedVal(LLTextBox *txtbox, const LLStyle::Params& normal_style, const std::string& text, const std::string& hl) +{ + static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", LLColor4::green); + + std::string text_uc = text; + LLStringUtil::toUpper(text_uc); + + size_t hl_begin = 0, hl_len = hl.size(); + + if (hl_len == 0 || (hl_begin = text_uc.find(hl)) == std::string::npos) + { + txtbox->setText(text, normal_style); + return; + } + + LLStyle::Params hl_style = normal_style; + hl_style.color = sFilterTextColor; + + txtbox->setText(LLStringUtil::null); // clear text + txtbox->appendText(text.substr(0, hl_begin), false, normal_style); + txtbox->appendText(text.substr(hl_begin, hl_len), false, hl_style); + txtbox->appendText(text.substr(hl_begin + hl_len), false, normal_style); +} + +const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str) +{ + static const std::string PHONE_SEPARATOR = LLUI::sSettingGroups["config"]->getString("AvalinePhoneSeparator"); + static const S32 PHONE_PART_LEN = 2; + + static std::string formatted_phone_str; + formatted_phone_str = phone_str; + S32 separator_pos = (S32)(formatted_phone_str.size()) - PHONE_PART_LEN; + for (; separator_pos >= PHONE_PART_LEN; separator_pos -= PHONE_PART_LEN) + { + formatted_phone_str.insert(separator_pos, PHONE_SEPARATOR); + } + + return formatted_phone_str; +} + +// EOF diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h new file mode 100644 index 0000000000..325c3c5b7c --- /dev/null +++ b/indra/llui/lltextutil.h @@ -0,0 +1,72 @@ +/** + * @file lltextutil.h + * @brief Misc text-related auxiliary methods + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXTUTIL_H +#define LL_LLTEXTUTIL_H + +#include "llstyle.h" + +class LLTextBox; + +namespace LLTextUtil +{ + + /** + * Set value for text box, highlighting substring hl_uc. + * + * Used to highlight filter matches. + * + * @param txtbox Text box to set value for + * @param normal_style Style to use for non-highlighted text + * @param text Text to set + * @param hl Upper-cased string to highlight + */ + void textboxSetHighlightedVal( + LLTextBox *txtbox, + const LLStyle::Params& normal_style, + const std::string& text, + const std::string& hl); + + /** + * Formats passed phone number to be more human readable. + * + * It just divides the number on parts by two digits from right to left. The first left part + * can have 2 or 3 digits, i.e. +44-33-33-44-55-66 or 12-34-56-78-90. Separator is set in + * application settings (AvalinePhoneSeparator) + * + * @param[in] phone_str string with original phone number + * @return reference to string with formatted phone number + */ + const std::string& formatPhoneNumber(const std::string& phone_str); +} + +#endif // LL_LLTEXTUTIL_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f2bed843c9..d77d53f6af 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -421,7 +421,6 @@ set(viewer_SOURCE_FILES lltexturestats.cpp lltexturestatsuploader.cpp lltextureview.cpp - lltextutil.cpp lltoast.cpp lltoastalertpanel.cpp lltoastgroupnotifypanel.cpp @@ -935,7 +934,6 @@ set(viewer_HEADER_FILES lltexturestats.h lltexturestatsuploader.h lltextureview.h - lltextutil.h lltoast.h lltoastalertpanel.h lltoastgroupnotifypanel.h diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 72ee289c91..24290ac089 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -32,19 +32,21 @@ #include "llviewerprecompiledheaders.h" +#include "llavatarlist.h" + // common #include "lltrans.h" #include "llcommonutils.h" -#include "llavatarlist.h" -#include "llagentdata.h" // for comparator +// llui +#include "lltextutil.h" // newview +#include "llagentdata.h" // for comparator #include "llavatariconctrl.h" #include "llcallingcard.h" // for LLAvatarTracker #include "llcachename.h" #include "llrecentpeople.h" -#include "lltextutil.h" #include "lluuid.h" #include "llvoiceclient.h" #include "llviewercontrol.h" // for gSavedSettings diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 656274cb7a..5a8ad73c83 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -38,7 +38,7 @@ #include "llbutton.h" #include "llfloaterreg.h" -#include "lluitextutil.h" +#include "lltextutil.h" #include "llagent.h" #include "llavatariconctrl.h" diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 3224ac6d9b..da5196df45 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -39,8 +39,8 @@ #include "lliconctrl.h" #include "llmenugl.h" #include "lltextbox.h" +#include "lltextutil.h" #include "lltrans.h" -#include "lluitextutil.h" // newview #include "llagent.h" diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c143ac9dea..039df69454 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -43,6 +43,7 @@ #include "llhttpclient.h" #include "llsdutil_math.h" #include "llstring.h" +#include "lltextutil.h" #include "lltrans.h" #include "lluictrlfactory.h" @@ -65,7 +66,6 @@ #include "llnearbychat.h" #include "llspeakers.h" //for LLIMSpeakerMgr #include "lltextbox.h" -#include "lltextutil.h" #include "llviewercontrol.h" #include "llviewerparcelmgr.h" diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index 9b592e79af..f94515d242 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -42,7 +42,7 @@ // llui #include "lliconctrl.h" -#include "lluitextutil.h" +#include "lltextutil.h" #include "llcallbacklist.h" #include "llinventoryfunctions.h" diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 4dd03e04a9..e8b6c6bfe5 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -38,7 +38,7 @@ #include "llsidetray.h" #include "llworldmap.h" #include "llteleporthistorystorage.h" -#include "lluitextutil.h" +#include "lltextutil.h" #include "llaccordionctrl.h" #include "llaccordionctrltab.h" -- cgit v1.3 From 40b476dbb2aee494d57dce81427b74ac19b1428d Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Sat, 29 May 2010 00:06:34 +0300 Subject: EXT-7198, EXT-7491 FIXED Added mutli-selection support for outfit items and outfit tabs selection support. - Added selecting multiple items from more than one accordion tab. - Integrated context menus from Vadim's patch for EXT-6726 Appearance SP menus (WIP tier 2). - Added selection to accordion control to use it instead of accordion tab focus in cases when focus is lost and outfit tab should stay selected. - Changed "Wear" button behavior: "Wear" puts on currently selected outfit (as the tooltip reads "Wear selected outfit"). There is always an outfit selected when the accordion is focused so for now there are no cases when only some items are selected. Separate items can be worn from context menu. - Added moving accordion tab selection with right click. Fixed (EXT-7491) Right click on an accordion title should move selection to it. Reviewed by Neal Orman at https://codereview.productengine.com/secondlife/r/437/ --HG-- branch : product-engine --- indra/llui/llaccordionctrl.cpp | 24 +++++++ indra/llui/llaccordionctrl.h | 1 + indra/llui/llaccordionctrltab.cpp | 29 +++++++- indra/llui/llaccordionctrltab.h | 7 ++ indra/newview/llinventoryitemslist.h | 3 + indra/newview/lloutfitslist.cpp | 78 ++++++++++++++++++---- indra/newview/lloutfitslist.h | 7 +- .../skins/default/xui/en/outfit_accordion_tab.xml | 2 + 8 files changed, 134 insertions(+), 17 deletions(-) (limited to 'indra/llui/llaccordionctrltab.cpp') diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 5d1d57cbb2..8e0245c451 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -65,6 +65,7 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) , mFitParent(params.fit_parent) , mAutoScrolling( false ) , mAutoScrollRate( 0.f ) + , mSelectedTab( NULL ) { mSingleExpansion = params.single_expansion; if(mFitParent && !mSingleExpansion) @@ -76,6 +77,7 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) LLAccordionCtrl::LLAccordionCtrl() : LLPanel() , mAutoScrolling( false ) , mAutoScrollRate( 0.f ) + , mSelectedTab( NULL ) { mSingleExpansion = false; mFitParent = false; @@ -689,6 +691,28 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info) } return 0; } + else if(str_action == "select_current") + { + for(size_t i=0;ihasFocus()) + { + if (mAccordionTabs[i] != mSelectedTab) + { + if (mSelectedTab) + { + mSelectedTab->setSelected(false); + } + mSelectedTab = mAccordionTabs[i]; + mSelectedTab->setSelected(true); + } + + return 1; + } + } + return 0; + } } else if (info.has("scrollToShowRect")) { diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index ab7d6548ca..a029201c90 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -130,6 +130,7 @@ private: bool mFitParent; bool mAutoScrolling; F32 mAutoScrollRate; + LLAccordionCtrlTab* mSelectedTab; }; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index b09c108ec3..83e67980a3 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -76,6 +76,8 @@ public: std::string getTitle(); void setTitle(const std::string& title, const std::string& hl); + void setSelected(bool is_selected) { mIsSelected = is_selected; } + virtual void onMouseEnter(S32 x, S32 y, MASK mask); virtual void onMouseLeave(S32 x, S32 y, MASK mask); virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); @@ -103,6 +105,7 @@ private: LLUIColor mHeaderBGColor; bool mNeedsHighlight; + bool mIsSelected; LLFrameTimer mAutoOpenTimer; }; @@ -115,7 +118,8 @@ LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader( const LLAccordionCtrlTabHeader::Params& p) : LLUICtrl(p) , mHeaderBGColor(p.header_bg_color()) -,mNeedsHighlight(false), +, mNeedsHighlight(false) +, mIsSelected(false), mImageCollapsed(p.header_collapse_img), mImageCollapsedPressed(p.header_collapse_img_pressed), mImageExpanded(p.header_expand_img), @@ -187,7 +191,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() // Only show green "focus" background image if the accordion is open, // because the user's mental model of focus is that it goes away after // the accordion is closed. - if (getParent()->hasFocus() + if (getParent()->hasFocus() || mIsSelected /*&& !(collapsible && !expanded)*/ // WHY?? ) { @@ -301,6 +305,7 @@ LLAccordionCtrlTab::Params::Params() ,header_image_focused("header_image_focused") ,header_text_color("header_text_color") ,fit_panel("fit_panel",true) + ,selection_enabled("selection_enabled", false) { mouse_opaque(false); } @@ -331,6 +336,11 @@ LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p) mHeader = LLUICtrlFactory::create(headerParams); addChild(mHeader, 1); + if (p.selection_enabled) + { + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this)); + } + reshape(100, 200,FALSE); } @@ -498,6 +508,15 @@ boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus return boost::signals2::connection(); } +void LLAccordionCtrlTab::setSelected(bool is_selected) +{ + LLAccordionCtrlTabHeader* header = findChild(DD_HEADER_NAME); + if (header) + { + header->setSelected(is_selected); + } +} + LLView* LLAccordionCtrlTab::findContainerView() { for(child_list_const_iter_t it = getChildList()->begin(); @@ -513,6 +532,11 @@ LLView* LLAccordionCtrlTab::findContainerView() return NULL; } +void LLAccordionCtrlTab::selectOnFocusReceived() +{ + if (getParent()) // A parent may not be set if tabs are added dynamically. + getParent()->notifyParent(LLSD().with("action", "select_current")); +} S32 LLAccordionCtrlTab::getHeaderHeight() { @@ -713,6 +737,7 @@ void LLAccordionCtrlTab::showAndFocusHeader() { LLAccordionCtrlTabHeader* header = getChild(DD_HEADER_NAME); header->setFocus(true); + header->setSelected(true); LLRect screen_rc; LLRect selected_rc = header->getRect(); diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index f5b7fd0af6..83a9024a74 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -88,6 +88,8 @@ public: Optional fit_panel; + Optional selection_enabled; + Optional padding_left; Optional padding_right; Optional padding_top; @@ -121,6 +123,8 @@ public: boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); boost::signals2::connection setFocusLostCallback(const focus_signal_t::slot_type& cb); + void setSelected(bool is_selected); + bool getCollapsible() {return mCollapsible;}; void setCollapsible(bool collapsible) {mCollapsible = collapsible;}; @@ -199,6 +203,9 @@ protected: void drawChild(const LLRect& root_rect,LLView* child); LLView* findContainerView (); + + void selectOnFocusReceived(); + private: class LLAccordionCtrlTabHeader; diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index 807952948b..03ad7c2184 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -133,6 +133,9 @@ public: /** Get the description of a corresponding inventory item */ const std::string& getDescription() const { return mItem->getDescription(); } + /** Get the associated inventory item */ + LLViewerInventoryItem* getItem() const { return mItem; } + virtual ~LLPanelInventoryListItemBase(){} protected: diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 17a2db7a43..8f189a1e9f 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -82,7 +82,6 @@ LLOutfitsList::LLOutfitsList() : LLPanel() , mAccordion(NULL) , mListCommands(NULL) - , mSelectedList(NULL) { mCategoriesObserver = new LLInventoryCategoriesObserver(); gInventory.addObserver(mCategoriesObserver); @@ -208,6 +207,8 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) // Setting list refresh callback to apply filter on list change. list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); + list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); + // Fetch the new outfit contents. cat->fetch(); @@ -237,23 +238,27 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter)); if (outfits_iter != mOutfitsMap.end()) { - // An outfit is removed from the list. Do the following: - // 1. Remove outfit accordion tab from accordion. - mAccordion->removeCollapsibleCtrl(outfits_iter->second); - const LLUUID& outfit_id = outfits_iter->first; + LLAccordionCtrlTab* tab = outfits_iter->second; - // 2. Remove outfit category from observer to stop monitoring its changes. + // An outfit is removed from the list. Do the following: + // 1. Remove outfit category from observer to stop monitoring its changes. mCategoriesObserver->removeCategory(outfit_id); - // 3. Reset selection if selected outfit is being removed. - if (mSelectedOutfitUUID == outfit_id) + // 2. Remove selected lists map entry. + mSelectedListsMap.erase(outfit_id); + + // 3. Reset currently selected outfit id if it is being removed. + if (outfit_id == mSelectedOutfitUUID) { - changeOutfitSelection(NULL, LLUUID()); + mSelectedOutfitUUID = LLUUID(); } // 4. Remove category UUID to accordion tab mapping. mOutfitsMap.erase(outfits_iter); + + // 5. Remove outfit tab from accordion. + mAccordion->removeCollapsibleCtrl(tab); } } @@ -283,6 +288,8 @@ void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl) void LLOutfitsList::performAction(std::string action) { + if (mSelectedOutfitUUID.isNull()) return; + LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedOutfitUUID); if (!cat) return; @@ -367,14 +374,28 @@ void LLOutfitsList::updateOutfitTab(const LLUUID& category_id) void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) { - // Reset selection in previously selected tab - // if a new one is selected. - if (list && mSelectedList && mSelectedList != list) + MASK mask = gKeyboard->currentMask(TRUE); + + // Reset selection in all previously selected tabs except for the current + // if new selection is started. + if (list && !(mask & MASK_CONTROL)) { - mSelectedList->resetSelection(); + for (wearables_lists_map_t::iterator iter = mSelectedListsMap.begin(); + iter != mSelectedListsMap.end(); + ++iter) + { + LLWearableItemsList* selected_list = (*iter).second; + if (selected_list != list) + { + selected_list->resetSelection(); + } + } + + // Clear current selection. + mSelectedListsMap.clear(); } - mSelectedList = list; + mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list)); mSelectedOutfitUUID = category_id; } @@ -494,6 +515,13 @@ void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const S32 header_bottom = tab->getLocalRect().getHeight() - tab->getHeaderHeight(); if(y >= header_bottom) { + // Focus tab header to trigger tab selection change. + LLUICtrl* header = tab->findChild("dd_header"); + if (header) + { + header->setFocus(TRUE); + } + uuid_vec_t selected_uuids; selected_uuids.push_back(cat_id); mOutfitMenu->show(ctrl, selected_uuids, x, y); @@ -501,4 +529,26 @@ void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const } } +void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) +{ + LLWearableItemsList* list = dynamic_cast(ctrl); + if (!list) return; + + uuid_vec_t selected_uuids; + + // Collect seleted items from all selected lists. + for (wearables_lists_map_t::iterator iter = mSelectedListsMap.begin(); + iter != mSelectedListsMap.end(); + ++iter) + { + uuid_vec_t uuids; + (*iter).second->getSelectedUUIDs(uuids); + + S32 prev_size = selected_uuids.size(); + selected_uuids.resize(prev_size + uuids.size()); + std::copy(uuids.begin(), uuids.end(), selected_uuids.begin() + prev_size); + } + + LLWearableItemsList::ContextMenu::instance().show(list, selected_uuids, x, y); +} // EOF diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index b6b3d6ae46..1da7360c2e 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -108,12 +108,17 @@ private: void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); + void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + LLInventoryCategoriesObserver* mCategoriesObserver; LLAccordionCtrl* mAccordion; LLPanel* mListCommands; - LLWearableItemsList* mSelectedList; + typedef std::map wearables_lists_map_t; + typedef wearables_lists_map_t::value_type wearables_lists_map_value_t; + wearables_lists_map_t mSelectedListsMap; + LLUUID mSelectedOutfitUUID; std::string mFilterSubString; diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index 066992b25d..44437d01eb 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -8,6 +8,7 @@ height="45" layout="topleft" name="Mockup Tab" + selection_enabled="true" title="Mockup Tab" translate="false" width="0"> @@ -18,5 +19,6 @@ multi_select="true" name="wearable_items_list" translate="false" + use_internal_context_menu="false" /> -- cgit v1.3