summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llaccordionctrl.cpp24
-rw-r--r--indra/llui/llaccordionctrl.h1
-rw-r--r--indra/llui/llaccordionctrltab.cpp29
-rw-r--r--indra/llui/llaccordionctrltab.h7
-rw-r--r--indra/newview/llinventoryitemslist.h3
-rw-r--r--indra/newview/lloutfitslist.cpp78
-rw-r--r--indra/newview/lloutfitslist.h7
-rw-r--r--indra/newview/skins/default/xui/en/outfit_accordion_tab.xml2
8 files changed, 134 insertions, 17 deletions
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;i<mAccordionTabs.size();++i)
+ {
+ // Set selection to the currently focused tab.
+ if(mAccordionTabs[i]->hasFocus())
+ {
+ 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<LLAccordionCtrlTabHeader>(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<LLAccordionCtrlTabHeader>(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<LLAccordionCtrlTabHeader>(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<bool> fit_panel;
+ Optional<bool> selection_enabled;
+
Optional<S32> padding_left;
Optional<S32> padding_right;
Optional<S32> 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<LLUICtrl>("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<LLWearableItemsList*>(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<LLUUID, LLWearableItemsList*> 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"
/>
</accordion_tab>