aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:29 -0500
committerJacek Antonelli2008-08-15 23:45:29 -0500
commit7bdb4845afdd157f95281293803567090e3f992a (patch)
treefbcada1c227d7407f9f37ccba360bfe6326d9c5e /linden/indra/llui
parentSecond Life viewer sources 1.19.0.0 (diff)
downloadmeta-impy-7bdb4845afdd157f95281293803567090e3f992a.zip
meta-impy-7bdb4845afdd157f95281293803567090e3f992a.tar.gz
meta-impy-7bdb4845afdd157f95281293803567090e3f992a.tar.bz2
meta-impy-7bdb4845afdd157f95281293803567090e3f992a.tar.xz
Second Life viewer sources 1.19.0.2
Diffstat (limited to '')
-rw-r--r--linden/indra/llui/llcombobox.cpp6
-rw-r--r--linden/indra/llui/llcombobox.h1
-rw-r--r--linden/indra/llui/llctrlselectioninterface.h1
-rw-r--r--linden/indra/llui/llfloater.cpp5
-rw-r--r--linden/indra/llui/llpanel.cpp29
-rw-r--r--linden/indra/llui/llradiogroup.h1
-rw-r--r--linden/indra/llui/llscrolllistctrl.cpp175
-rw-r--r--linden/indra/llui/llscrolllistctrl.h14
-rw-r--r--linden/indra/llui/llview.cpp35
9 files changed, 161 insertions, 106 deletions
diff --git a/linden/indra/llui/llcombobox.cpp b/linden/indra/llui/llcombobox.cpp
index 22b5033..96092b4 100644
--- a/linden/indra/llui/llcombobox.cpp
+++ b/linden/indra/llui/llcombobox.cpp
@@ -648,12 +648,16 @@ void LLComboBox::showList()
648 } 648 }
649 mList->setFocus(TRUE); 649 mList->setFocus(TRUE);
650 650
651 // register ourselves as a "top" control
652 // effectively putting us into a special draw layer
653 // and not affecting the bounding rectangle calculation
654 gFocusMgr.setTopCtrl(this);
655
651 // Show the list and push the button down 656 // Show the list and push the button down
652 mButton->setToggleState(TRUE); 657 mButton->setToggleState(TRUE);
653 mList->setVisible(TRUE); 658 mList->setVisible(TRUE);
654 659
655 setUseBoundingRect(TRUE); 660 setUseBoundingRect(TRUE);
656 gFocusMgr.setTopCtrl(this);
657} 661}
658 662
659void LLComboBox::hideList() 663void LLComboBox::hideList()
diff --git a/linden/indra/llui/llcombobox.h b/linden/indra/llui/llcombobox.h
index 2a70db2..7511449 100644
--- a/linden/indra/llui/llcombobox.h
+++ b/linden/indra/llui/llcombobox.h
@@ -156,6 +156,7 @@ public:
156 virtual BOOL getCanSelect() const { return TRUE; } 156 virtual BOOL getCanSelect() const { return TRUE; }
157 virtual BOOL selectFirstItem() { return setCurrentByIndex(0); } 157 virtual BOOL selectFirstItem() { return setCurrentByIndex(0); }
158 virtual BOOL selectNthItem( S32 index ) { return setCurrentByIndex(index); } 158 virtual BOOL selectNthItem( S32 index ) { return setCurrentByIndex(index); }
159 virtual BOOL selectItemRange( S32 first, S32 last ) { return setCurrentByIndex(first); }
159 virtual S32 getFirstSelectedIndex() const { return getCurrentIndex(); } 160 virtual S32 getFirstSelectedIndex() const { return getCurrentIndex(); }
160 virtual BOOL setCurrentByID( const LLUUID& id ); 161 virtual BOOL setCurrentByID( const LLUUID& id );
161 virtual LLUUID getCurrentID(); // LLUUID::null if no items in menu 162 virtual LLUUID getCurrentID(); // LLUUID::null if no items in menu
diff --git a/linden/indra/llui/llctrlselectioninterface.h b/linden/indra/llui/llctrlselectioninterface.h
index 121d971..b4d3fc0 100644
--- a/linden/indra/llui/llctrlselectioninterface.h
+++ b/linden/indra/llui/llctrlselectioninterface.h
@@ -58,6 +58,7 @@ public:
58 58
59 virtual BOOL selectFirstItem() = 0; 59 virtual BOOL selectFirstItem() = 0;
60 virtual BOOL selectNthItem( S32 index ) = 0; 60 virtual BOOL selectNthItem( S32 index ) = 0;
61 virtual BOOL selectItemRange( S32 first, S32 last ) = 0;
61 62
62 virtual S32 getFirstSelectedIndex() const = 0; 63 virtual S32 getFirstSelectedIndex() const = 0;
63 64
diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp
index 1500f9f..496b67f 100644
--- a/linden/indra/llui/llfloater.cpp
+++ b/linden/indra/llui/llfloater.cpp
@@ -2735,6 +2735,11 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
2735 { 2735 {
2736 mTabContainer->selectTabPanel(floaterp); 2736 mTabContainer->selectTabPanel(floaterp);
2737 } 2737 }
2738 else
2739 {
2740 // reassert visible tab (hiding new floater if necessary)
2741 mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
2742 }
2738 2743
2739 floaterp->setHost(this); 2744 floaterp->setHost(this);
2740 if (mMinimized) 2745 if (mMinimized)
diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp
index af8aa21..7430e50 100644
--- a/linden/indra/llui/llpanel.cpp
+++ b/linden/indra/llui/llpanel.cpp
@@ -356,6 +356,13 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
356 if( getVisible() && getEnabled() && 356 if( getVisible() && getEnabled() &&
357 gFocusMgr.childHasKeyboardFocus(this) && !called_from_parent ) 357 gFocusMgr.childHasKeyboardFocus(this) && !called_from_parent )
358 { 358 {
359 // handle user hitting ESC to defocus
360 if (key == KEY_ESCAPE)
361 {
362 gFocusMgr.setKeyboardFocus(NULL);
363 return TRUE;
364 }
365
359 LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); 366 LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
360 // If we have a default button, click it when 367 // If we have a default button, click it when
361 // return is pressed, unless current focus is a return-capturing button 368 // return is pressed, unless current focus is a return-capturing button
@@ -1322,6 +1329,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
1322 } 1329 }
1323 } 1330 }
1324 } 1331 }
1332 layout_stackp->updateLayout();
1325 1333
1326 return layout_stackp; 1334 return layout_stackp;
1327} 1335}
@@ -1442,10 +1450,14 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1442 { 1450 {
1443 // panels that are not fully visible do not count towards shrink headroom 1451 // panels that are not fully visible do not count towards shrink headroom
1444 if ((*panel_it)->mVisibleAmt < 1.f) 1452 if ((*panel_it)->mVisibleAmt < 1.f)
1453 {
1445 continue; 1454 continue;
1455 }
1446 // if currently resizing a panel or the panel is flagged as not automatically resizing 1456 // if currently resizing a panel or the panel is flagged as not automatically resizing
1447 // only track total available headroom, but don't use it for automatic resize logic 1457 // only track total available headroom, but don't use it for automatic resize logic
1448 if ((*panel_it)->mResizeBar->hasMouseCapture() || (!(*panel_it)->mAutoResize && !force_resize)) 1458 if ((*panel_it)->mResizeBar->hasMouseCapture()
1459 || (!(*panel_it)->mAutoResize
1460 && !force_resize))
1449 { 1461 {
1450 if (mOrientation == HORIZONTAL) 1462 if (mOrientation == HORIZONTAL)
1451 { 1463 {
@@ -1498,7 +1510,9 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1498 S32 delta_size = 0; 1510 S32 delta_size = 0;
1499 1511
1500 // if panel can automatically resize (not animating, and resize flag set)... 1512 // if panel can automatically resize (not animating, and resize flag set)...
1501 if ((*panel_it)->mVisibleAmt == 1.f && (force_resize || (*panel_it)->mAutoResize) && !(*panel_it)->mResizeBar->hasMouseCapture()) 1513 if ((*panel_it)->mVisibleAmt == 1.f
1514 && (force_resize || (*panel_it)->mAutoResize)
1515 && !(*panel_it)->mResizeBar->hasMouseCapture())
1502 { 1516 {
1503 if (mOrientation == HORIZONTAL) 1517 if (mOrientation == HORIZONTAL)
1504 { 1518 {
@@ -1506,7 +1520,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1506 if (pixels_to_distribute < 0) 1520 if (pixels_to_distribute < 0)
1507 { 1521 {
1508 // shrink proportionally to amount over minimum 1522 // shrink proportionally to amount over minimum
1509 delta_size = llround((F32)pixels_to_distribute * (F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available); 1523 delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * (F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available) : 0;
1510 } 1524 }
1511 else 1525 else
1512 { 1526 {
@@ -1525,7 +1539,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1525 if (pixels_to_distribute < 0) 1539 if (pixels_to_distribute < 0)
1526 { 1540 {
1527 // shrink proportionally to amount over minimum 1541 // shrink proportionally to amount over minimum
1528 delta_size = llround((F32)pixels_to_distribute * (F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available); 1542 delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * (F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available) : 0;
1529 } 1543 }
1530 else 1544 else
1531 { 1545 {
@@ -1617,9 +1631,10 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
1617 } 1631 }
1618 1632
1619 // not enough room to fit existing contents 1633 // not enough room to fit existing contents
1620 if (!force_resize 1634 if (force_resize == FALSE
1621 && ((cur_y != -mPanelSpacing) 1635 // layout did not complete by reaching target position
1622 || (cur_x != mRect.getWidth() + mPanelSpacing))) 1636 && ((mOrientation == VERTICAL && cur_y != -mPanelSpacing)
1637 || (mOrientation == HORIZONTAL && cur_x != mRect.getWidth() + mPanelSpacing)))
1623 { 1638 {
1624 // do another layout pass with all stacked elements contributing 1639 // do another layout pass with all stacked elements contributing
1625 // even those that don't usually resize 1640 // even those that don't usually resize
diff --git a/linden/indra/llui/llradiogroup.h b/linden/indra/llui/llradiogroup.h
index e0a4168..aed8de2 100644
--- a/linden/indra/llui/llradiogroup.h
+++ b/linden/indra/llui/llradiogroup.h
@@ -118,6 +118,7 @@ public:
118 /*virtual*/ BOOL getCanSelect() const { return TRUE; } 118 /*virtual*/ BOOL getCanSelect() const { return TRUE; }
119 /*virtual*/ BOOL selectFirstItem() { return setSelectedIndex(0); } 119 /*virtual*/ BOOL selectFirstItem() { return setSelectedIndex(0); }
120 /*virtual*/ BOOL selectNthItem( S32 index ) { return setSelectedIndex(index); } 120 /*virtual*/ BOOL selectNthItem( S32 index ) { return setSelectedIndex(index); }
121 /*virtual*/ BOOL selectItemRange( S32 first, S32 last ) { return setSelectedIndex(first); }
121 /*virtual*/ S32 getFirstSelectedIndex() const { return getSelectedIndex(); } 122 /*virtual*/ S32 getFirstSelectedIndex() const { return getSelectedIndex(); }
122 /*virtual*/ BOOL setCurrentByID( const LLUUID& id ); 123 /*virtual*/ BOOL setCurrentByID( const LLUUID& id );
123 /*virtual*/ LLUUID getCurrentID(); // LLUUID::null if no items in menu 124 /*virtual*/ LLUUID getCurrentID(); // LLUUID::null if no items in menu
diff --git a/linden/indra/llui/llscrolllistctrl.cpp b/linden/indra/llui/llscrolllistctrl.cpp
index d65ebd2..36a7b00 100644
--- a/linden/indra/llui/llscrolllistctrl.cpp
+++ b/linden/indra/llui/llscrolllistctrl.cpp
@@ -518,6 +518,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
518 mNeedsScroll(FALSE), 518 mNeedsScroll(FALSE),
519 mCanSelect(TRUE), 519 mCanSelect(TRUE),
520 mDisplayColumnHeaders(FALSE), 520 mDisplayColumnHeaders(FALSE),
521 mColumnsDirty(FALSE),
521 mMaxItemCount(INT_MAX), 522 mMaxItemCount(INT_MAX),
522 mMaxContentWidth(0), 523 mMaxContentWidth(0),
523 mBackgroundVisible( TRUE ), 524 mBackgroundVisible( TRUE ),
@@ -630,7 +631,6 @@ void LLScrollListCtrl::clearRows()
630 631
631 mScrollLines = 0; 632 mScrollLines = 0;
632 mLastSelected = NULL; 633 mLastSelected = NULL;
633 calcMaxContentWidth(NULL);
634 updateLayout(); 634 updateLayout();
635 mDirty = FALSE; 635 mDirty = FALSE;
636} 636}
@@ -762,7 +762,7 @@ void LLScrollListCtrl::updateLayout()
762 mScrollbar->setDocSize( getItemCount() ); 762 mScrollbar->setDocSize( getItemCount() );
763 mScrollbar->setVisible(scrollbar_visible); 763 mScrollbar->setVisible(scrollbar_visible);
764 764
765 updateColumns(); 765 dirtyColumns();
766} 766}
767 767
768// Attempt to size the control to show all items. 768// Attempt to size the control to show all items.
@@ -840,7 +840,6 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
840 } 840 }
841 841
842 updateLineHeightInsert(item); 842 updateLineHeightInsert(item);
843 calcMaxContentWidth(item);
844 843
845 updateLayout(); 844 updateLayout();
846 } 845 }
@@ -848,17 +847,14 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
848 return not_too_big; 847 return not_too_big;
849} 848}
850 849
851void LLScrollListCtrl::calcMaxContentWidth(LLScrollListItem* added_item) 850void LLScrollListCtrl::calcColumnWidths()
852{ 851{
853 const S32 HEADING_TEXT_PADDING = 30; 852 const S32 HEADING_TEXT_PADDING = 30;
854 const S32 COLUMN_TEXT_PADDING = 20; 853 const S32 COLUMN_TEXT_PADDING = 20;
855 854
856 if (added_item == NULL) 855 mMaxContentWidth = 0;
857 {
858 mMaxContentWidth = 0;
859 }
860 856
861 S32 item_content_width = 0; 857 S32 max_item_width = 0;
862 858
863 ordered_columns_t::iterator column_itor; 859 ordered_columns_t::iterator column_itor;
864 for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor) 860 for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor)
@@ -866,31 +862,37 @@ void LLScrollListCtrl::calcMaxContentWidth(LLScrollListItem* added_item)
866 LLScrollListColumn* column = *column_itor; 862 LLScrollListColumn* column = *column_itor;
867 if (!column) continue; 863 if (!column) continue;
868 864
869 if (!added_item) 865 // update column width
866 S32 new_width = column->mWidth;
867 if (column->mRelWidth >= 0)
870 { 868 {
871 // update on all items 869 new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth());
872 column->mMaxContentWidth = column->mHeader ? LLFontGL::sSansSerifSmall->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; 870 }
873 item_list::iterator iter; 871 else if (column->mDynamicWidth)
874 for (iter = mItemList.begin(); iter != mItemList.end(); iter++) 872 {
875 { 873 new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
876 LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); 874 }
877 if (!cellp) continue;
878 875
879 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); 876 if (new_width != column->mWidth)
880 } 877 {
878 column->mWidth = new_width;
881 } 879 }
882 else 880
881 // update max content width for this column, by looking at all items
882 column->mMaxContentWidth = column->mHeader ? LLFontGL::sSansSerifSmall->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0;
883 item_list::iterator iter;
884 for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
883 { 885 {
884 LLScrollListCell* cellp = added_item->getColumn(column->mIndex); 886 LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex);
885 if (!cellp) continue; 887 if (!cellp) continue;
886 888
887 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); 889 column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth);
888 } 890 }
889 891
890 item_content_width += column->mMaxContentWidth; 892 max_item_width += column->mMaxContentWidth;
891 } 893 }
892 894
893 mMaxContentWidth = llmax(mMaxContentWidth, item_content_width); 895 mMaxContentWidth = max_item_width;
894} 896}
895 897
896const S32 SCROLL_LIST_ROW_PAD = 2; 898const S32 SCROLL_LIST_ROW_PAD = 2;
@@ -926,29 +928,9 @@ void LLScrollListCtrl::updateLineHeightInsert(LLScrollListItem* itemp)
926 928
927void LLScrollListCtrl::updateColumns() 929void LLScrollListCtrl::updateColumns()
928{ 930{
929 mColumnsIndexed.resize(mColumns.size()); 931 calcColumnWidths();
930
931 std::map<LLString, LLScrollListColumn>::iterator column_itor;
932 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
933 {
934 LLScrollListColumn *column = &column_itor->second;
935 S32 new_width = column->mWidth;
936 if (column->mRelWidth >= 0)
937 {
938 new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth());
939 }
940 else if (column->mDynamicWidth)
941 {
942 new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
943 }
944
945 if (new_width != column->mWidth)
946 {
947 column->mWidth = new_width;
948 }
949 mColumnsIndexed[column_itor->second.mIndex] = column;
950 }
951 932
933 // propagate column widths to individual cells
952 item_list::iterator iter; 934 item_list::iterator iter;
953 for (iter = mItemList.begin(); iter != mItemList.end(); iter++) 935 for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
954 { 936 {
@@ -963,7 +945,7 @@ void LLScrollListCtrl::updateColumns()
963 } 945 }
964 } 946 }
965 947
966 // update headers 948 // update column headers
967 std::vector<LLScrollListColumn*>::iterator column_ordered_it; 949 std::vector<LLScrollListColumn*>::iterator column_ordered_it;
968 S32 left = mItemListRect.mLeft; 950 S32 left = mItemListRect.mLeft;
969 LLColumnHeader* last_header = NULL; 951 LLColumnHeader* last_header = NULL;
@@ -998,6 +980,7 @@ void LLScrollListCtrl::updateColumns()
998 } 980 }
999 } 981 }
1000 982
983 //FIXME: stretch the entire last column if it is resizable (gestures windows shows truncated text in last column)
1001 // expand last column header we encountered to full list width 984 // expand last column header we encountered to full list width
1002 if (last_header) 985 if (last_header)
1003 { 986 {
@@ -1055,28 +1038,42 @@ BOOL LLScrollListCtrl::selectFirstItem()
1055 return success; 1038 return success;
1056} 1039}
1057 1040
1058 1041// Deselects all other items
1042// virtual
1059BOOL LLScrollListCtrl::selectNthItem( S32 target_index ) 1043BOOL LLScrollListCtrl::selectNthItem( S32 target_index )
1060{ 1044{
1061 if (mItemList.empty()) return FALSE; 1045 return selectItemRange(target_index, target_index);
1046}
1062 1047
1063 // Deselects all other items 1048// virtual
1064 BOOL success = FALSE; 1049BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index )
1065 S32 index = 0; 1050{
1051 if (mItemList.empty())
1052 {
1053 return FALSE;
1054 }
1066 1055
1067 target_index = llclamp(target_index, 0, (S32)mItemList.size() - 1); 1056 S32 listlen = (S32)mItemList.size();
1057 first_index = llclamp(first_index, 0, listlen-1);
1058
1059 if (last_index < 0)
1060 last_index = listlen-1;
1061 else
1062 last_index = llclamp(last_index, first_index, listlen-1);
1068 1063
1069 item_list::iterator iter; 1064 BOOL success = FALSE;
1070 for (iter = mItemList.begin(); iter != mItemList.end(); iter++) 1065 S32 index = 0;
1066 for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); iter++)
1071 { 1067 {
1072 LLScrollListItem *itemp = *iter; 1068 LLScrollListItem *itemp = *iter;
1073 if( target_index == index ) 1069 if( index >= first_index && index <= last_index )
1074 { 1070 {
1075 if( itemp->getEnabled() ) 1071 if( itemp->getEnabled() )
1076 { 1072 {
1077 selectItem(itemp); 1073 selectItem(itemp);
1078 success = TRUE; 1074 success = TRUE;
1079 mOriginalSelection = target_index; 1075 if (!success)
1076 mOriginalSelection = first_index;
1080 } 1077 }
1081 } 1078 }
1082 else 1079 else
@@ -1125,7 +1122,7 @@ void LLScrollListCtrl::swapWithPrevious(S32 index)
1125 1122
1126void LLScrollListCtrl::deleteSingleItem(S32 target_index) 1123void LLScrollListCtrl::deleteSingleItem(S32 target_index)
1127{ 1124{
1128 if (target_index >= (S32)mItemList.size()) 1125 if (target_index < 0 || target_index >= (S32)mItemList.size())
1129 { 1126 {
1130 return; 1127 return;
1131 } 1128 }
@@ -1138,7 +1135,7 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index)
1138 } 1135 }
1139 delete itemp; 1136 delete itemp;
1140 mItemList.erase(mItemList.begin() + target_index); 1137 mItemList.erase(mItemList.begin() + target_index);
1141 calcMaxContentWidth(NULL); 1138 dirtyColumns();
1142} 1139}
1143 1140
1144//FIXME: refactor item deletion 1141//FIXME: refactor item deletion
@@ -1163,7 +1160,7 @@ void LLScrollListCtrl::deleteItems(const LLSD& sd)
1163 } 1160 }
1164 } 1161 }
1165 1162
1166 calcMaxContentWidth(NULL); 1163 dirtyColumns();
1167} 1164}
1168 1165
1169void LLScrollListCtrl::deleteSelectedItems() 1166void LLScrollListCtrl::deleteSelectedItems()
@@ -1183,7 +1180,7 @@ void LLScrollListCtrl::deleteSelectedItems()
1183 } 1180 }
1184 } 1181 }
1185 mLastSelected = NULL; 1182 mLastSelected = NULL;
1186 calcMaxContentWidth(NULL); 1183 dirtyColumns();
1187} 1184}
1188 1185
1189void LLScrollListCtrl::highlightNthItem(S32 target_index) 1186void LLScrollListCtrl::highlightNthItem(S32 target_index)
@@ -1237,7 +1234,7 @@ S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item )
1237 return -1; 1234 return -1;
1238} 1235}
1239 1236
1240S32 LLScrollListCtrl::getItemIndex( LLUUID& target_id ) 1237S32 LLScrollListCtrl::getItemIndex( const LLUUID& target_id )
1241{ 1238{
1242 S32 index = 0; 1239 S32 index = 0;
1243 item_list::iterator iter; 1240 item_list::iterator iter;
@@ -1722,6 +1719,12 @@ void LLScrollListCtrl::draw()
1722 gl_rect_2d(background); 1719 gl_rect_2d(background);
1723 } 1720 }
1724 1721
1722 if (mColumnsDirty)
1723 {
1724 updateColumns();
1725 mColumnsDirty = FALSE;
1726 }
1727
1725 drawItems(); 1728 drawItems();
1726 1729
1727 if (mBorder) 1730 if (mBorder)
@@ -1989,9 +1992,8 @@ BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask)
1989 gFocusMgr.setMouseCapture(this); 1992 gFocusMgr.setMouseCapture(this);
1990 mNeedsScroll = TRUE; 1993 mNeedsScroll = TRUE;
1991 } 1994 }
1992 // otherwise we already have this item selected 1995
1993 // so propagate state of cell to rest of selected column 1996 // propagate state of cell to rest of selected column
1994 else
1995 { 1997 {
1996 // propagate value of this cell to other selected items 1998 // propagate value of this cell to other selected items
1997 // and commit the respective widgets 1999 // and commit the respective widgets
@@ -2537,6 +2539,23 @@ void LLScrollListCtrl::sortItems()
2537 setSorted(TRUE); 2539 setSorted(TRUE);
2538} 2540}
2539 2541
2542void LLScrollListCtrl::dirtyColumns()
2543{
2544 mColumnsDirty = TRUE;
2545
2546 // need to keep mColumnsIndexed up to date
2547 // just in case someone indexes into it immediately
2548 mColumnsIndexed.resize(mColumns.size());
2549
2550 std::map<LLString, LLScrollListColumn>::iterator column_itor;
2551 for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor)
2552 {
2553 LLScrollListColumn *column = &column_itor->second;
2554 mColumnsIndexed[column_itor->second.mIndex] = column;
2555 }
2556}
2557
2558
2540S32 LLScrollListCtrl::getScrollPos() 2559S32 LLScrollListCtrl::getScrollPos()
2541{ 2560{
2542 return mScrollbar->getDocPos(); 2561 return mScrollbar->getDocPos();
@@ -2727,6 +2746,12 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2727 S32 search_column = 0; 2746 S32 search_column = 0;
2728 node->getAttributeS32("search_column", search_column); 2747 node->getAttributeS32("search_column", search_column);
2729 2748
2749 S32 sort_column = -1;
2750 node->getAttributeS32("sort_column", sort_column);
2751
2752 BOOL sort_ascending = TRUE;
2753 node->getAttributeBOOL("sort_ascending", sort_ascending);
2754
2730 LLUICtrlCallback callback = NULL; 2755 LLUICtrlCallback callback = NULL;
2731 2756
2732 LLScrollListCtrl* scroll_list = new LLScrollListCtrl( 2757 LLScrollListCtrl* scroll_list = new LLScrollListCtrl(
@@ -2751,6 +2776,11 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
2751 2776
2752 scroll_list->setSearchColumn(search_column); 2777 scroll_list->setSearchColumn(search_column);
2753 2778
2779 if (sort_column >= 0)
2780 {
2781 scroll_list->sortByColumn(sort_column, sort_ascending);
2782 }
2783
2754 LLSD columns; 2784 LLSD columns;
2755 S32 index = 0; 2785 S32 index = 0;
2756 LLXMLNodePtr child; 2786 LLXMLNodePtr child;
@@ -3026,7 +3056,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
3026 } 3056 }
3027 } 3057 }
3028 3058
3029 updateColumns(); 3059 dirtyColumns();
3030} 3060}
3031 3061
3032// static 3062// static
@@ -3257,13 +3287,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
3257 col_index++; 3287 col_index++;
3258 } 3288 }
3259 3289
3260 S32 num_columns = mColumns.size(); 3290 // add dummy cells for missing columns
3261 for (S32 column = 0; column < num_columns; ++column) 3291 for (column_map_t::iterator column_it = mColumns.begin(); column_it != mColumns.end(); ++column_it)
3262 { 3292 {
3263 if (new_item->getColumn(column) == NULL) 3293 S32 column_idx = column_it->second.mIndex;
3294 if (new_item->getColumn(column_idx) == NULL)
3264 { 3295 {
3265 LLScrollListColumn* column_ptr = mColumnsIndexed[column]; 3296 LLScrollListColumn* column_ptr = &column_it->second;
3266 new_item->setColumn(column, new LLScrollListText("", gResMgr->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->mWidth, LLFontGL::NORMAL)); 3297 new_item->setColumn(column_idx, new LLScrollListText("", gResMgr->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->mWidth, LLFontGL::NORMAL));
3267 } 3298 }
3268 } 3299 }
3269 3300
@@ -3665,7 +3696,7 @@ LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_d
3665void LLColumnHeader::userSetShape(const LLRect& new_rect) 3696void LLColumnHeader::userSetShape(const LLRect& new_rect)
3666{ 3697{
3667 S32 new_width = new_rect.getWidth(); 3698 S32 new_width = new_rect.getWidth();
3668 S32 delta_width = new_width - (mRect.getWidth() + mColumn->mParentCtrl->getColumnPadding()); 3699 S32 delta_width = new_width - (mRect.getWidth() /*+ mColumn->mParentCtrl->getColumnPadding()*/);
3669 3700
3670 if (delta_width != 0) 3701 if (delta_width != 0)
3671 { 3702 {
@@ -3737,6 +3768,8 @@ void LLColumnHeader::userSetShape(const LLRect& new_rect)
3737 } 3768 }
3738 3769
3739 // tell scroll list to layout columns again 3770 // tell scroll list to layout columns again
3771 // do immediate update to get proper feedback to resize handle
3772 // which needs to know how far the resize actually went
3740 mColumn->mParentCtrl->updateColumns(); 3773 mColumn->mParentCtrl->updateColumns();
3741 } 3774 }
3742} 3775}
diff --git a/linden/indra/llui/llscrolllistctrl.h b/linden/indra/llui/llscrolllistctrl.h
index ada4f9b..71ba63d 100644
--- a/linden/indra/llui/llscrolllistctrl.h
+++ b/linden/indra/llui/llscrolllistctrl.h
@@ -97,6 +97,7 @@ public:
97 virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const; 97 virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const;
98 virtual S32 getContentWidth() const; 98 virtual S32 getContentWidth() const;
99 virtual S32 getHeight() const { return llround(mFont->getLineHeight()); } 99 virtual S32 getHeight() const { return llround(mFont->getLineHeight()); }
100 virtual void setValue(LLSD value) { setText(value.asString()); }
100 virtual const LLSD getValue() const { return LLSD(mText.getString()); } 101 virtual const LLSD getValue() const { return LLSD(mText.getString()); }
101 virtual BOOL getVisible() const { return mVisible; } 102 virtual BOOL getVisible() const { return mVisible; }
102 virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;} 103 virtual void highlightText(S32 offset, S32 num_chars) {mHighlightOffset = offset; mHighlightCount = num_chars;}
@@ -440,6 +441,7 @@ public:
440 BOOL handleClick(S32 x, S32 y, MASK mask); 441 BOOL handleClick(S32 x, S32 y, MASK mask);
441 BOOL selectFirstItem(); 442 BOOL selectFirstItem();
442 BOOL selectNthItem( S32 index ); 443 BOOL selectNthItem( S32 index );
444 BOOL selectItemRange( S32 first, S32 last );
443 BOOL selectItemAt(S32 x, S32 y, MASK mask); 445 BOOL selectItemAt(S32 x, S32 y, MASK mask);
444 446
445 void deleteSingleItem( S32 index ); 447 void deleteSingleItem( S32 index );
@@ -459,7 +461,7 @@ public:
459 virtual BOOL getCanSelect() const { return mCanSelect; } 461 virtual BOOL getCanSelect() const { return mCanSelect; }
460 462
461 S32 getItemIndex( LLScrollListItem* item ); 463 S32 getItemIndex( LLScrollListItem* item );
462 S32 getItemIndex( LLUUID& item_id ); 464 S32 getItemIndex( const LLUUID& item_id );
463 465
464 LLScrollListItem* addCommentText( const LLString& comment_text, EAddPosition pos = ADD_BOTTOM); 466 LLScrollListItem* addCommentText( const LLString& comment_text, EAddPosition pos = ADD_BOTTOM);
465 LLScrollListItem* addSeparator(EAddPosition pos); 467 LLScrollListItem* addSeparator(EAddPosition pos);
@@ -561,7 +563,7 @@ public:
561 static void onClickColumn(void *userdata); 563 static void onClickColumn(void *userdata);
562 564
563 void updateColumns(); 565 void updateColumns();
564 void calcMaxContentWidth(LLScrollListItem* changed_item); 566 void calcColumnWidths();
565 S32 getMaxContentWidth() { return mMaxContentWidth; } 567 S32 getMaxContentWidth() { return mMaxContentWidth; }
566 568
567 void setDisplayHeading(BOOL display); 569 void setDisplayHeading(BOOL display);
@@ -596,6 +598,9 @@ public:
596 598
597 S32 selectMultiple( LLDynamicArray<LLUUID> ids ); 599 S32 selectMultiple( LLDynamicArray<LLUUID> ids );
598 void sortItems(); 600 void sortItems();
601 // manually call this whenever editing list items in place to flag need for resorting
602 void setSorted(BOOL sorted);
603 void dirtyColumns(); // some operation has potentially affected column layout or ordering
599 604
600protected: 605protected:
601 // "Full" interface: use this when you're creating a list that has one or more of the following: 606 // "Full" interface: use this when you're creating a list that has one or more of the following:
@@ -624,7 +629,6 @@ protected:
624 void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE); 629 void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
625 void deselectItem(LLScrollListItem* itemp); 630 void deselectItem(LLScrollListItem* itemp);
626 void commitIfChanged(); 631 void commitIfChanged();
627 void setSorted(BOOL sorted);
628 BOOL setSort(S32 column, BOOL ascending); 632 BOOL setSort(S32 column, BOOL ascending);
629 633
630protected: 634protected:
@@ -645,6 +649,7 @@ protected:
645 BOOL mNeedsScroll; 649 BOOL mNeedsScroll;
646 BOOL mCanSelect; 650 BOOL mCanSelect;
647 BOOL mDisplayColumnHeaders; 651 BOOL mDisplayColumnHeaders;
652 BOOL mColumnsDirty;
648 653
649 typedef std::deque<LLScrollListItem *> item_list; 654 typedef std::deque<LLScrollListItem *> item_list;
650 item_list mItemList; 655 item_list mItemList;
@@ -686,7 +691,8 @@ protected:
686 691
687 BOOL mSorted; 692 BOOL mSorted;
688 693
689 std::map<LLString, LLScrollListColumn> mColumns; 694 typedef std::map<LLString, LLScrollListColumn> column_map_t;
695 column_map_t mColumns;
690 696
691 BOOL mDirty; 697 BOOL mDirty;
692 S32 mOriginalSelection; 698 S32 mOriginalSelection;
diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp
index 04d33a6..39398b0 100644
--- a/linden/indra/llui/llview.cpp
+++ b/linden/indra/llui/llview.cpp
@@ -973,18 +973,10 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
973 } 973 }
974 } 974 }
975 975
976 if( !handled && !called_from_parent) 976 if( !handled && !called_from_parent && mParentView)
977 { 977 {
978 if (mIsFocusRoot) 978 // Upward traversal
979 { 979 handled = mParentView->handleKey( key, mask, FALSE );
980 // stop processing at focus root
981 handled = FALSE;
982 }
983 else if (mParentView)
984 {
985 // Upward traversal
986 handled = mParentView->handleKey( key, mask, FALSE );
987 }
988 } 980 }
989 return handled; 981 return handled;
990} 982}
@@ -1019,18 +1011,10 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
1019 } 1011 }
1020 1012
1021 1013
1022 if (!handled && !called_from_parent) 1014 if (!handled && !called_from_parent && mParentView)
1023 { 1015 {
1024 if (mIsFocusRoot) 1016 // Upward traversal
1025 { 1017 handled = mParentView->handleUnicodeChar(uni_char, FALSE);
1026 // stop processing at focus root
1027 handled = FALSE;
1028 }
1029 else if(mParentView)
1030 {
1031 // Upward traversal
1032 handled = mParentView->handleUnicodeChar(uni_char, FALSE);
1033 }
1034 } 1018 }
1035 1019
1036 return handled; 1020 return handled;
@@ -1666,7 +1650,12 @@ void LLView::updateBoundingRect()
1666 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) 1650 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
1667 { 1651 {
1668 LLView* childp = *child_it; 1652 LLView* childp = *child_it;
1669 if (!childp->getVisible()) continue; 1653 // ignore invisible and "top" children when calculating bounding rect
1654 // such as combobox popups
1655 if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
1656 {
1657 continue;
1658 }
1670 1659
1671 LLRect child_bounding_rect = childp->getBoundingRect(); 1660 LLRect child_bounding_rect = childp->getBoundingRect();
1672 1661