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-engine
master
Paul Guslisty 2010-07-01 20:00:00 +03:00
parent e1566bb1f0
commit d5bed7df35
6 changed files with 129 additions and 6 deletions

View File

@ -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())

View File

@ -293,6 +293,7 @@ public:
bool updateValue(const LLSD& old_value, const LLSD& new_value);
void scrollToShowFirstSelectedItem();
void selectFirstItem ();
void selectLastItem ();

View File

@ -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(

View File

@ -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;

View File

@ -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

View File

@ -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);