summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llbutton.cpp12
-rw-r--r--indra/llui/llcombobox.cpp10
-rw-r--r--indra/llui/llcombobox.h1
-rw-r--r--indra/llui/llctrlselectioninterface.h1
-rw-r--r--indra/llui/llfloater.cpp22
-rw-r--r--indra/llui/llpanel.cpp34
-rw-r--r--indra/llui/llpanel.h1
-rw-r--r--indra/llui/llradiogroup.h1
-rw-r--r--indra/llui/llscrolllistctrl.cpp205
-rw-r--r--indra/llui/llscrolllistctrl.h16
-rw-r--r--indra/llui/llview.cpp35
11 files changed, 189 insertions, 149 deletions
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 6c27ccc037..435e1d1701 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -956,37 +956,37 @@ S32 round_up(S32 grid, S32 value)
void LLButton::setImageUnselected(const LLString &image_name)
{
- setImageUnselected(LLUI::getUIImageByName(image_name));
+ setImageUnselected(image_name.empty() ? NULL : LLUI::getUIImageByName(image_name));
mImageUnselectedName = image_name;
}
void LLButton::setImageSelected(const LLString &image_name)
{
- setImageSelected(LLUI::getUIImageByName(image_name));
+ setImageSelected(image_name.empty() ? NULL : LLUI::getUIImageByName(image_name));
mImageSelectedName = image_name;
}
void LLButton::setImageHoverSelected(const LLString &image_name)
{
- setImageHoverSelected(LLUI::getUIImageByName(image_name));
+ setImageHoverSelected(image_name.empty() ? NULL : LLUI::getUIImageByName(image_name));
mImageHoverSelectedName = image_name;
}
void LLButton::setImageHoverUnselected(const LLString &image_name)
{
- setImageHoverUnselected(LLUI::getUIImageByName(image_name));
+ setImageHoverUnselected(image_name.empty() ? NULL : LLUI::getUIImageByName(image_name));
mImageHoverUnselectedName = image_name;
}
void LLButton::setImageDisabled(const LLString &image_name)
{
- setImageDisabled(LLUI::getUIImageByName(image_name));
+ setImageDisabled(image_name.empty() ? NULL : LLUI::getUIImageByName(image_name));
mImageDisabledName = image_name;
}
void LLButton::setImageDisabledSelected(const LLString &image_name)
{
- setImageDisabledSelected(LLUI::getUIImageByName(image_name));
+ setImageDisabledSelected(image_name.empty() ? NULL : LLUI::getUIImageByName(image_name));
mImageDisabledSelectedName = image_name;
}
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 250ca523d2..ca02305f32 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -642,12 +642,16 @@ void LLComboBox::showList()
mList->setFocus(TRUE);
+ // register ourselves as a "top" control
+ // effectively putting us into a special draw layer
+ // and not affecting the bounding rectangle calculation
+ gFocusMgr.setTopCtrl(this);
+
// Show the list and push the button down
mButton->setToggleState(TRUE);
mList->setVisible(TRUE);
setUseBoundingRect(TRUE);
- gFocusMgr.setTopCtrl(this);
}
void LLComboBox::hideList()
@@ -1081,6 +1085,10 @@ BOOL LLComboBox::operateOnAll(EOperation op)
return FALSE;
}
+BOOL LLComboBox::selectItemRange( S32 first, S32 last )
+{
+ return mList->selectItemRange(first, last);
+}
//
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 13c2455d61..0d6c3aef2e 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -156,6 +156,7 @@ public:
virtual BOOL getCanSelect() const { return TRUE; }
virtual BOOL selectFirstItem() { return setCurrentByIndex(0); }
virtual BOOL selectNthItem( S32 index ) { return setCurrentByIndex(index); }
+ virtual BOOL selectItemRange( S32 first, S32 last );
virtual S32 getFirstSelectedIndex() const { return getCurrentIndex(); }
virtual BOOL setCurrentByID( const LLUUID& id );
virtual LLUUID getCurrentID() const; // LLUUID::null if no items in menu
diff --git a/indra/llui/llctrlselectioninterface.h b/indra/llui/llctrlselectioninterface.h
index e43e20a4c0..eb89a0833d 100644
--- a/indra/llui/llctrlselectioninterface.h
+++ b/indra/llui/llctrlselectioninterface.h
@@ -58,6 +58,7 @@ public:
virtual BOOL selectFirstItem() = 0;
virtual BOOL selectNthItem( S32 index ) = 0;
+ virtual BOOL selectItemRange( S32 first, S32 last ) = 0;
virtual S32 getFirstSelectedIndex() const = 0;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 5c1f8429d1..68719bea40 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1343,21 +1343,7 @@ void LLFloater::draw()
}
}
- if( getDefaultButton() )
- {
- if (gFocusMgr.childHasKeyboardFocus( this ) && getDefaultButton()->getEnabled())
- {
- LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- // is this button a direct descendent and not a nested widget (e.g. checkbox)?
- BOOL focus_is_child_button = focus_ctrl->getWidgetType() == WIDGET_TYPE_BUTTON && focus_ctrl->getParent() == this;
- // only enable default button when current focus is not a button
- getDefaultButton()->setBorderEnabled(!focus_is_child_button);
- }
- else
- {
- getDefaultButton()->setBorderEnabled(FALSE);
- }
- }
+ LLPanel::updateDefaultBtn();
// draw children
LLView* focused_child = gFocusMgr.getKeyboardFocus();
@@ -1368,6 +1354,7 @@ void LLFloater::draw()
focused_child->setVisible(FALSE);
}
+ // don't call LLPanel::draw() since we've implemented custom background rendering
LLView::draw();
if( isBackgroundVisible() )
@@ -2568,6 +2555,11 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
{
mTabContainer->selectTabPanel(floaterp);
}
+ else
+ {
+ // reassert visible tab (hiding new floater if necessary)
+ mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
+ }
floaterp->setHost(this);
if (isMinimized())
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 6554a25dcf..4c16683704 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -211,6 +211,11 @@ void LLPanel::draw()
}
}
+ updateDefaultBtn();
+}
+
+void LLPanel::updateDefaultBtn()
+{
if( mDefaultBtn)
{
if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
@@ -353,6 +358,13 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
if( getVisible() && getEnabled() &&
gFocusMgr.childHasKeyboardFocus(this) && !called_from_parent )
{
+ // handle user hitting ESC to defocus
+ if (key == KEY_ESCAPE)
+ {
+ gFocusMgr.setKeyboardFocus(NULL);
+ return TRUE;
+ }
+
LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
// If we have a default button, click it when
// return is pressed, unless current focus is a return-capturing button
@@ -1298,6 +1310,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
}
}
}
+ layout_stackp->updateLayout();
return layout_stackp;
}
@@ -1408,10 +1421,14 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
// panels that are not fully visible do not count towards shrink headroom
if ((*panel_it)->mVisibleAmt < 1.f)
+ {
continue;
+ }
// if currently resizing a panel or the panel is flagged as not automatically resizing
// only track total available headroom, but don't use it for automatic resize logic
- if ((*panel_it)->mResizeBar->hasMouseCapture() || (!(*panel_it)->mAutoResize && !force_resize))
+ if ((*panel_it)->mResizeBar->hasMouseCapture()
+ || (!(*panel_it)->mAutoResize
+ && !force_resize))
{
if (mOrientation == HORIZONTAL)
{
@@ -1464,7 +1481,9 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
S32 delta_size = 0;
// if panel can automatically resize (not animating, and resize flag set)...
- if ((*panel_it)->mVisibleAmt == 1.f && (force_resize || (*panel_it)->mAutoResize) && !(*panel_it)->mResizeBar->hasMouseCapture())
+ if ((*panel_it)->mVisibleAmt == 1.f
+ && (force_resize || (*panel_it)->mAutoResize)
+ && !(*panel_it)->mResizeBar->hasMouseCapture())
{
if (mOrientation == HORIZONTAL)
{
@@ -1472,7 +1491,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
if (pixels_to_distribute < 0)
{
// shrink proportionally to amount over minimum
- delta_size = llround((F32)pixels_to_distribute * (F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available);
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * (F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available) : 0;
}
else
{
@@ -1491,7 +1510,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
if (pixels_to_distribute < 0)
{
// shrink proportionally to amount over minimum
- delta_size = llround((F32)pixels_to_distribute * (F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available);
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * (F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available) : 0;
}
else
{
@@ -1583,9 +1602,10 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
}
// not enough room to fit existing contents
- if (!force_resize
- && ((cur_y != -mPanelSpacing)
- || (cur_x != getRect().getWidth() + mPanelSpacing)))
+ if (force_resize == FALSE
+ // layout did not complete by reaching target position
+ && ((mOrientation == VERTICAL && cur_y != -mPanelSpacing)
+ || (mOrientation == HORIZONTAL && cur_x != getRect().getWidth() + mPanelSpacing)))
{
// do another layout pass with all stacked elements contributing
// even those that don't usually resize
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 2fdf95df58..6c2df683e4 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -119,6 +119,7 @@ public:
BOOL isBackgroundOpaque() const { return mBgOpaque; }
void setDefaultBtn(LLButton* btn = NULL);
void setDefaultBtn(const LLString& id);
+ void updateDefaultBtn();
void setLabel(const LLStringExplicit& label) { mLabel = label; }
LLString getLabel() const { return mLabel; }
diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h
index d35bd741d7..3e01e8223c 100644
--- a/indra/llui/llradiogroup.h
+++ b/indra/llui/llradiogroup.h
@@ -121,6 +121,7 @@ public:
/*virtual*/ BOOL getCanSelect() const { return TRUE; }
/*virtual*/ BOOL selectFirstItem() { return setSelectedIndex(0); }
/*virtual*/ BOOL selectNthItem( S32 index ) { return setSelectedIndex(index); }
+ /*virtual*/ BOOL selectItemRange( S32 first, S32 last ) { return setSelectedIndex(first); }
/*virtual*/ S32 getFirstSelectedIndex() const { return getSelectedIndex(); }
/*virtual*/ BOOL setCurrentByID( const LLUUID& id );
/*virtual*/ LLUUID getCurrentID() const; // LLUUID::null if no items in menu
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 94053980e6..4227a34777 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -220,22 +220,14 @@ LLScrollListText::LLScrollListText( const LLString& text, const LLFontGL* font,
: LLScrollListCell(width),
mText( text ),
mFont( font ),
+ mColor(color),
+ mUseColor(use_color),
mFontStyle( font_style ),
mFontAlignment( font_alignment ),
mVisible( visible ),
mHighlightCount( 0 ),
mHighlightOffset( 0 )
{
- if (use_color)
- {
- mColor = new LLColor4();
- mColor->setVec(color);
- }
- else
- {
- mColor = NULL;
- }
-
sCount++;
// initialize rounded rect image
@@ -248,7 +240,6 @@ LLScrollListText::LLScrollListText( const LLString& text, const LLFontGL* font,
LLScrollListText::~LLScrollListText()
{
sCount--;
- delete mColor;
}
S32 LLScrollListText::getContentWidth() const
@@ -259,11 +250,8 @@ S32 LLScrollListText::getContentWidth() const
void LLScrollListText::setColor(const LLColor4& color)
{
- if (!mColor)
- {
- mColor = new LLColor4();
- }
- *mColor = color;
+ mColor = color;
+ mUseColor = TRUE;
}
void LLScrollListText::setText(const LLStringExplicit& text)
@@ -279,14 +267,14 @@ void LLScrollListText::setValue(const LLSD& text)
void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_color) const
{
- const LLColor4* display_color;
- if (mColor)
+ LLColor4 display_color;
+ if (mUseColor)
{
display_color = mColor;
}
else
{
- display_color = &color;
+ display_color = color;
}
if (mHighlightCount > 0)
@@ -333,7 +321,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
}
mFont->render(mText.getWString(), 0,
start_x, 2.f,
- *display_color,
+ display_color,
mFontAlignment,
LLFontGL::BOTTOM,
mFontStyle,
@@ -524,6 +512,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mNeedsScroll(FALSE),
mCanSelect(TRUE),
mDisplayColumnHeaders(FALSE),
+ mColumnsDirty(FALSE),
mMaxItemCount(INT_MAX),
mMaxContentWidth(0),
mBackgroundVisible( TRUE ),
@@ -636,7 +625,6 @@ void LLScrollListCtrl::clearRows()
mScrollLines = 0;
mLastSelected = NULL;
- calcMaxContentWidth(NULL);
updateLayout();
mDirty = FALSE;
}
@@ -768,7 +756,7 @@ void LLScrollListCtrl::updateLayout()
mScrollbar->setDocSize( getItemCount() );
mScrollbar->setVisible(scrollbar_visible);
- updateColumns();
+ dirtyColumns();
}
// Attempt to size the control to show all items.
@@ -846,7 +834,6 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
}
updateLineHeightInsert(item);
- calcMaxContentWidth(item);
updateLayout();
}
@@ -854,17 +841,14 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
return not_too_big;
}
-void LLScrollListCtrl::calcMaxContentWidth(LLScrollListItem* added_item)
+void LLScrollListCtrl::calcColumnWidths()
{
const S32 HEADING_TEXT_PADDING = 30;
const S32 COLUMN_TEXT_PADDING = 20;
- if (added_item == NULL)
- {
- mMaxContentWidth = 0;
- }
+ mMaxContentWidth = 0;
- S32 item_content_width = 0;
+ S32 max_item_width = 0;
ordered_columns_t::iterator column_itor;
for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor)
@@ -872,31 +856,37 @@ void LLScrollListCtrl::calcMaxContentWidth(LLScrollListItem* added_item)
LLScrollListColumn* column = *column_itor;
if (!column) continue;
- if (!added_item)
+ // update column width
+ S32 new_width = column->mWidth;
+ if (column->mRelWidth >= 0)
{
- // update on all items
- column->mMaxContentWidth = column->mHeader ? LLFontGL::sSansSerifSmall->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0;
- item_list::iterator iter;
- for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
- {
- LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex);
- if (!cellp) continue;
+ new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth());
+ }
+ else if (column->mDynamicWidth)
+ {
+ new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
+ }
- column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
- }
+ if (new_width != column->mWidth)
+ {
+ column->mWidth = new_width;
}
- else
+
+ // update max content width for this column, by looking at all items
+ column->mMaxContentWidth = column->mHeader ? LLFontGL::sSansSerifSmall->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0;
+ item_list::iterator iter;
+ for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
- LLScrollListCell* cellp = added_item->getColumn(column->mIndex);
+ LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex);
if (!cellp) continue;
column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
}
- item_content_width += column->mMaxContentWidth;
+ max_item_width += column->mMaxContentWidth;
}
- mMaxContentWidth = llmax(mMaxContentWidth, item_content_width);
+ mMaxContentWidth = max_item_width;
}
const S32 SCROLL_LIST_ROW_PAD = 2;
@@ -932,29 +922,9 @@ void LLScrollListCtrl::updateLineHeightInsert(LLScrollListItem* itemp)
void LLScrollListCtrl::updateColumns()
{
- mColumnsIndexed.resize(mColumns.size());
-
- std::map<LLString, LLScrollListColumn>::iterator column_itor;
- for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
- {
- LLScrollListColumn *column = &column_itor->second;
- S32 new_width = column->mWidth;
- if (column->mRelWidth >= 0)
- {
- new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth());
- }
- else if (column->mDynamicWidth)
- {
- new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
- }
-
- if (new_width != column->mWidth)
- {
- column->mWidth = new_width;
- }
- mColumnsIndexed[column_itor->second.mIndex] = column;
- }
+ calcColumnWidths();
+ // propagate column widths to individual cells
item_list::iterator iter;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
@@ -969,7 +939,7 @@ void LLScrollListCtrl::updateColumns()
}
}
- // update headers
+ // update column headers
std::vector<LLScrollListColumn*>::iterator column_ordered_it;
S32 left = mItemListRect.mLeft;
LLColumnHeader* last_header = NULL;
@@ -1004,6 +974,7 @@ void LLScrollListCtrl::updateColumns()
}
}
+ //FIXME: stretch the entire last column if it is resizable (gestures windows shows truncated text in last column)
// expand last column header we encountered to full list width
if (last_header)
{
@@ -1061,28 +1032,42 @@ BOOL LLScrollListCtrl::selectFirstItem()
return success;
}
-
+// Deselects all other items
+// virtual
BOOL LLScrollListCtrl::selectNthItem( S32 target_index )
{
- if (mItemList.empty()) return FALSE;
+ return selectItemRange(target_index, target_index);
+}
- // Deselects all other items
- BOOL success = FALSE;
- S32 index = 0;
+// virtual
+BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index )
+{
+ if (mItemList.empty())
+ {
+ return FALSE;
+ }
- target_index = llclamp(target_index, 0, (S32)mItemList.size() - 1);
+ S32 listlen = (S32)mItemList.size();
+ first_index = llclamp(first_index, 0, listlen-1);
+
+ if (last_index < 0)
+ last_index = listlen-1;
+ else
+ last_index = llclamp(last_index, first_index, listlen-1);
- item_list::iterator iter;
- for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
+ BOOL success = FALSE;
+ S32 index = 0;
+ for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
LLScrollListItem *itemp = *iter;
- if( target_index == index )
+ if( index >= first_index && index <= last_index )
{
if( itemp->getEnabled() )
{
- selectItem(itemp);
+ selectItem(itemp, FALSE);
success = TRUE;
- mOriginalSelection = target_index;
+ if (!success)
+ mOriginalSelection = first_index;
}
}
else
@@ -1131,7 +1116,7 @@ void LLScrollListCtrl::swapWithPrevious(S32 index)
void LLScrollListCtrl::deleteSingleItem(S32 target_index)
{
- if (target_index >= (S32)mItemList.size())
+ if (target_index < 0 || target_index >= (S32)mItemList.size())
{
return;
}
@@ -1144,7 +1129,7 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index)
}
delete itemp;
mItemList.erase(mItemList.begin() + target_index);
- calcMaxContentWidth(NULL);
+ dirtyColumns();
}
//FIXME: refactor item deletion
@@ -1169,7 +1154,7 @@ void LLScrollListCtrl::deleteItems(const LLSD& sd)
}
}
- calcMaxContentWidth(NULL);
+ dirtyColumns();
}
void LLScrollListCtrl::deleteSelectedItems()
@@ -1189,7 +1174,7 @@ void LLScrollListCtrl::deleteSelectedItems()
}
}
mLastSelected = NULL;
- calcMaxContentWidth(NULL);
+ dirtyColumns();
}
void LLScrollListCtrl::highlightNthItem(S32 target_index)
@@ -1243,7 +1228,7 @@ S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const
return -1;
}
-S32 LLScrollListCtrl::getItemIndex( LLUUID& target_id ) const
+S32 LLScrollListCtrl::getItemIndex( const LLUUID& target_id ) const
{
S32 index = 0;
item_list::const_iterator iter;
@@ -1730,6 +1715,12 @@ void LLScrollListCtrl::draw()
gl_rect_2d(background);
}
+ if (mColumnsDirty)
+ {
+ updateColumns();
+ mColumnsDirty = FALSE;
+ }
+
drawItems();
if (mBorder)
@@ -1996,9 +1987,8 @@ BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask)
gFocusMgr.setMouseCapture(this);
mNeedsScroll = TRUE;
}
- // otherwise we already have this item selected
- // so propagate state of cell to rest of selected column
- else
+
+ // propagate state of cell to rest of selected column
{
// propagate value of this cell to other selected items
// and commit the respective widgets
@@ -2534,6 +2524,23 @@ void LLScrollListCtrl::sortItems()
setSorted(TRUE);
}
+void LLScrollListCtrl::dirtyColumns()
+{
+ mColumnsDirty = TRUE;
+
+ // need to keep mColumnsIndexed up to date
+ // just in case someone indexes into it immediately
+ mColumnsIndexed.resize(mColumns.size());
+
+ std::map<LLString, LLScrollListColumn>::iterator column_itor;
+ for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
+ {
+ LLScrollListColumn *column = &column_itor->second;
+ mColumnsIndexed[column_itor->second.mIndex] = column;
+ }
+}
+
+
S32 LLScrollListCtrl::getScrollPos() const
{
return mScrollbar->getDocPos();
@@ -2724,6 +2731,12 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
S32 search_column = 0;
node->getAttributeS32("search_column", search_column);
+ S32 sort_column = -1;
+ node->getAttributeS32("sort_column", sort_column);
+
+ BOOL sort_ascending = TRUE;
+ node->getAttributeBOOL("sort_ascending", sort_ascending);
+
LLUICtrlCallback callback = NULL;
LLScrollListCtrl* scroll_list = new LLScrollListCtrl(
@@ -2748,6 +2761,11 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
scroll_list->setSearchColumn(search_column);
+ if (sort_column >= 0)
+ {
+ scroll_list->sortByColumn(sort_column, sort_ascending);
+ }
+
LLSD columns;
S32 index = 0;
LLXMLNodePtr child;
@@ -3010,7 +3028,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
}
}
- updateColumns();
+ dirtyColumns();
}
// static
@@ -3241,13 +3259,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
col_index++;
}
- S32 num_columns = mColumns.size();
- for (S32 column = 0; column < num_columns; ++column)
+ // add dummy cells for missing columns
+ for (column_map_t::iterator column_it = mColumns.begin(); column_it != mColumns.end(); ++column_it)
{
- if (new_item->getColumn(column) == NULL)
+ S32 column_idx = column_it->second.mIndex;
+ if (new_item->getColumn(column_idx) == NULL)
{
- LLScrollListColumn* column_ptr = mColumnsIndexed[column];
- new_item->setColumn(column, new LLScrollListText("", gResMgr->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->mWidth, LLFontGL::NORMAL));
+ LLScrollListColumn* column_ptr = &column_it->second;
+ new_item->setColumn(column_idx, new LLScrollListText("", gResMgr->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->mWidth, LLFontGL::NORMAL));
}
}
@@ -3649,7 +3668,7 @@ LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_d
void LLColumnHeader::userSetShape(const LLRect& new_rect)
{
S32 new_width = new_rect.getWidth();
- S32 delta_width = new_width - getRect().getWidth();
+ S32 delta_width = new_width - (getRect().getWidth() /*+ mColumn->mParentCtrl->getColumnPadding()*/);
if (delta_width != 0)
{
@@ -3721,6 +3740,8 @@ void LLColumnHeader::userSetShape(const LLRect& new_rect)
}
// tell scroll list to layout columns again
+ // do immediate update to get proper feedback to resize handle
+ // which needs to know how far the resize actually went
mColumn->mParentCtrl->updateColumns();
}
}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index d889512ee6..6edb2939dd 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -120,7 +120,8 @@ public:
private:
LLUIString mText;
const LLFontGL* mFont;
- LLColor4* mColor;
+ LLColor4 mColor;
+ U8 mUseColor;
U8 mFontStyle;
LLFontGL::HAlign mFontAlignment;
BOOL mVisible;
@@ -467,6 +468,7 @@ public:
BOOL handleClick(S32 x, S32 y, MASK mask);
BOOL selectFirstItem();
BOOL selectNthItem( S32 index );
+ BOOL selectItemRange( S32 first, S32 last );
BOOL selectItemAt(S32 x, S32 y, MASK mask);
void deleteSingleItem( S32 index );
@@ -486,7 +488,7 @@ public:
virtual BOOL getCanSelect() const { return mCanSelect; }
S32 getItemIndex( LLScrollListItem* item ) const;
- S32 getItemIndex( LLUUID& item_id ) const;
+ S32 getItemIndex( const LLUUID& item_id ) const;
LLScrollListItem* addCommentText( const LLString& comment_text, EAddPosition pos = ADD_BOTTOM);
LLScrollListItem* addSeparator(EAddPosition pos);
@@ -587,7 +589,7 @@ public:
static void onClickColumn(void *userdata);
void updateColumns();
- void calcMaxContentWidth(LLScrollListItem* changed_item);
+ void calcColumnWidths();
S32 getMaxContentWidth() { return mMaxContentWidth; }
void setDisplayHeading(BOOL display);
@@ -616,6 +618,9 @@ public:
S32 selectMultiple( LLDynamicArray<LLUUID> ids );
void sortItems();
+ // manually call this whenever editing list items in place to flag need for resorting
+ void setSorted(BOOL sorted) { mSorted = sorted; }
+ void dirtyColumns(); // some operation has potentially affected column layout or ordering
protected:
// "Full" interface: use this when you're creating a list that has one or more of the following:
@@ -649,7 +654,6 @@ private:
void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
void deselectItem(LLScrollListItem* itemp);
void commitIfChanged();
- void setSorted(BOOL sorted) { mSorted = sorted; }
BOOL setSort(S32 column, BOOL ascending);
@@ -670,6 +674,7 @@ private:
BOOL mNeedsScroll;
BOOL mCanSelect;
BOOL mDisplayColumnHeaders;
+ BOOL mColumnsDirty;
item_list mItemList;
@@ -710,7 +715,8 @@ private:
BOOL mSorted;
- std::map<LLString, LLScrollListColumn> mColumns;
+ typedef std::map<LLString, LLScrollListColumn> column_map_t;
+ column_map_t mColumns;
BOOL mDirty;
S32 mOriginalSelection;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 1014f17898..56e24085ac 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -760,18 +760,10 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
}
}
- if( !handled && !called_from_parent)
+ if( !handled && !called_from_parent && mParentView)
{
- if (mIsFocusRoot)
- {
- // stop processing at focus root
- handled = FALSE;
- }
- else if (mParentView)
- {
- // Upward traversal
- handled = mParentView->handleKey( key, mask, FALSE );
- }
+ // Upward traversal
+ handled = mParentView->handleKey( key, mask, FALSE );
}
return handled;
}
@@ -806,18 +798,10 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
}
- if (!handled && !called_from_parent)
+ if (!handled && !called_from_parent && mParentView)
{
- if (mIsFocusRoot)
- {
- // stop processing at focus root
- handled = FALSE;
- }
- else if(mParentView)
- {
- // Upward traversal
- handled = mParentView->handleUnicodeChar(uni_char, FALSE);
- }
+ // Upward traversal
+ handled = mParentView->handleUnicodeChar(uni_char, FALSE);
}
return handled;
@@ -1448,7 +1432,12 @@ void LLView::updateBoundingRect()
for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
LLView* childp = *child_it;
- if (!childp->getVisible()) continue;
+ // ignore invisible and "top" children when calculating bounding rect
+ // such as combobox popups
+ if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
+ {
+ continue;
+ }
LLRect child_bounding_rect = childp->getBoundingRect();