aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llscrolllistctrl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llui/llscrolllistctrl.cpp')
-rw-r--r--linden/indra/llui/llscrolllistctrl.cpp175
1 files changed, 104 insertions, 71 deletions
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}