EXT-7565 FIXED Would be nice to preserve selection while switching between folder/list view modes
- Created callback called 'SaveSelecton' (which preserves selection while switching between folder/list view modes) for folder/list view modes buttons in LLPanelOutfitEdit. - Added 'scrollToShowFirstSelectedItem' method in the LLFlatListView which scrools and shows the first selected item in case multiselection. - It's possible to set selection for flat list view items before list is build. The result is that any items will be selected. To get rid of it: 1. Overrided LLFlatListView::selectItemByValue method in LLInventoryItemsList so that if list is not created yet, items ids are saved to the vector. 2. Added 'LLInventoryItemsList::updateSelection()' method which selects items with ids from that vector when list is created. - A little refactoring: moved funcionality of updating WearablesPanel's verb buttons to the separate method called LLPanelOutfitEdit::updateWearablesPanelVerbButtons() to made code more readable and self-explanatory Reviewed by Vadim Savchuk and Neal Orman at https://codereview.productengine.com/secondlife/r/579/ --HG-- branch : product-enginemaster
parent
e1566bb1f0
commit
d5bed7df35
|
|
@ -776,6 +776,18 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)
|
|||
return true;
|
||||
}
|
||||
|
||||
void LLFlatListView::scrollToShowFirstSelectedItem()
|
||||
{
|
||||
if (!mSelectedItemPairs.size()) return;
|
||||
|
||||
LLRect selected_rc = mSelectedItemPairs.front()->first->getRect();
|
||||
|
||||
if (selected_rc.isValid())
|
||||
{
|
||||
scrollToShowRect(selected_rc);
|
||||
}
|
||||
}
|
||||
|
||||
LLRect LLFlatListView::getLastSelectedItemRect()
|
||||
{
|
||||
if (!mSelectedItemPairs.size())
|
||||
|
|
|
|||
|
|
@ -293,6 +293,7 @@ public:
|
|||
|
||||
bool updateValue(const LLSD& old_value, const LLSD& new_value);
|
||||
|
||||
void scrollToShowFirstSelectedItem();
|
||||
|
||||
void selectFirstItem ();
|
||||
void selectLastItem ();
|
||||
|
|
|
|||
|
|
@ -85,6 +85,37 @@ boost::signals2::connection LLInventoryItemsList::setRefreshCompleteCallback(con
|
|||
return mRefreshCompleteSignal.connect(cb);
|
||||
}
|
||||
|
||||
bool LLInventoryItemsList::selectItemByValue(const LLSD& value, bool select)
|
||||
{
|
||||
if (!LLFlatListView::selectItemByValue(value, select) && !value.isUndefined())
|
||||
{
|
||||
mSelectTheseIDs.push_back(value);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLInventoryItemsList::updateSelection()
|
||||
{
|
||||
if(mSelectTheseIDs.empty()) return;
|
||||
|
||||
std::vector<LLSD> cur;
|
||||
getValues(cur);
|
||||
|
||||
for(std::vector<LLSD>::const_iterator cur_id_it = cur.begin(); cur_id_it != cur.end() && !mSelectTheseIDs.empty(); ++cur_id_it)
|
||||
{
|
||||
uuid_vec_t::iterator select_ids_it = std::find(mSelectTheseIDs.begin(), mSelectTheseIDs.end(), *cur_id_it);
|
||||
if(select_ids_it != mSelectTheseIDs.end())
|
||||
{
|
||||
selectItemByUUID(*select_ids_it);
|
||||
mSelectTheseIDs.erase(select_ids_it);
|
||||
}
|
||||
}
|
||||
|
||||
scrollToShowFirstSelectedItem();
|
||||
mSelectTheseIDs.clear();
|
||||
}
|
||||
|
||||
void LLInventoryItemsList::doIdle()
|
||||
{
|
||||
if (!mNeedsRefresh) return;
|
||||
|
|
@ -149,6 +180,12 @@ void LLInventoryItemsList::refresh()
|
|||
bool needs_refresh = add_limit_exceeded;
|
||||
setNeedsRefresh(needs_refresh);
|
||||
setForceRefresh(needs_refresh);
|
||||
|
||||
// After list building completed, select items that had been requested to select before list was build
|
||||
if(!needs_refresh)
|
||||
{
|
||||
updateSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryItemsList::computeDifference(
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@ public:
|
|||
*/
|
||||
void setForceRefresh(bool force_refresh){ mForceRefresh = force_refresh; }
|
||||
|
||||
virtual bool selectItemByValue(const LLSD& value, bool select = true);
|
||||
|
||||
void updateSelection();
|
||||
|
||||
/**
|
||||
* Idle routine used to refresh the list regardless of the current list
|
||||
* visibility, unlike draw() which is called only for the visible list.
|
||||
|
|
@ -104,6 +108,9 @@ protected:
|
|||
private:
|
||||
uuid_vec_t mIDs; // IDs of items that were added in refreshList().
|
||||
// Will be used in refresh() to determine added and removed ids
|
||||
|
||||
uuid_vec_t mSelectTheseIDs; // IDs that will be selected if list is not loaded till now
|
||||
|
||||
bool mNeedsRefresh;
|
||||
|
||||
bool mForceRefresh;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "lloutfitobserver.h"
|
||||
#include "llcofwearables.h"
|
||||
#include "llfilteredwearablelist.h"
|
||||
#include "llfolderviewitem.h"
|
||||
#include "llinventory.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llui.h"
|
||||
|
|
@ -462,7 +463,9 @@ BOOL LLPanelOutfitEdit::postBuild()
|
|||
|
||||
childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL);
|
||||
childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesFolderView, this), NULL);
|
||||
childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);
|
||||
childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL);
|
||||
childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);
|
||||
childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
|
||||
childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
|
||||
childSetCommitCallback("shop_btn_1", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL);
|
||||
|
|
@ -610,9 +613,7 @@ void LLPanelOutfitEdit::showWearablesListView()
|
|||
{
|
||||
if(switchPanels(mInventoryItemsPanel, mWearablesListViewPanel))
|
||||
{
|
||||
mFolderViewBtn->setToggleState(FALSE);
|
||||
mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign());
|
||||
mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign());
|
||||
updateWearablesPanelVerbButtons();
|
||||
updateFiltersVisibility();
|
||||
}
|
||||
mListViewBtn->setToggleState(TRUE);
|
||||
|
|
@ -622,9 +623,7 @@ void LLPanelOutfitEdit::showWearablesFolderView()
|
|||
{
|
||||
if(switchPanels(mWearablesListViewPanel, mInventoryItemsPanel))
|
||||
{
|
||||
mListViewBtn->setToggleState(FALSE);
|
||||
mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign());
|
||||
mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign());
|
||||
updateWearablesPanelVerbButtons();
|
||||
updateFiltersVisibility();
|
||||
}
|
||||
mFolderViewBtn->setToggleState(TRUE);
|
||||
|
|
@ -1138,5 +1137,66 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list)
|
|||
// return selected_id;
|
||||
}
|
||||
|
||||
void LLPanelOutfitEdit::updateWearablesPanelVerbButtons()
|
||||
{
|
||||
if(mWearablesListViewPanel->getVisible())
|
||||
{
|
||||
mFolderViewBtn->setToggleState(FALSE);
|
||||
mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign());
|
||||
mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign());
|
||||
}
|
||||
else if(mInventoryItemsPanel->getVisible())
|
||||
{
|
||||
mListViewBtn->setToggleState(FALSE);
|
||||
mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign());
|
||||
mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign());
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelOutfitEdit::saveListSelection()
|
||||
{
|
||||
if(mWearablesListViewPanel->getVisible())
|
||||
{
|
||||
std::set<LLUUID> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList();
|
||||
|
||||
if(!selected_ids.size()) return;
|
||||
|
||||
mWearableItemsList->resetSelection();
|
||||
|
||||
for (std::set<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id)
|
||||
{
|
||||
mWearableItemsList->selectItemByUUID(*item_id, true);
|
||||
}
|
||||
mWearableItemsList->scrollToShowFirstSelectedItem();
|
||||
}
|
||||
else if(mInventoryItemsPanel->getVisible())
|
||||
{
|
||||
std::vector<LLUUID> selected_ids;
|
||||
mWearableItemsList->getSelectedUUIDs(selected_ids);
|
||||
|
||||
if(!selected_ids.size()) return;
|
||||
|
||||
mInventoryItemsPanel->clearSelection();
|
||||
LLFolderView* root = mInventoryItemsPanel->getRootFolder();
|
||||
|
||||
if(!root) return;
|
||||
|
||||
for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id)
|
||||
{
|
||||
LLFolderViewItem* item = root->getItemByID(*item_id);
|
||||
if (!item) continue;
|
||||
|
||||
LLFolderViewFolder* parent = item->getParentFolder();
|
||||
if(parent)
|
||||
{
|
||||
parent->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
|
||||
}
|
||||
mInventoryItemsPanel->getRootFolder()->changeSelection(item, TRUE);
|
||||
}
|
||||
mInventoryItemsPanel->getRootFolder()->scrollToShowSelection();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// EOF
|
||||
|
|
|
|||
|
|
@ -140,6 +140,12 @@ public:
|
|||
void showWearablesListView();
|
||||
void showWearablesFolderView();
|
||||
|
||||
/**
|
||||
* Method preserves selection while switching between folder/list view modes
|
||||
*/
|
||||
void saveListSelection();
|
||||
|
||||
void updateWearablesPanelVerbButtons();
|
||||
void updateFiltersVisibility();
|
||||
|
||||
void onFolderViewFilterCommitted(LLUICtrl* ctrl);
|
||||
|
|
|
|||
Loading…
Reference in New Issue