diff options
author | Maki <maki@hotmilk.space> | 2024-05-15 20:58:28 -0400 |
---|---|---|
committer | Maki <maki@hotmilk.space> | 2024-05-15 20:58:28 -0400 |
commit | ec23d45e2e9a87147641fed6f8c3ef6083c2f878 (patch) | |
tree | 169edbab006d8bbd86b2980ab98fb62e097067ff /indra/llui/llflatlistview.cpp | |
parent | 8d824e8923b26c7a1d858e6cb587be1cf7d4dfeb (diff) | |
parent | 2f25f87ee719a79efc8316079f3c881eddb4d266 (diff) |
Merge branch 'release/maint-b' into pipewire-linux-volume-catcher
Diffstat (limited to 'indra/llui/llflatlistview.cpp')
-rw-r--r-- | indra/llui/llflatlistview.cpp | 1962 |
1 files changed, 981 insertions, 981 deletions
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index fd4c33df30..cd866f1625 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llflatlistview.cpp * @brief LLFlatListView base class and extension to support messages for several cases of an empty list. * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -33,76 +33,76 @@ static const LLDefaultChildRegistry::Register<LLFlatListView> flat_list_view("flat_list_view"); -const LLSD SELECTED_EVENT = LLSD().with("selected", true); -const LLSD UNSELECTED_EVENT = LLSD().with("selected", false); +const LLSD SELECTED_EVENT = LLSD().with("selected", true); +const LLSD UNSELECTED_EVENT = LLSD().with("selected", false); //forward declaration bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2); LLFlatListView::Params::Params() -: item_pad("item_pad"), - allow_select("allow_select"), - multi_select("multi_select"), - keep_one_selected("keep_one_selected"), - keep_selection_visible_on_reshape("keep_selection_visible_on_reshape",false), - no_items_text("no_items_text") +: item_pad("item_pad"), + allow_select("allow_select"), + multi_select("multi_select"), + keep_one_selected("keep_one_selected"), + keep_selection_visible_on_reshape("keep_selection_visible_on_reshape",false), + no_items_text("no_items_text") {}; void LLFlatListView::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) { - S32 delta = height - getRect().getHeight(); - LLScrollContainer::reshape(width, height, called_from_parent); - setItemsNoScrollWidth(width); - rearrangeItems(); - - if(delta!= 0 && mKeepSelectionVisibleOnReshape) - { - ensureSelectedVisible(); - } + S32 delta = height - getRect().getHeight(); + LLScrollContainer::reshape(width, height, called_from_parent); + setItemsNoScrollWidth(width); + rearrangeItems(); + + if(delta!= 0 && mKeepSelectionVisibleOnReshape) + { + ensureSelectedVisible(); + } } const LLRect& LLFlatListView::getItemsRect() const { - return mItemsPanel->getRect(); + return mItemsPanel->getRect(); } bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/) { - if (!item) return false; - if (value.isUndefined()) return false; - - //force uniqueness of items, easiest check but unreliable - if (item->getParent() == mItemsPanel) return false; - - item_pair_t* new_pair = new item_pair_t(item, value); - switch (pos) - { - case ADD_TOP: - mItemPairs.push_front(new_pair); - //in LLView::draw() children are iterated in backorder - mItemsPanel->addChildInBack(item); - break; - case ADD_BOTTOM: - mItemPairs.push_back(new_pair); - mItemsPanel->addChild(item); - break; - default: - break; - } - - //_4 is for MASK - item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); - item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); - - // Children don't accept the focus - item->setTabStop(false); - - if (rearrange) - { - rearrangeItems(); - notifyParentItemsRectChanged(); - } - return true; + if (!item) return false; + if (value.isUndefined()) return false; + + //force uniqueness of items, easiest check but unreliable + if (item->getParent() == mItemsPanel) return false; + + item_pair_t* new_pair = new item_pair_t(item, value); + switch (pos) + { + case ADD_TOP: + mItemPairs.push_front(new_pair); + //in LLView::draw() children are iterated in backorder + mItemsPanel->addChildInBack(item); + break; + case ADD_BOTTOM: + mItemPairs.push_back(new_pair); + mItemsPanel->addChild(item); + break; + default: + break; + } + + //_4 is for MASK + item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); + item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); + + // Children don't accept the focus + item->setTabStop(false); + + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + return true; } bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= true*/) @@ -183,263 +183,263 @@ bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= tr bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value /*= LLUUID::null*/) { - if (!after_item) return false; - if (!item_to_add) return false; - if (value.isUndefined()) return false; - - if (mItemPairs.empty()) return false; - - //force uniqueness of items, easiest check but unreliable - if (item_to_add->getParent() == mItemsPanel) return false; - - item_pair_t* after_pair = getItemPair(after_item); - if (!after_pair) return false; - - item_pair_t* new_pair = new item_pair_t(item_to_add, value); - if (after_pair == mItemPairs.back()) - { - mItemPairs.push_back(new_pair); - mItemsPanel->addChild(item_to_add); - } - else - { - pairs_iterator_t it = mItemPairs.begin(); - for (; it != mItemPairs.end(); ++it) - { - if (*it == after_pair) - { - // insert new elements before the element at position of passed iterator. - mItemPairs.insert(++it, new_pair); - mItemsPanel->addChild(item_to_add); - break; - } - } - } - - //_4 is for MASK - item_to_add->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); - item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); - - rearrangeItems(); - notifyParentItemsRectChanged(); - return true; + if (!after_item) return false; + if (!item_to_add) return false; + if (value.isUndefined()) return false; + + if (mItemPairs.empty()) return false; + + //force uniqueness of items, easiest check but unreliable + if (item_to_add->getParent() == mItemsPanel) return false; + + item_pair_t* after_pair = getItemPair(after_item); + if (!after_pair) return false; + + item_pair_t* new_pair = new item_pair_t(item_to_add, value); + if (after_pair == mItemPairs.back()) + { + mItemPairs.push_back(new_pair); + mItemsPanel->addChild(item_to_add); + } + else + { + pairs_iterator_t it = mItemPairs.begin(); + for (; it != mItemPairs.end(); ++it) + { + if (*it == after_pair) + { + // insert new elements before the element at position of passed iterator. + mItemPairs.insert(++it, new_pair); + mItemsPanel->addChild(item_to_add); + break; + } + } + } + + //_4 is for MASK + item_to_add->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); + item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); + + rearrangeItems(); + notifyParentItemsRectChanged(); + return true; } bool LLFlatListView::removeItem(LLPanel* item, bool rearrange) { - if (!item) return false; - if (item->getParent() != mItemsPanel) return false; - - item_pair_t* item_pair = getItemPair(item); - if (!item_pair) return false; + if (!item) return false; + if (item->getParent() != mItemsPanel) return false; + + item_pair_t* item_pair = getItemPair(item); + if (!item_pair) return false; - return removeItemPair(item_pair, rearrange); + return removeItemPair(item_pair, rearrange); } bool LLFlatListView::removeItemByValue(const LLSD& value, bool rearrange) { - if (value.isUndefined()) return false; - - item_pair_t* item_pair = getItemPair(value); - if (!item_pair) return false; + if (value.isUndefined()) return false; - return removeItemPair(item_pair, rearrange); + item_pair_t* item_pair = getItemPair(value); + if (!item_pair) return false; + + return removeItemPair(item_pair, rearrange); } bool LLFlatListView::removeItemByUUID(const LLUUID& uuid, bool rearrange) { - return removeItemByValue(LLSD(uuid), rearrange); + return removeItemByValue(LLSD(uuid), rearrange); } LLPanel* LLFlatListView::getItemByValue(const LLSD& value) const { - if (value.isUndefined()) return NULL; + if (value.isUndefined()) return NULL; - item_pair_t* pair = getItemPair(value); - if (pair) return pair->first; - return NULL; + item_pair_t* pair = getItemPair(value); + if (pair) return pair->first; + return NULL; } bool LLFlatListView::selectItem(LLPanel* item, bool select /*= true*/) { - if (!item) return false; - if (item->getParent() != mItemsPanel) return false; - - item_pair_t* item_pair = getItemPair(item); - if (!item_pair) return false; + if (!item) return false; + if (item->getParent() != mItemsPanel) return false; + + item_pair_t* item_pair = getItemPair(item); + if (!item_pair) return false; - return selectItemPair(item_pair, select); + return selectItemPair(item_pair, select); } bool LLFlatListView::selectItemByValue(const LLSD& value, bool select /*= true*/) { - if (value.isUndefined()) return false; + if (value.isUndefined()) return false; - item_pair_t* item_pair = getItemPair(value); - if (!item_pair) return false; + item_pair_t* item_pair = getItemPair(value); + if (!item_pair) return false; - return selectItemPair(item_pair, select); + return selectItemPair(item_pair, select); } bool LLFlatListView::selectItemByUUID(const LLUUID& uuid, bool select /* = true*/) { - return selectItemByValue(LLSD(uuid), select); + return selectItemByValue(LLSD(uuid), select); } LLSD LLFlatListView::getSelectedValue() const { - if (mSelectedItemPairs.empty()) return LLSD(); + if (mSelectedItemPairs.empty()) return LLSD(); - item_pair_t* first_selected_pair = mSelectedItemPairs.front(); - return first_selected_pair->second; + item_pair_t* first_selected_pair = mSelectedItemPairs.front(); + return first_selected_pair->second; } void LLFlatListView::getSelectedValues(std::vector<LLSD>& selected_values) const { - if (mSelectedItemPairs.empty()) return; + if (mSelectedItemPairs.empty()) return; - for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - selected_values.push_back((*it)->second); - } + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_values.push_back((*it)->second); + } } LLUUID LLFlatListView::getSelectedUUID() const { - const LLSD& value = getSelectedValue(); - if (value.isDefined() && value.isUUID()) - { - return value.asUUID(); - } - else - { - return LLUUID::null; - } + const LLSD& value = getSelectedValue(); + if (value.isDefined() && value.isUUID()) + { + return value.asUUID(); + } + else + { + return LLUUID::null; + } } void LLFlatListView::getSelectedUUIDs(uuid_vec_t& selected_uuids) const { - if (mSelectedItemPairs.empty()) return; + if (mSelectedItemPairs.empty()) return; - for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - selected_uuids.push_back((*it)->second.asUUID()); - } + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_uuids.push_back((*it)->second.asUUID()); + } } LLPanel* LLFlatListView::getSelectedItem() const { - if (mSelectedItemPairs.empty()) return NULL; + if (mSelectedItemPairs.empty()) return NULL; - return mSelectedItemPairs.front()->first; + return mSelectedItemPairs.front()->first; } void LLFlatListView::getSelectedItems(std::vector<LLPanel*>& selected_items) const { - if (mSelectedItemPairs.empty()) return; + if (mSelectedItemPairs.empty()) return; - for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - selected_items.push_back((*it)->first); - } + for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + selected_items.push_back((*it)->first); + } } void LLFlatListView::resetSelection(bool no_commit_on_deselection /*= false*/) { - if (mSelectedItemPairs.empty()) return; + if (mSelectedItemPairs.empty()) return; - for (pairs_iterator_t it= mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - item_pair_t* pair_to_deselect = *it; - LLPanel* item = pair_to_deselect->first; - item->setValue(UNSELECTED_EVENT); - } + for (pairs_iterator_t it= mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + item_pair_t* pair_to_deselect = *it; + LLPanel* item = pair_to_deselect->first; + item->setValue(UNSELECTED_EVENT); + } - mSelectedItemPairs.clear(); + mSelectedItemPairs.clear(); - if (mCommitOnSelectionChange && !no_commit_on_deselection) - { - onCommit(); - } + if (mCommitOnSelectionChange && !no_commit_on_deselection) + { + onCommit(); + } - // Stretch selected item rect to ensure it won't be clipped - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); } void LLFlatListView::setNoItemsCommentText(const std::string& comment_text) { - mNoItemsCommentTextbox->setValue(comment_text); + mNoItemsCommentTextbox->setValue(comment_text); } U32 LLFlatListView::size(const bool only_visible_items) const { - if (only_visible_items) - { - U32 size = 0; - for (pairs_const_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++iter) - { - if ((*iter)->first->getVisible()) - ++size; - } - return size; - } - else - { - return mItemPairs.size(); - } + if (only_visible_items) + { + U32 size = 0; + for (pairs_const_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + if ((*iter)->first->getVisible()) + ++size; + } + return size; + } + else + { + return mItemPairs.size(); + } } void LLFlatListView::clear() { - // This will clear mSelectedItemPairs, calling all appropriate callbacks. - resetSelection(); - - // do not use LLView::deleteAllChildren to avoid removing nonvisible items. drag-n-drop for ex. - for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - mItemsPanel->removeChild((*it)->first); - (*it)->first->die(); - delete *it; - } - mItemPairs.clear(); - - // also set items panel height to zero. Reshape it to allow reshaping of non-item children - LLRect rc = mItemsPanel->getRect(); - rc.mBottom = rc.mTop; - mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); - mItemsPanel->setRect(rc); - - setNoItemsCommentVisible(true); - notifyParentItemsRectChanged(); + // This will clear mSelectedItemPairs, calling all appropriate callbacks. + resetSelection(); + + // do not use LLView::deleteAllChildren to avoid removing nonvisible items. drag-n-drop for ex. + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + mItemsPanel->removeChild((*it)->first); + (*it)->first->die(); + delete *it; + } + mItemPairs.clear(); + + // also set items panel height to zero. Reshape it to allow reshaping of non-item children + LLRect rc = mItemsPanel->getRect(); + rc.mBottom = rc.mTop; + mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); + mItemsPanel->setRect(rc); + + setNoItemsCommentVisible(true); + notifyParentItemsRectChanged(); } void LLFlatListView::sort() { - if (!mItemComparator) - { - LL_WARNS() << "No comparator specified for sorting FlatListView items." << LL_ENDL; - return; - } - - mItemPairs.sort(ComparatorAdaptor(*mItemComparator)); - rearrangeItems(); + if (!mItemComparator) + { + LL_WARNS() << "No comparator specified for sorting FlatListView items." << LL_ENDL; + return; + } + + mItemPairs.sort(ComparatorAdaptor(*mItemComparator)); + rearrangeItems(); } bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value) { - if (old_value.isUndefined() || new_value.isUndefined()) return false; - if (llsds_are_equal(old_value, new_value)) return false; + if (old_value.isUndefined() || new_value.isUndefined()) return false; + if (llsds_are_equal(old_value, new_value)) return false; - item_pair_t* item_pair = getItemPair(old_value); - if (!item_pair) return false; + item_pair_t* item_pair = getItemPair(old_value); + if (!item_pair) return false; - item_pair->second = new_value; - return true; + item_pair->second = new_value; + return true; } ////////////////////////////////////////////////////////////////////////// @@ -447,7 +447,7 @@ bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value) ////////////////////////////////////////////////////////////////////////// LLFlatListView::LLFlatListView(const LLFlatListView::Params& p) -: LLScrollContainer(p) +: LLScrollContainer(p) , mItemComparator(NULL) , mItemsPanel(NULL) , mItemPad(p.item_pad) @@ -460,857 +460,857 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p) , mIsConsecutiveSelection(false) , mKeepSelectionVisibleOnReshape(p.keep_selection_visible_on_reshape) { - mBorderThickness = getBorderWidth(); - - LLRect scroll_rect = getRect(); - LLRect items_rect; - - setItemsNoScrollWidth(scroll_rect.getWidth()); - items_rect.setLeftTopAndSize(mBorderThickness, scroll_rect.getHeight() - mBorderThickness, mItemsNoScrollWidth, 0); - - LLPanel::Params pp; - pp.rect(items_rect); - mItemsPanel = LLUICtrlFactory::create<LLPanel> (pp); - addChild(mItemsPanel); - - //we don't need to stretch in vertical direction on reshaping by a parent - //no bottom following! - mItemsPanel->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); - - LLViewBorder::Params params; - params.name("scroll border"); - params.rect(getLastSelectedItemRect()); - params.visible(false); - params.bevel_style(LLViewBorder::BEVEL_IN); - mSelectedItemsBorder = LLUICtrlFactory::create<LLViewBorder> (params); - mItemsPanel->addChild( mSelectedItemsBorder ); - - { - // create textbox for "No Items" comment text - LLTextBox::Params text_p = p.no_items_text; - if (!text_p.rect.isProvided()) - { - LLRect comment_rect = getRect(); - comment_rect.setOriginAndSize(0, 0, comment_rect.getWidth(), comment_rect.getHeight()); - comment_rect.stretch(-getBorderWidth()); - text_p.rect(comment_rect); - } - text_p.border_visible(false); - - if (!text_p.follows.isProvided()) - { - text_p.follows.flags(FOLLOWS_ALL); - } - mNoItemsCommentTextbox = LLUICtrlFactory::create<LLTextBox>(text_p, this); - } + mBorderThickness = getBorderWidth(); + + LLRect scroll_rect = getRect(); + LLRect items_rect; + + setItemsNoScrollWidth(scroll_rect.getWidth()); + items_rect.setLeftTopAndSize(mBorderThickness, scroll_rect.getHeight() - mBorderThickness, mItemsNoScrollWidth, 0); + + LLPanel::Params pp; + pp.rect(items_rect); + mItemsPanel = LLUICtrlFactory::create<LLPanel> (pp); + addChild(mItemsPanel); + + //we don't need to stretch in vertical direction on reshaping by a parent + //no bottom following! + mItemsPanel->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); + + LLViewBorder::Params params; + params.name("scroll border"); + params.rect(getLastSelectedItemRect()); + params.visible(false); + params.bevel_style(LLViewBorder::BEVEL_IN); + mSelectedItemsBorder = LLUICtrlFactory::create<LLViewBorder> (params); + mItemsPanel->addChild( mSelectedItemsBorder ); + + { + // create textbox for "No Items" comment text + LLTextBox::Params text_p = p.no_items_text; + if (!text_p.rect.isProvided()) + { + LLRect comment_rect = getRect(); + comment_rect.setOriginAndSize(0, 0, comment_rect.getWidth(), comment_rect.getHeight()); + comment_rect.stretch(-getBorderWidth()); + text_p.rect(comment_rect); + } + text_p.border_visible(false); + + if (!text_p.follows.isProvided()) + { + text_p.follows.flags(FOLLOWS_ALL); + } + mNoItemsCommentTextbox = LLUICtrlFactory::create<LLTextBox>(text_p, this); + } }; LLFlatListView::~LLFlatListView() { - for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - mItemsPanel->removeChild((*it)->first); - (*it)->first->die(); - delete *it; - } - mItemPairs.clear(); + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + mItemsPanel->removeChild((*it)->first); + (*it)->first->die(); + delete *it; + } + mItemPairs.clear(); } // virtual void LLFlatListView::draw() { - // Highlight border if a child of this container has keyboard focus - if( mSelectedItemsBorder->getVisible() ) - { - mSelectedItemsBorder->setKeyboardFocusHighlight( hasFocus() ); - } - LLScrollContainer::draw(); + // Highlight border if a child of this container has keyboard focus + if( mSelectedItemsBorder->getVisible() ) + { + mSelectedItemsBorder->setKeyboardFocusHighlight( hasFocus() ); + } + LLScrollContainer::draw(); } // virtual BOOL LLFlatListView::postBuild() { - setTabStop(true); - return LLScrollContainer::postBuild(); + setTabStop(true); + return LLScrollContainer::postBuild(); } void LLFlatListView::rearrangeItems() { - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); - setNoItemsCommentVisible(0==size()); + setNoItemsCommentVisible(0==size()); - if (mItemPairs.empty()) return; + if (mItemPairs.empty()) return; - //calculating required height - assuming items can be of different height - //list should accommodate all its items - S32 height = 0; + //calculating required height - assuming items can be of different height + //list should accommodate all its items + S32 height = 0; - S32 invisible_children_count = 0; - pairs_iterator_t it = mItemPairs.begin(); - for (; it != mItemPairs.end(); ++it) - { - LLPanel* item = (*it)->first; + S32 invisible_children_count = 0; + pairs_iterator_t it = mItemPairs.begin(); + for (; it != mItemPairs.end(); ++it) + { + LLPanel* item = (*it)->first; - // skip invisible child - if (!item->getVisible()) - { - ++invisible_children_count; - continue; - } + // skip invisible child + if (!item->getVisible()) + { + ++invisible_children_count; + continue; + } - height += item->getRect().getHeight(); - } + height += item->getRect().getHeight(); + } - // add paddings between items, excluding invisible ones - height += mItemPad * (mItemPairs.size() - invisible_children_count - 1); + // add paddings between items, excluding invisible ones + height += mItemPad * (mItemPairs.size() - invisible_children_count - 1); - LLRect rc = mItemsPanel->getRect(); - S32 width = mItemsNoScrollWidth; + LLRect rc = mItemsPanel->getRect(); + S32 width = mItemsNoScrollWidth; - // update width to avoid horizontal scrollbar - if (height > getRect().getHeight() - 2 * mBorderThickness) - width -= scrollbar_size; + // update width to avoid horizontal scrollbar + if (height > getRect().getHeight() - 2 * mBorderThickness) + width -= scrollbar_size; - //changes the bottom, end of the list goes down in the scroll container - rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height); - mItemsPanel->setRect(rc); + //changes the bottom, end of the list goes down in the scroll container + rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height); + mItemsPanel->setRect(rc); - //reshaping items - S32 item_new_top = height; - pairs_iterator_t it2, first_it = mItemPairs.begin(); - for (it2 = first_it; it2 != mItemPairs.end(); ++it2) - { - LLPanel* item = (*it2)->first; + //reshaping items + S32 item_new_top = height; + pairs_iterator_t it2, first_it = mItemPairs.begin(); + for (it2 = first_it; it2 != mItemPairs.end(); ++it2) + { + LLPanel* item = (*it2)->first; - // skip invisible child - if (!item->getVisible()) - continue; + // skip invisible child + if (!item->getVisible()) + continue; - LLRect rc = item->getRect(); - rc.setLeftTopAndSize(rc.mLeft, item_new_top, width, rc.getHeight()); - item->reshape(rc.getWidth(), rc.getHeight()); - item->setRect(rc); + LLRect rc = item->getRect(); + rc.setLeftTopAndSize(rc.mLeft, item_new_top, width, rc.getHeight()); + item->reshape(rc.getWidth(), rc.getHeight()); + item->setRect(rc); - // move top for next item in list - item_new_top -= (rc.getHeight() + mItemPad); - } + // move top for next item in list + item_new_top -= (rc.getHeight() + mItemPad); + } - // Stretch selected item rect to ensure it won't be clipped - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); } void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask) { - if (!item_pair) return; - - if (!item_pair->first) - { - LL_WARNS() << "Attempt to selet an item pair containing null panel item" << LL_ENDL; - return; - } - - setFocus(TRUE); - - bool select_item = !isSelected(item_pair); - - //*TODO find a better place for that enforcing stuff - if (mKeepOneItemSelected && numSelected() == 1 && !select_item) return; - - if ( (mask & MASK_SHIFT) && !(mask & MASK_CONTROL) - && mMultipleSelection && !mSelectedItemPairs.empty() ) - { - item_pair_t* last_selected_pair = mSelectedItemPairs.back(); - - // If item_pair is already selected - do nothing - if (last_selected_pair == item_pair) - return; - - bool grab_items = false; - bool reverse = false; - pairs_list_t pairs_to_select; - - // Pick out items from list between last selected and current clicked item_pair. - for (pairs_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++iter) - { - item_pair_t* cur = *iter; - if (cur == last_selected_pair || cur == item_pair) - { - // We've got reverse selection if last grabed item isn't a new selection. - reverse = grab_items && (cur != item_pair); - grab_items = !grab_items; - // Skip last selected and current clicked item pairs. - continue; - } - if (!cur->first->getVisible()) - { - // Skip invisible item pairs. - continue; - } - if (grab_items) - { - pairs_to_select.push_back(cur); - } - } - - if (reverse) - { - pairs_to_select.reverse(); - } - - pairs_to_select.push_back(item_pair); - - for (pairs_iterator_t - iter = pairs_to_select.begin(), - iter_end = pairs_to_select.end(); - iter != iter_end; ++iter) - { - item_pair_t* pair_to_select = *iter; - if (isSelected(pair_to_select)) - { - // Item was already selected but there is a need to keep order from last selected pair to new selection. - // Do it here to prevent extra mCommitOnSelectionChange in selectItemPair(). - mSelectedItemPairs.remove(pair_to_select); - mSelectedItemPairs.push_back(pair_to_select); - } - else - { - selectItemPair(pair_to_select, true); - } - } - - if (!select_item) - { - // Update last selected item border. - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); - } - return; - } - - //no need to do additional commit on selection reset - if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(true); - - //only CTRL usage allows to deselect an item, usual clicking on an item cannot deselect it - if (mask & MASK_CONTROL) - selectItemPair(item_pair, select_item); - else - selectItemPair(item_pair, true); + if (!item_pair) return; + + if (!item_pair->first) + { + LL_WARNS() << "Attempt to selet an item pair containing null panel item" << LL_ENDL; + return; + } + + setFocus(TRUE); + + bool select_item = !isSelected(item_pair); + + //*TODO find a better place for that enforcing stuff + if (mKeepOneItemSelected && numSelected() == 1 && !select_item) return; + + if ( (mask & MASK_SHIFT) && !(mask & MASK_CONTROL) + && mMultipleSelection && !mSelectedItemPairs.empty() ) + { + item_pair_t* last_selected_pair = mSelectedItemPairs.back(); + + // If item_pair is already selected - do nothing + if (last_selected_pair == item_pair) + return; + + bool grab_items = false; + bool reverse = false; + pairs_list_t pairs_to_select; + + // Pick out items from list between last selected and current clicked item_pair. + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + item_pair_t* cur = *iter; + if (cur == last_selected_pair || cur == item_pair) + { + // We've got reverse selection if last grabed item isn't a new selection. + reverse = grab_items && (cur != item_pair); + grab_items = !grab_items; + // Skip last selected and current clicked item pairs. + continue; + } + if (!cur->first->getVisible()) + { + // Skip invisible item pairs. + continue; + } + if (grab_items) + { + pairs_to_select.push_back(cur); + } + } + + if (reverse) + { + pairs_to_select.reverse(); + } + + pairs_to_select.push_back(item_pair); + + for (pairs_iterator_t + iter = pairs_to_select.begin(), + iter_end = pairs_to_select.end(); + iter != iter_end; ++iter) + { + item_pair_t* pair_to_select = *iter; + if (isSelected(pair_to_select)) + { + // Item was already selected but there is a need to keep order from last selected pair to new selection. + // Do it here to prevent extra mCommitOnSelectionChange in selectItemPair(). + mSelectedItemPairs.remove(pair_to_select); + mSelectedItemPairs.push_back(pair_to_select); + } + else + { + selectItemPair(pair_to_select, true); + } + } + + if (!select_item) + { + // Update last selected item border. + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + } + return; + } + + //no need to do additional commit on selection reset + if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(true); + + //only CTRL usage allows to deselect an item, usual clicking on an item cannot deselect it + if (mask & MASK_CONTROL) + selectItemPair(item_pair, select_item); + else + selectItemPair(item_pair, true); } void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask) { - if (!item_pair) - return; + if (!item_pair) + return; - // Forbid deselecting of items on right mouse button click if mMultipleSelection flag is set on, - // because some of derived classes may have context menu and selected items must be kept. - if ( !(mask & MASK_CONTROL) && mMultipleSelection && isSelected(item_pair) ) - return; + // Forbid deselecting of items on right mouse button click if mMultipleSelection flag is set on, + // because some of derived classes may have context menu and selected items must be kept. + if ( !(mask & MASK_CONTROL) && mMultipleSelection && isSelected(item_pair) ) + return; - // else got same behavior as at onItemMouseClick - onItemMouseClick(item_pair, mask); + // else got same behavior as at onItemMouseClick + onItemMouseClick(item_pair, mask); } BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask) { - BOOL reset_selection = (mask != MASK_SHIFT); - BOOL handled = FALSE; - switch (key) - { - case KEY_RETURN: - { - if (mSelectedItemPairs.size() && mask == MASK_NONE) - { - mOnReturnSignal(this, getValue()); - handled = TRUE; - } - break; - } - case KEY_UP: - { - if ( !selectNextItemPair(true, reset_selection) && reset_selection) - { - // If case we are in accordion tab notify parent to go to the previous accordion - if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed - resetSelection(); - } - break; - } - case KEY_DOWN: - { - if ( !selectNextItemPair(false, reset_selection) && reset_selection) - { - // If case we are in accordion tab notify parent to go to the next accordion - if( notifyParent(LLSD().with("action","select_next")) > 0 ) //message was processed - resetSelection(); - } - break; - } - case KEY_ESCAPE: - { - if (mask == MASK_NONE) - { - setFocus(FALSE); // pass focus to the game area (EXT-8357) - } - break; - } - default: - break; - } - - if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() ) - { - ensureSelectedVisible(); - /* - LLRect visible_rc = getVisibleContentRect(); - LLRect selected_rc = getLastSelectedItemRect(); - - if ( !visible_rc.contains (selected_rc) ) - { - // But scroll in Items panel coordinates - scrollToShowRect(selected_rc); - } - - // In case we are in accordion tab notify parent to show selected rectangle - LLRect screen_rc; - localRectToScreen(selected_rc, &screen_rc); - notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/ - - handled = TRUE; - } - - return handled ? handled : LLScrollContainer::handleKeyHere(key, mask); + BOOL reset_selection = (mask != MASK_SHIFT); + BOOL handled = FALSE; + switch (key) + { + case KEY_RETURN: + { + if (mSelectedItemPairs.size() && mask == MASK_NONE) + { + mOnReturnSignal(this, getValue()); + handled = TRUE; + } + break; + } + case KEY_UP: + { + if ( !selectNextItemPair(true, reset_selection) && reset_selection) + { + // If case we are in accordion tab notify parent to go to the previous accordion + if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed + resetSelection(); + } + break; + } + case KEY_DOWN: + { + if ( !selectNextItemPair(false, reset_selection) && reset_selection) + { + // If case we are in accordion tab notify parent to go to the next accordion + if( notifyParent(LLSD().with("action","select_next")) > 0 ) //message was processed + resetSelection(); + } + break; + } + case KEY_ESCAPE: + { + if (mask == MASK_NONE) + { + setFocus(FALSE); // pass focus to the game area (EXT-8357) + } + break; + } + default: + break; + } + + if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() ) + { + ensureSelectedVisible(); + /* + LLRect visible_rc = getVisibleContentRect(); + LLRect selected_rc = getLastSelectedItemRect(); + + if ( !visible_rc.contains (selected_rc) ) + { + // But scroll in Items panel coordinates + scrollToShowRect(selected_rc); + } + + // In case we are in accordion tab notify parent to show selected rectangle + LLRect screen_rc; + localRectToScreen(selected_rc, &screen_rc); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/ + + handled = TRUE; + } + + return handled ? handled : LLScrollContainer::handleKeyHere(key, mask); } LLFlatListView::item_pair_t* LLFlatListView::getItemPair(LLPanel* item) const { - llassert(item); - - for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - item_pair_t* item_pair = *it; - if (item_pair->first == item) return item_pair; - } - return NULL; + llassert(item); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + if (item_pair->first == item) return item_pair; + } + return NULL; } //compares two LLSD's bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2) { - llassert(llsd_1.isDefined()); - llassert(llsd_2.isDefined()); - - if (llsd_1.type() != llsd_2.type()) return false; - - if (!llsd_1.isMap()) - { - if (llsd_1.isUUID()) return llsd_1.asUUID() == llsd_2.asUUID(); - - //assumptions that string representaion is enough for other types - return llsd_1.asString() == llsd_2.asString(); - } - - if (llsd_1.size() != llsd_2.size()) return false; - - LLSD::map_const_iterator llsd_1_it = llsd_1.beginMap(); - LLSD::map_const_iterator llsd_2_it = llsd_2.beginMap(); - for (S32 i = 0; i < llsd_1.size(); ++i) - { - if ((*llsd_1_it).first != (*llsd_2_it).first) return false; - if (!llsds_are_equal((*llsd_1_it).second, (*llsd_2_it).second)) return false; - ++llsd_1_it; - ++llsd_2_it; - } - return true; + llassert(llsd_1.isDefined()); + llassert(llsd_2.isDefined()); + + if (llsd_1.type() != llsd_2.type()) return false; + + if (!llsd_1.isMap()) + { + if (llsd_1.isUUID()) return llsd_1.asUUID() == llsd_2.asUUID(); + + //assumptions that string representaion is enough for other types + return llsd_1.asString() == llsd_2.asString(); + } + + if (llsd_1.size() != llsd_2.size()) return false; + + LLSD::map_const_iterator llsd_1_it = llsd_1.beginMap(); + LLSD::map_const_iterator llsd_2_it = llsd_2.beginMap(); + for (S32 i = 0; i < llsd_1.size(); ++i) + { + if ((*llsd_1_it).first != (*llsd_2_it).first) return false; + if (!llsds_are_equal((*llsd_1_it).second, (*llsd_2_it).second)) return false; + ++llsd_1_it; + ++llsd_2_it; + } + return true; } LLFlatListView::item_pair_t* LLFlatListView::getItemPair(const LLSD& value) const { - llassert(value.isDefined()); - - for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - item_pair_t* item_pair = *it; - if (llsds_are_equal(item_pair->second, value)) return item_pair; - } - return NULL; + llassert(value.isDefined()); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + if (llsds_are_equal(item_pair->second, value)) return item_pair; + } + return NULL; } bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select) { - llassert(item_pair); - - if (!mAllowSelection && select) return false; - - if (isSelected(item_pair) == select) return true; //already in specified selection state - if (select) - { - mSelectedItemPairs.push_back(item_pair); - } - else - { - mSelectedItemPairs.remove(item_pair); - } - - //a way of notifying panel of selection state changes - LLPanel* item = item_pair->first; - item->setValue(select ? SELECTED_EVENT : UNSELECTED_EVENT); - - if (mCommitOnSelectionChange) - { - onCommit(); - } - - // Stretch selected item rect to ensure it won't be clipped - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); - // By default mark it as not consecutive selection - mIsConsecutiveSelection = false; - - return true; + llassert(item_pair); + + if (!mAllowSelection && select) return false; + + if (isSelected(item_pair) == select) return true; //already in specified selection state + if (select) + { + mSelectedItemPairs.push_back(item_pair); + } + else + { + mSelectedItemPairs.remove(item_pair); + } + + //a way of notifying panel of selection state changes + LLPanel* item = item_pair->first; + item->setValue(select ? SELECTED_EVENT : UNSELECTED_EVENT); + + if (mCommitOnSelectionChange) + { + onCommit(); + } + + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + // By default mark it as not consecutive selection + mIsConsecutiveSelection = false; + + return true; } void LLFlatListView::scrollToShowFirstSelectedItem() { - if (!mSelectedItemPairs.size()) return; + if (!mSelectedItemPairs.size()) return; - LLRect selected_rc = mSelectedItemPairs.front()->first->getRect(); + LLRect selected_rc = mSelectedItemPairs.front()->first->getRect(); - if (selected_rc.isValid()) - { - scrollToShowRect(selected_rc); - } + if (selected_rc.isValid()) + { + scrollToShowRect(selected_rc); + } } LLRect LLFlatListView::getLastSelectedItemRect() { - if (!mSelectedItemPairs.size()) - { - return LLRect::null; - } + if (!mSelectedItemPairs.size()) + { + return LLRect::null; + } - return mSelectedItemPairs.back()->first->getRect(); + return mSelectedItemPairs.back()->first->getRect(); } -void LLFlatListView::selectFirstItem () +void LLFlatListView::selectFirstItem () { - // No items - no actions! - if (0 == size()) return; - - // Select first visible item - for (pairs_iterator_t - iter = mItemPairs.begin(), - iter_end = mItemPairs.end(); - iter != iter_end; ++iter) - { - // skip invisible items - if ( (*iter)->first->getVisible() ) - { - selectItemPair(*iter, true); - ensureSelectedVisible(); - break; - } - } + // No items - no actions! + if (0 == size()) return; + + // Select first visible item + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + // skip invisible items + if ( (*iter)->first->getVisible() ) + { + selectItemPair(*iter, true); + ensureSelectedVisible(); + break; + } + } } -void LLFlatListView::selectLastItem () +void LLFlatListView::selectLastItem () { - // No items - no actions! - if (0 == size()) return; - - // Select last visible item - for (pairs_list_t::reverse_iterator - r_iter = mItemPairs.rbegin(), - r_iter_end = mItemPairs.rend(); - r_iter != r_iter_end; ++r_iter) - { - // skip invisible items - if ( (*r_iter)->first->getVisible() ) - { - selectItemPair(*r_iter, true); - ensureSelectedVisible(); - break; - } - } + // No items - no actions! + if (0 == size()) return; + + // Select last visible item + for (pairs_list_t::reverse_iterator + r_iter = mItemPairs.rbegin(), + r_iter_end = mItemPairs.rend(); + r_iter != r_iter_end; ++r_iter) + { + // skip invisible items + if ( (*r_iter)->first->getVisible() ) + { + selectItemPair(*r_iter, true); + ensureSelectedVisible(); + break; + } + } } void LLFlatListView::ensureSelectedVisible() { - LLRect selected_rc = getLastSelectedItemRect(); + LLRect selected_rc = getLastSelectedItemRect(); - if ( selected_rc.isValid() ) - { - scrollToShowRect(selected_rc); - } + if ( selected_rc.isValid() ) + { + scrollToShowRect(selected_rc); + } } // virtual bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selection) { - // No items - no actions! - if ( 0 == size() ) - return false; - - if (!mIsConsecutiveSelection) - { - // Leave only one item selected if list has not consecutive selection - if (mSelectedItemPairs.size() && !reset_selection) - { - item_pair_t* cur_sel_pair = mSelectedItemPairs.back(); - resetSelection(); - selectItemPair (cur_sel_pair, true); - } - } - - if ( mSelectedItemPairs.size() ) - { - item_pair_t* to_sel_pair = NULL; - item_pair_t* cur_sel_pair = NULL; - - // Take the last selected pair - cur_sel_pair = mSelectedItemPairs.back(); - // Bases on given direction choose next item to select - if ( is_up_direction ) - { - // Find current selected item position in mItemPairs list - pairs_list_t::reverse_iterator sel_it = std::find(mItemPairs.rbegin(), mItemPairs.rend(), cur_sel_pair); - - for (;++sel_it != mItemPairs.rend();) - { - // skip invisible items - if ( (*sel_it)->first->getVisible() ) - { - to_sel_pair = *sel_it; - break; - } - } - } - else - { - // Find current selected item position in mItemPairs list - pairs_list_t::iterator sel_it = std::find(mItemPairs.begin(), mItemPairs.end(), cur_sel_pair); - - for (;++sel_it != mItemPairs.end();) - { - // skip invisible items - if ( (*sel_it)->first->getVisible() ) - { - to_sel_pair = *sel_it; - break; - } - } - } - - if ( to_sel_pair ) - { - bool select = true; - if ( reset_selection ) - { - // Reset current selection if we were asked about it - resetSelection(); - } - else - { - // If item already selected and no reset request than we should deselect last selected item. - select = (mSelectedItemPairs.end() == std::find(mSelectedItemPairs.begin(), mSelectedItemPairs.end(), to_sel_pair)); - } - // Select/Deselect next item - selectItemPair(select ? to_sel_pair : cur_sel_pair, select); - // Mark it as consecutive selection - mIsConsecutiveSelection = true; - return true; - } - } - else - { - // If there weren't selected items then choose the first one bases on given direction - // Force selection to first item - if (is_up_direction) - selectLastItem(); - else - selectFirstItem(); - // Mark it as consecutive selection - mIsConsecutiveSelection = true; - return true; - } - - return false; + // No items - no actions! + if ( 0 == size() ) + return false; + + if (!mIsConsecutiveSelection) + { + // Leave only one item selected if list has not consecutive selection + if (mSelectedItemPairs.size() && !reset_selection) + { + item_pair_t* cur_sel_pair = mSelectedItemPairs.back(); + resetSelection(); + selectItemPair (cur_sel_pair, true); + } + } + + if ( mSelectedItemPairs.size() ) + { + item_pair_t* to_sel_pair = NULL; + item_pair_t* cur_sel_pair = NULL; + + // Take the last selected pair + cur_sel_pair = mSelectedItemPairs.back(); + // Bases on given direction choose next item to select + if ( is_up_direction ) + { + // Find current selected item position in mItemPairs list + pairs_list_t::reverse_iterator sel_it = std::find(mItemPairs.rbegin(), mItemPairs.rend(), cur_sel_pair); + + for (;++sel_it != mItemPairs.rend();) + { + // skip invisible items + if ( (*sel_it)->first->getVisible() ) + { + to_sel_pair = *sel_it; + break; + } + } + } + else + { + // Find current selected item position in mItemPairs list + pairs_list_t::iterator sel_it = std::find(mItemPairs.begin(), mItemPairs.end(), cur_sel_pair); + + for (;++sel_it != mItemPairs.end();) + { + // skip invisible items + if ( (*sel_it)->first->getVisible() ) + { + to_sel_pair = *sel_it; + break; + } + } + } + + if ( to_sel_pair ) + { + bool select = true; + if ( reset_selection ) + { + // Reset current selection if we were asked about it + resetSelection(); + } + else + { + // If item already selected and no reset request than we should deselect last selected item. + select = (mSelectedItemPairs.end() == std::find(mSelectedItemPairs.begin(), mSelectedItemPairs.end(), to_sel_pair)); + } + // Select/Deselect next item + selectItemPair(select ? to_sel_pair : cur_sel_pair, select); + // Mark it as consecutive selection + mIsConsecutiveSelection = true; + return true; + } + } + else + { + // If there weren't selected items then choose the first one bases on given direction + // Force selection to first item + if (is_up_direction) + selectLastItem(); + else + selectFirstItem(); + // Mark it as consecutive selection + mIsConsecutiveSelection = true; + return true; + } + + return false; } BOOL LLFlatListView::canSelectAll() const { - return 0 != size() && mAllowSelection && mMultipleSelection; + return 0 != size() && mAllowSelection && mMultipleSelection; } void LLFlatListView::selectAll() { - if (!mAllowSelection || !mMultipleSelection) - return; - - mSelectedItemPairs.clear(); - - for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - item_pair_t* item_pair = *it; - mSelectedItemPairs.push_back(item_pair); - //a way of notifying panel of selection state changes - LLPanel* item = item_pair->first; - item->setValue(SELECTED_EVENT); - } - - if (mCommitOnSelectionChange) - { - onCommit(); - } - - // Stretch selected item rect to ensure it won't be clipped - mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + if (!mAllowSelection || !mMultipleSelection) + return; + + mSelectedItemPairs.clear(); + + for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* item_pair = *it; + mSelectedItemPairs.push_back(item_pair); + //a way of notifying panel of selection state changes + LLPanel* item = item_pair->first; + item->setValue(SELECTED_EVENT); + } + + if (mCommitOnSelectionChange) + { + onCommit(); + } + + // Stretch selected item rect to ensure it won't be clipped + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); } bool LLFlatListView::isSelected(item_pair_t* item_pair) const { - llassert(item_pair); + llassert(item_pair); - pairs_const_iterator_t it_end = mSelectedItemPairs.end(); - return std::find(mSelectedItemPairs.begin(), it_end, item_pair) != it_end; + pairs_const_iterator_t it_end = mSelectedItemPairs.end(); + return std::find(mSelectedItemPairs.begin(), it_end, item_pair) != it_end; } bool LLFlatListView::removeItemPair(item_pair_t* item_pair, bool rearrange) { - llassert(item_pair); - - bool deleted = false; - bool selection_changed = false; - for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - item_pair_t* _item_pair = *it; - if (_item_pair == item_pair) - { - mItemPairs.erase(it); - deleted = true; - break; - } - } - - if (!deleted) return false; - - for (pairs_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) - { - item_pair_t* selected_item_pair = *it; - if (selected_item_pair == item_pair) - { - it = mSelectedItemPairs.erase(it); - selection_changed = true; - break; - } - } - - mItemsPanel->removeChild(item_pair->first); - item_pair->first->die(); - delete item_pair; - - if (rearrange) - { - rearrangeItems(); - notifyParentItemsRectChanged(); - } - - if (selection_changed && mCommitOnSelectionChange) - { - onCommit(); - } - - return true; + llassert(item_pair); + + bool deleted = false; + bool selection_changed = false; + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + item_pair_t* _item_pair = *it; + if (_item_pair == item_pair) + { + mItemPairs.erase(it); + deleted = true; + break; + } + } + + if (!deleted) return false; + + for (pairs_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it) + { + item_pair_t* selected_item_pair = *it; + if (selected_item_pair == item_pair) + { + it = mSelectedItemPairs.erase(it); + selection_changed = true; + break; + } + } + + mItemsPanel->removeChild(item_pair->first); + item_pair->first->die(); + delete item_pair; + + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + + if (selection_changed && mCommitOnSelectionChange) + { + onCommit(); + } + + return true; } void LLFlatListView::notifyParentItemsRectChanged() { - S32 comment_height = 0; + S32 comment_height = 0; - // take into account comment text height if exists - if (mNoItemsCommentTextbox && mNoItemsCommentTextbox->getVisible()) - { - // top text padding inside the textbox is included into the height - comment_height = mNoItemsCommentTextbox->getTextPixelHeight(); + // take into account comment text height if exists + if (mNoItemsCommentTextbox && mNoItemsCommentTextbox->getVisible()) + { + // top text padding inside the textbox is included into the height + comment_height = mNoItemsCommentTextbox->getTextPixelHeight(); - // take into account a distance from parent's top border to textbox's top - comment_height += getRect().getHeight() - mNoItemsCommentTextbox->getRect().mTop; - } + // take into account a distance from parent's top border to textbox's top + comment_height += getRect().getHeight() - mNoItemsCommentTextbox->getRect().mTop; + } - LLRect req_rect = getItemsRect(); + LLRect req_rect = getItemsRect(); - // get maximum of items total height and comment text height - req_rect.setOriginAndSize(req_rect.mLeft, req_rect.mBottom, req_rect.getWidth(), llmax(req_rect.getHeight(), comment_height)); + // get maximum of items total height and comment text height + req_rect.setOriginAndSize(req_rect.mLeft, req_rect.mBottom, req_rect.getWidth(), llmax(req_rect.getHeight(), comment_height)); - // take into account border size. - req_rect.stretch(getBorderWidth()); + // take into account border size. + req_rect.stretch(getBorderWidth()); - if (req_rect == mPrevNotifyParentRect) - return; + if (req_rect == mPrevNotifyParentRect) + return; - mPrevNotifyParentRect = req_rect; + mPrevNotifyParentRect = req_rect; - LLSD params; - params["action"] = "size_changes"; - params["width"] = req_rect.getWidth(); - params["height"] = req_rect.getHeight(); + LLSD params; + params["action"] = "size_changes"; + params["width"] = req_rect.getWidth(); + params["height"] = req_rect.getHeight(); - if (getParent()) // dummy widgets don't have a parent - getParent()->notifyParent(params); + if (getParent()) // dummy widgets don't have a parent + getParent()->notifyParent(params); } void LLFlatListView::setNoItemsCommentVisible(bool visible) const { - if (mNoItemsCommentTextbox) - { - mSelectedItemsBorder->setVisible(!visible); - mNoItemsCommentTextbox->setVisible(visible); - } + if (mNoItemsCommentTextbox) + { + mSelectedItemsBorder->setVisible(!visible); + mNoItemsCommentTextbox->setVisible(visible); + } } void LLFlatListView::getItems(std::vector<LLPanel*>& items) const { - if (mItemPairs.empty()) return; + if (mItemPairs.empty()) return; - items.clear(); - for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - items.push_back((*it)->first); - } + items.clear(); + for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + items.push_back((*it)->first); + } } void LLFlatListView::getValues(std::vector<LLSD>& values) const { - if (mItemPairs.empty()) return; + if (mItemPairs.empty()) return; - values.clear(); - for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) - { - values.push_back((*it)->second); - } + values.clear(); + for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + values.push_back((*it)->second); + } } // virtual void LLFlatListView::onFocusReceived() { - if (size()) - { - mSelectedItemsBorder->setVisible(TRUE); - } - gEditMenuHandler = this; + if (size()) + { + mSelectedItemsBorder->setVisible(TRUE); + } + gEditMenuHandler = this; } // virtual void LLFlatListView::onFocusLost() { - mSelectedItemsBorder->setVisible(FALSE); - // Route menu back to the default - if (gEditMenuHandler == this) - { - gEditMenuHandler = NULL; - } + mSelectedItemsBorder->setVisible(FALSE); + // Route menu back to the default + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } } -//virtual +//virtual S32 LLFlatListView::notify(const LLSD& info) { - if (info.has("action")) - { - std::string str_action = info["action"]; - if (str_action == "select_first") - { - setFocus(true); - selectFirstItem(); - return 1; - } - else if (str_action == "select_last") - { - setFocus(true); - selectLastItem(); - return 1; - } - } - else if (info.has("rearrange")) - { - rearrangeItems(); - notifyParentItemsRectChanged(); - return 1; - } - - return 0; + if (info.has("action")) + { + std::string str_action = info["action"]; + if (str_action == "select_first") + { + setFocus(true); + selectFirstItem(); + return 1; + } + else if (str_action == "select_last") + { + setFocus(true); + selectLastItem(); + return 1; + } + } + else if (info.has("rearrange")) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + return 1; + } + + return 0; } void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items) { - LLSD action; - action.with("detach", LLSD()); - // Clear detached_items list - detached_items.clear(); - // Go through items and detach valid items, remove them from items panel - // and add to detached_items. - pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); - while (iter != iter_end) - { - LLPanel* pItem = (*iter)->first; - if (1 == pItem->notify(action)) - { - selectItemPair((*iter), false); - mItemsPanel->removeChild(pItem); - detached_items.push_back(pItem); - } - iter++; - } - if (!detached_items.empty()) - { - // Some items were detached, clean ourself from unusable memory - if (detached_items.size() == mItemPairs.size()) - { - // This way will be faster if all items were disconnected - pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); - while (iter != iter_end) - { - (*iter)->first = NULL; - delete *iter; - iter++; - } - mItemPairs.clear(); - // Also set items panel height to zero. - // Reshape it to allow reshaping of non-item children. - LLRect rc = mItemsPanel->getRect(); - rc.mBottom = rc.mTop; - mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); - mItemsPanel->setRect(rc); - setNoItemsCommentVisible(true); - } - else - { - std::vector<LLPanel*>::const_iterator - detached_iter = detached_items.begin(), - detached_iter_end = detached_items.end(); - while (detached_iter < detached_iter_end) - { - LLPanel* pDetachedItem = *detached_iter; - pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); - while (iter != iter_end) - { - item_pair_t* item_pair = *iter; - if (item_pair->first == pDetachedItem) - { - mItemPairs.erase(iter); - item_pair->first = NULL; - delete item_pair; - break; - } - iter++; - } - detached_iter++; - } - rearrangeItems(); - } - notifyParentItemsRectChanged(); - } + LLSD action; + action.with("detach", LLSD()); + // Clear detached_items list + detached_items.clear(); + // Go through items and detach valid items, remove them from items panel + // and add to detached_items. + pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); + while (iter != iter_end) + { + LLPanel* pItem = (*iter)->first; + if (1 == pItem->notify(action)) + { + selectItemPair((*iter), false); + mItemsPanel->removeChild(pItem); + detached_items.push_back(pItem); + } + iter++; + } + if (!detached_items.empty()) + { + // Some items were detached, clean ourself from unusable memory + if (detached_items.size() == mItemPairs.size()) + { + // This way will be faster if all items were disconnected + pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); + while (iter != iter_end) + { + (*iter)->first = NULL; + delete *iter; + iter++; + } + mItemPairs.clear(); + // Also set items panel height to zero. + // Reshape it to allow reshaping of non-item children. + LLRect rc = mItemsPanel->getRect(); + rc.mBottom = rc.mTop; + mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); + mItemsPanel->setRect(rc); + setNoItemsCommentVisible(true); + } + else + { + std::vector<LLPanel*>::const_iterator + detached_iter = detached_items.begin(), + detached_iter_end = detached_items.end(); + while (detached_iter < detached_iter_end) + { + LLPanel* pDetachedItem = *detached_iter; + pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end(); + while (iter != iter_end) + { + item_pair_t* item_pair = *iter; + if (item_pair->first == pDetachedItem) + { + mItemPairs.erase(iter); + item_pair->first = NULL; + delete item_pair; + break; + } + iter++; + } + detached_iter++; + } + rearrangeItems(); + } + notifyParentItemsRectChanged(); + } } @@ -1324,7 +1324,7 @@ LLFlatListViewEx::Params::Params() } LLFlatListViewEx::LLFlatListViewEx(const Params& p) -: LLFlatListView(p) +: LLFlatListView(p) , mNoFilteredItemsMsg(p.no_filtered_items_msg) , mNoItemsMsg(p.no_items_msg) , mForceShowingUnmatchedItems(false) @@ -1334,41 +1334,41 @@ LLFlatListViewEx::LLFlatListViewEx(const Params& p) void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string) { - bool items_filtered = !filter_string.empty(); - if (items_filtered) - { - // items were filtered - LLStringUtil::format_map_t args; - args["[SEARCH_TERM]"] = LLURI::escape(filter_string); - std::string text = mNoFilteredItemsMsg; - LLStringUtil::format(text, args); - setNoItemsCommentText(text); - } - else - { - // list does not contain any items at all - setNoItemsCommentText(mNoItemsMsg); - } + bool items_filtered = !filter_string.empty(); + if (items_filtered) + { + // items were filtered + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(filter_string); + std::string text = mNoFilteredItemsMsg; + LLStringUtil::format(text, args); + setNoItemsCommentText(text); + } + else + { + // list does not contain any items at all + setNoItemsCommentText(mNoItemsMsg); + } } bool LLFlatListViewEx::getForceShowingUnmatchedItems() { - return mForceShowingUnmatchedItems; + return mForceShowingUnmatchedItems; } void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show) { - mForceShowingUnmatchedItems = show; + mForceShowingUnmatchedItems = show; } void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent) { - if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString)) - { - mFilterSubString = filter_str; - updateNoItemsMessage(mFilterSubString); - filterItems(false, notify_parent); - } + if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString)) + { + mFilterSubString = filter_str; + updateNoItemsMessage(mFilterSubString); + filterItems(false, notify_parent); + } } bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) @@ -1376,49 +1376,49 @@ bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) if (!item) return false; - BOOL visible = TRUE; - - // 0 signifies that filter is matched, - // i.e. we don't hide items that don't support 'match_filter' action, separators etc. - if (0 == item->notify(action)) - { - mHasMatchedItems = true; - } - else - { - // TODO: implement (re)storing of current selection. - if (!mForceShowingUnmatchedItems) - { - selectItem(item, false); - visible = FALSE; - } - } - - if (item->getVisible() != visible) - { - item->setVisible(visible); - return true; - } - - return false; + BOOL visible = TRUE; + + // 0 signifies that filter is matched, + // i.e. we don't hide items that don't support 'match_filter' action, separators etc. + if (0 == item->notify(action)) + { + mHasMatchedItems = true; + } + else + { + // TODO: implement (re)storing of current selection. + if (!mForceShowingUnmatchedItems) + { + selectItem(item, false); + visible = FALSE; + } + } + + if (item->getVisible() != visible) + { + item->setVisible(visible); + return true; + } + + return false; } void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) { - std::string cur_filter = mFilterSubString; - LLStringUtil::toUpper(cur_filter); + std::string cur_filter = mFilterSubString; + LLStringUtil::toUpper(cur_filter); - LLSD action; - action.with("match_filter", cur_filter); + LLSD action; + action.with("match_filter", cur_filter); - mHasMatchedItems = false; - bool visibility_changed = false; - pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end(); - while (iter != iter_end) - { - LLPanel* pItem = (*(iter++))->first; - visibility_changed |= updateItemVisibility(pItem, action); - } + mHasMatchedItems = false; + bool visibility_changed = false; + pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end(); + while (iter != iter_end) + { + LLPanel* pItem = (*(iter++))->first; + visibility_changed |= updateItemVisibility(pItem, action); + } if (re_sort) { @@ -1433,7 +1433,7 @@ void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) bool LLFlatListViewEx::hasMatchedItems() { - return mHasMatchedItems; + return mHasMatchedItems; } //EOF |