summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorRamzi Linden <ramzi@lindenlab.com>2009-11-23 16:11:35 -0800
committerRamzi Linden <ramzi@lindenlab.com>2009-11-23 16:11:35 -0800
commitf39d4e98a73d5e13ce06f6188bf2d60d2db5d085 (patch)
treeb39781e1fcbcc57139b395934594158102773c3b /indra/llui
parent58eab5547fcd5f665c5254f31afd778797e5c84c (diff)
parentc9a1d3040e4ec8fde7bc1d69ea0509f0f7d288a1 (diff)
merge
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llcheckboxctrl.h1
-rw-r--r--indra/llui/llflatlistview.cpp241
-rw-r--r--indra/llui/llflatlistview.h25
-rw-r--r--indra/llui/llresizebar.cpp6
4 files changed, 273 insertions, 0 deletions
diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h
index 2f8e8fdd23..b14e66b915 100644
--- a/indra/llui/llcheckboxctrl.h
+++ b/indra/llui/llcheckboxctrl.h
@@ -107,6 +107,7 @@ public:
std::string getLabel() const;
void setFont( const LLFontGL* font ) { mFont = font; }
+ const LLFontGL* getFont() { return mFont; }
virtual void setControlName(const std::string& control_name, LLView* context);
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 19f203b80c..8de3a8a96f 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -94,6 +94,9 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*
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);
+
rearrangeItems();
notifyParentItemsRectChanged();
return true;
@@ -282,6 +285,9 @@ void LLFlatListView::resetSelection(bool no_commit_on_deselection /*= false*/)
{
onCommit();
}
+
+ // Stretch selected items rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
}
void LLFlatListView::setNoItemsCommentText(const std::string& comment_text)
@@ -381,8 +387,34 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
//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(getSelectedItemsRect());
+ params.visible(false);
+ params.bevel_style(LLViewBorder::BEVEL_IN);
+ mSelectedItemsBorder = LLUICtrlFactory::create<LLViewBorder> (params);
+ mItemsPanel->addChild( mSelectedItemsBorder );
};
+// virtual
+void LLFlatListView::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();
+}
+
void LLFlatListView::rearrangeItems()
{
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
@@ -444,6 +476,9 @@ void LLFlatListView::rearrangeItems()
// move top for next item in list
item_new_top -= (rc.getHeight() + mItemPad);
}
+
+ // Stretch selected items rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
}
void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
@@ -473,6 +508,64 @@ void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask)
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
+ notifyParent(LLSD().insert("action","select_prev"));
+ }
+ 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
+ notifyParent(LLSD().insert("action","select_next"));
+ }
+ break;
+ }
+ case 'A':
+ {
+ if(MASK_CONTROL & mask)
+ {
+ selectAll();
+ handled = TRUE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if ( key == KEY_UP || key == KEY_DOWN )
+ {
+ LLRect selcted_rect = getLastSelectedItemRect().stretch(1);
+ LLRect visible_rect = getVisibleContentRect();
+ if ( !visible_rect.contains (selcted_rect) )
+ scrollToShowRect(selcted_rect);
+ handled = TRUE;
+ }
+
+ return handled ? handled : LLScrollContainer::handleKeyHere(key, mask);
+}
+
LLFlatListView::item_pair_t* LLFlatListView::getItemPair(LLPanel* item) const
{
llassert(item);
@@ -552,6 +645,143 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)
onCommit();
}
+ setFocus(TRUE);
+
+ // Stretch selected items rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+
+ return true;
+}
+
+LLRect LLFlatListView::getLastSelectedItemRect()
+{
+ if (!mSelectedItemPairs.size())
+ {
+ return LLRect::null;
+ }
+
+ return mSelectedItemPairs.back()->first->getRect();
+}
+
+LLRect LLFlatListView::getSelectedItemsRect()
+{
+ if (!mSelectedItemPairs.size())
+ {
+ return LLRect::null;
+ }
+ LLRect rc = getLastSelectedItemRect();
+ for ( pairs_const_iterator_t
+ it = mSelectedItemPairs.begin(),
+ it_end = mSelectedItemPairs.end();
+ it != it_end; ++it )
+ {
+ rc.unionWith((*it)->first->getRect());
+ }
+ return rc;
+}
+
+// virtual
+bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selection)
+{
+ // No items - no actions!
+ if ( !mItemPairs.size() )
+ return false;
+
+ item_pair_t* cur_sel_pair = NULL;
+ item_pair_t* to_sel_pair = NULL;
+
+ if ( mSelectedItemPairs.size() )
+ {
+ // Take the last selected pair
+ cur_sel_pair = mSelectedItemPairs.back();
+ }
+ else
+ {
+ // If there weren't selected items then choose the first one bases on given direction
+ cur_sel_pair = (is_up_direction) ? mItemPairs.back() : mItemPairs.front();
+ // Force selection to first item
+ to_sel_pair = cur_sel_pair;
+ }
+
+ // 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);
+
+ return true;
+ }
+ return false;
+}
+
+bool LLFlatListView::selectAll()
+{
+ if (!mAllowSelection)
+ return false;
+
+ 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 items rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+
return true;
}
@@ -670,4 +900,15 @@ void LLFlatListView::getValues(std::vector<LLSD>& values) const
}
}
+// virtual
+void LLFlatListView::onFocusReceived()
+{
+ mSelectedItemsBorder->setVisible(TRUE);
+}
+// virtual
+void LLFlatListView::onFocusLost()
+{
+ mSelectedItemsBorder->setVisible(FALSE);
+}
+
//EOF
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index 97772bc677..eac947a0d7 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -113,6 +113,10 @@ public:
virtual ~LLFlatListView() { clear(); };
+ /**
+ * Connects callback to signal called when Return key is pressed.
+ */
+ boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); }
/** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
@@ -318,6 +322,10 @@ protected:
virtual bool selectItemPair(item_pair_t* item_pair, bool select);
+ virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection);
+
+ virtual bool selectAll();
+
virtual bool isSelected(item_pair_t* item_pair) const;
virtual bool removeItemPair(item_pair_t* item_pair);
@@ -331,6 +339,19 @@ protected:
*/
void notifyParentItemsRectChanged();
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ virtual BOOL postBuild();
+
+ virtual void onFocusReceived();
+
+ virtual void onFocusLost();
+
+ virtual void draw();
+
+ LLRect getLastSelectedItemRect();
+
+ LLRect getSelectedItemsRect();
private:
@@ -381,6 +402,10 @@ private:
LLRect mPrevNotifyParentRect;
LLTextBox* mNoItemsCommentTextbox;
+
+ LLViewBorder* mSelectedItemsBorder;
+
+ commit_signal_t mOnReturnSignal;
};
#endif
diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp
index 304ac64f31..a7cf9be277 100644
--- a/indra/llui/llresizebar.cpp
+++ b/indra/llui/llresizebar.cpp
@@ -143,6 +143,12 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
if( valid_rect.localPointInRect( screen_x, screen_y ) && mResizingView )
{
+ // undock floater when user resize it
+ if (((LLFloater*)getParent())->isDocked())
+ {
+ ((LLFloater*)getParent())->setDocked(false, false);
+ }
+
// Resize the parent
LLRect orig_rect = mResizingView->getRect();
LLRect scaled_rect = orig_rect;