00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "elements/CEGUIMultiColumnList.h"
00027 #include "CEGUIExceptions.h"
00028 #include "elements/CEGUIScrollbar.h"
00029 #include "elements/CEGUIListHeader.h"
00030 #include "elements/CEGUIListboxItem.h"
00031 #include "CEGUILogger.h"
00032
00033 #include <algorithm>
00034
00035
00036
00037 namespace CEGUI
00038 {
00039 const String MultiColumnList::EventNamespace("MultiColumnList");
00040
00041
00042
00043
00044 MultiColumnListProperties::ColumnsMovable MultiColumnList::d_columnsMovableProperty;
00045 MultiColumnListProperties::ColumnsSizable MultiColumnList::d_columnsSizableProperty;
00046 MultiColumnListProperties::ForceHorzScrollbar MultiColumnList::d_forceHorzScrollProperty;
00047 MultiColumnListProperties::ForceVertScrollbar MultiColumnList::d_forceVertScrollProperty;
00048 MultiColumnListProperties::NominatedSelectionColumnID MultiColumnList::d_nominatedSelectColProperty;
00049 MultiColumnListProperties::NominatedSelectionRow MultiColumnList::d_nominatedSelectRowProperty;
00050 MultiColumnListProperties::SelectionMode MultiColumnList::d_selectModeProperty;
00051 MultiColumnListProperties::SortColumnID MultiColumnList::d_sortColumnIDProperty;
00052 MultiColumnListProperties::SortDirection MultiColumnList::d_sortDirectionProperty;
00053 MultiColumnListProperties::SortSettingEnabled MultiColumnList::d_sortSettingProperty;
00054
00055
00056
00057
00058
00059
00060 const String MultiColumnList::EventSelectionModeChanged( (utf8*)"SelectModeChanged" );
00061 const String MultiColumnList::EventNominatedSelectColumnChanged( (utf8*)"NomSelColChanged" );
00062 const String MultiColumnList::EventNominatedSelectRowChanged( (utf8*)"NomSelRowChanged" );
00063 const String MultiColumnList::EventVertScrollbarModeChanged( (utf8*)"VertBarModeChanged" );
00064 const String MultiColumnList::EventHorzScrollbarModeChanged( (utf8*)"HorzBarModeChanged" );
00065 const String MultiColumnList::EventSelectionChanged( (utf8*)"SelectionChanged" );
00066 const String MultiColumnList::EventListContentsChanged( (utf8*)"ContentsChanged" );
00067 const String MultiColumnList::EventSortColumnChanged( (utf8*)"SortColChanged" );
00068 const String MultiColumnList::EventSortDirectionChanged( (utf8*)"SortDirChanged" );
00069 const String MultiColumnList::EventListColumnSized( (utf8*)"ColSized" );
00070 const String MultiColumnList::EventListColumnMoved( (utf8*)"ColMoved" );
00071
00072
00073
00074
00075
00076 MultiColumnList::MultiColumnList(const String& type, const String& name) :
00077 Window(type, name),
00078 d_forceVertScroll(false),
00079 d_forceHorzScroll(false),
00080 d_nominatedSelectCol(0),
00081 d_nominatedSelectRow(0),
00082 d_lastSelected(NULL)
00083 {
00084
00085 addMultiColumnListboxEvents();
00086
00087
00088 addMultiColumnListProperties();
00089
00090
00091 d_selectMode = CellSingle;
00092 setSelectionMode(RowSingle);
00093 }
00094
00095
00096
00097
00098
00099 MultiColumnList::~MultiColumnList(void)
00100 {
00101
00102 resetList_impl();
00103 }
00104
00105
00106
00107
00108
00109
00110 bool MultiColumnList::isUserSortControlEnabled(void) const
00111 {
00112 return d_header->isSortingEnabled();
00113 }
00114
00115
00116
00117
00118
00119 bool MultiColumnList::isUserColumnSizingEnabled(void) const
00120 {
00121 return d_header->isColumnSizingEnabled();
00122 }
00123
00124
00125
00126
00127
00128 bool MultiColumnList::isUserColumnDraggingEnabled(void) const
00129 {
00130 return d_header->isColumnDraggingEnabled();
00131 }
00132
00133
00134
00135
00136
00137 uint MultiColumnList::getColumnCount(void) const
00138 {
00139 return d_header->getColumnCount();
00140 }
00141
00142
00143
00144
00145
00146 uint MultiColumnList::getRowCount(void) const
00147 {
00148 return (uint)d_grid.size();
00149 }
00150
00151
00152
00153
00154
00155
00156 uint MultiColumnList::getSortColumn(void) const
00157 {
00158 return d_header->getSortColumn();
00159 }
00160
00161
00162
00163
00164
00165 uint MultiColumnList::getColumnWithID(uint col_id) const
00166 {
00167 return d_header->getColumnFromID(col_id);
00168 }
00169
00170
00171
00172
00173
00174
00175 uint MultiColumnList::getColumnWithHeaderText(const String& text) const
00176 {
00177 return d_header->getColumnWithText(text);
00178 }
00179
00180
00181
00182
00183
00184 float MultiColumnList::getTotalColumnHeadersWidth(void) const
00185 {
00186 float width = d_header->getTotalSegmentsPixelExtent();
00187
00188 if (getMetricsMode() == Relative)
00189 {
00190 width = absoluteToRelativeX(width);
00191 }
00192
00193 return width;
00194 }
00195
00196
00197
00198
00199
00200 float MultiColumnList::getColumnHeaderWidth(uint col_idx) const
00201 {
00202 float width = d_header->getColumnPixelWidth(col_idx);
00203
00204 if (getMetricsMode() == Relative)
00205 {
00206 width = absoluteToRelativeX(width);
00207 }
00208
00209 return width;
00210 }
00211
00212
00213
00214
00215
00216 ListHeaderSegment::SortDirection MultiColumnList::getSortDirection(void) const
00217 {
00218 return d_header->getSortDirection();
00219 }
00220
00221
00222
00223
00224
00225 ListHeaderSegment& MultiColumnList::getHeaderSegmentForColumn(uint col_idx) const
00226 {
00227 return d_header->getSegmentFromColumn(col_idx);
00228 }
00229
00230
00231
00232
00233
00234 uint MultiColumnList::getItemRowIndex(const ListboxItem* item) const
00235 {
00236 for (uint i = 0; i < getRowCount(); ++i)
00237 {
00238 if (isListboxItemInRow(item, i))
00239 {
00240 return i;
00241 }
00242
00243 }
00244
00245
00246 throw InvalidRequestException((utf8*)"MultiColumnList::getItemRowIndex - the given ListboxItem is not attached to this MultiColumnList.");
00247 }
00248
00249
00250
00251
00252
00253 uint MultiColumnList::getItemColumnIndex(const ListboxItem* item) const
00254 {
00255 for (uint i = 0; i < getColumnCount(); ++i)
00256 {
00257 if (isListboxItemInColumn(item, i))
00258 {
00259 return i;
00260 }
00261
00262 }
00263
00264
00265 throw InvalidRequestException((utf8*)"MultiColumnList::getItemColumnIndex - the given ListboxItem is not attached to this MultiColumnList.");
00266 }
00267
00268
00269
00270
00271
00272 MCLGridRef MultiColumnList::getItemGridReference(const ListboxItem* item) const
00273 {
00274 return MCLGridRef(getItemRowIndex(item), getItemColumnIndex(item));
00275 }
00276
00277
00278
00279
00280
00281
00282 ListboxItem* MultiColumnList::getItemAtGridReference(const MCLGridRef& grid_ref) const
00283 {
00284
00285 if (grid_ref.column >= getColumnCount())
00286 {
00287 throw InvalidRequestException((utf8*)"MultiColumnList::getItemAtGridReference - the column given in the grid reference is out of range.");
00288 }
00289 else if (grid_ref.row >= getRowCount())
00290 {
00291 throw InvalidRequestException((utf8*)"MultiColumnList::getItemAtGridReference - the row given in the grid reference is out of range.");
00292 }
00293 else
00294 {
00295 return d_grid[grid_ref.row][grid_ref.column];
00296 }
00297
00298 }
00299
00300
00301
00302
00303
00304 bool MultiColumnList::isListboxItemInColumn(const ListboxItem* item, uint col_idx) const
00305 {
00306
00307 if (col_idx >= getColumnCount())
00308 {
00309 throw InvalidRequestException((utf8*)"MultiColumnList::isListboxItemInColumn - the column index given is out of range.");
00310 }
00311 else
00312 {
00313 for (uint i = 0; i < getRowCount(); ++i)
00314 {
00315 if (d_grid[i][col_idx] == item)
00316 {
00317 return true;
00318 }
00319
00320 }
00321
00322
00323 return false;
00324 }
00325
00326 }
00327
00328
00329
00330
00331
00332 bool MultiColumnList::isListboxItemInRow(const ListboxItem* item, uint row_idx) const
00333 {
00334
00335 if (row_idx >= getRowCount())
00336 {
00337 throw InvalidRequestException((utf8*)"MultiColumnList::isListboxItemInRow - the row index given is out of range.");
00338 }
00339 else
00340 {
00341 for (uint i = 0; i < getColumnCount(); ++i)
00342 {
00343 if (d_grid[row_idx][i] == item)
00344 {
00345 return true;
00346 }
00347
00348 }
00349
00350
00351 return false;
00352 }
00353
00354 }
00355
00356
00357
00358
00359
00360 bool MultiColumnList::isListboxItemInList(const ListboxItem* item) const
00361 {
00362 for (uint i = 0; i < getRowCount(); ++i)
00363 {
00364 for (uint j = 0; j < getColumnCount(); ++j)
00365 {
00366 if (d_grid[i][j] == item)
00367 {
00368 return true;
00369 }
00370
00371 }
00372
00373 }
00374
00375 return false;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 ListboxItem* MultiColumnList::findColumnItemWithText(const String& text, uint col_idx, const ListboxItem* start_item) const
00385 {
00386
00387 if (col_idx >= getColumnCount())
00388 {
00389 throw InvalidRequestException((utf8*)"MultiColumnList::findColumnItemWithText - specified column index is out of range.");
00390 }
00391
00392
00393 uint i = (start_item == NULL) ? 0 : getItemRowIndex(start_item) + 1;
00394
00395 for ( ; i < getRowCount(); ++i)
00396 {
00397
00398 if (d_grid[i][col_idx]->getText() == text)
00399 {
00400 return d_grid[i][col_idx];
00401 }
00402
00403 }
00404
00405
00406 return NULL;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415 ListboxItem* MultiColumnList::findRowItemWithText(const String& text, uint row_idx, const ListboxItem* start_item) const
00416 {
00417
00418 if (row_idx >= getRowCount())
00419 {
00420 throw InvalidRequestException((utf8*)"MultiColumnList::findRowItemWithText - specified row index is out of range.");
00421 }
00422
00423
00424 uint i = (start_item == NULL) ? 0 : getItemColumnIndex(start_item) + 1;
00425
00426 for ( ; i < getColumnCount(); ++i)
00427 {
00428
00429 if (d_grid[row_idx][i]->getText() == text)
00430 {
00431 return d_grid[row_idx][i];
00432 }
00433
00434 }
00435
00436
00437 return NULL;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 ListboxItem* MultiColumnList::findListItemWithText(const String& text, const ListboxItem* start_item) const
00449 {
00450 MCLGridRef startRef(0, 0);
00451
00452
00453 if (start_item != NULL)
00454 {
00455 startRef = getItemGridReference(start_item);
00456 ++startRef.column;
00457 }
00458
00459
00460 for (uint i = startRef.row; i < getRowCount(); ++i)
00461 {
00462 for (uint j = startRef.column; j < getColumnCount(); ++j)
00463 {
00464
00465 if (d_grid[i][j]->getText() == text)
00466 {
00467 return d_grid[i][j];
00468 }
00469
00470 }
00471
00472 }
00473
00474
00475 return NULL;
00476 }
00477
00478
00479
00480
00481
00482
00483 ListboxItem* MultiColumnList::getFirstSelectedItem(void) const
00484 {
00485 return getNextSelected(NULL);
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 ListboxItem* MultiColumnList::getNextSelected(const ListboxItem* start_item) const
00497 {
00498 MCLGridRef startRef(0, 0);
00499
00500
00501 if (start_item != NULL)
00502 {
00503 startRef = getItemGridReference(start_item);
00504 ++startRef.column;
00505 }
00506
00507
00508 for (uint i = startRef.row; i < getRowCount(); ++i)
00509 {
00510 for (uint j = startRef.column; j < getColumnCount(); ++j)
00511 {
00512
00513 ListboxItem* item = d_grid[i][j];
00514
00515 if ((item != NULL) && item->isSelected())
00516 {
00517 return d_grid[i][j];
00518 }
00519
00520 }
00521
00522 }
00523
00524
00525 return NULL;
00526 }
00527
00528
00529
00530
00531
00532 uint MultiColumnList::getSelectedCount(void) const
00533 {
00534 uint count = 0;
00535
00536 for (uint i = 0; i < getRowCount(); ++i)
00537 {
00538 for (uint j = 0; j < getColumnCount(); ++j)
00539 {
00540 ListboxItem* item = d_grid[i][j];
00541
00542 if ((item != NULL) && item->isSelected())
00543 {
00544 ++count;
00545 }
00546
00547 }
00548
00549 }
00550
00551 return count;
00552 }
00553
00554
00555
00556
00557
00558 bool MultiColumnList::isItemSelected(const MCLGridRef& grid_ref) const
00559 {
00560 ListboxItem* item = getItemAtGridReference(grid_ref);
00561
00562 if (item != NULL)
00563 {
00564 return item->isSelected();
00565 }
00566
00567
00568 return false;
00569 }
00570
00571
00572
00573
00574
00575 uint MultiColumnList::getNominatedSelectionColumnID(void) const
00576 {
00577 return d_header->getSegmentFromColumn(d_nominatedSelectCol).getID();
00578 }
00579
00580
00581
00582
00583
00584 uint MultiColumnList::getNominatedSelectionColumn(void) const
00585 {
00586 return d_nominatedSelectCol;
00587 }
00588
00589
00590
00591
00592
00593 uint MultiColumnList::getNominatedSelectionRow(void) const
00594 {
00595 return d_nominatedSelectRow;
00596 }
00597
00598
00599
00600
00601
00602 MultiColumnList::SelectionMode MultiColumnList::getSelectionMode(void) const
00603 {
00604 return d_selectMode;
00605 }
00606
00607
00608
00609
00610
00611 void MultiColumnList::initialise(void)
00612 {
00613
00614 d_vertScrollbar = createVertScrollbar();
00615 d_horzScrollbar = createHorzScrollbar();
00616 d_header = createListHeader();
00617
00618
00619 addChildWindow(d_vertScrollbar);
00620 addChildWindow(d_horzScrollbar);
00621 addChildWindow(d_header);
00622
00623
00624 d_header->subscribeEvent(ListHeader::EventSegmentRenderOffsetChanged, Event::Subscriber(&CEGUI::MultiColumnList::handleHeaderScroll, this));
00625 d_header->subscribeEvent(ListHeader::EventSegmentSequenceChanged, Event::Subscriber(&CEGUI::MultiColumnList::handleHeaderSegMove, this));
00626 d_header->subscribeEvent(ListHeader::EventSegmentSized, Event::Subscriber(&CEGUI::MultiColumnList::handleColumnSizeChange, this));
00627 d_header->subscribeEvent(ListHeader::EventSortColumnChanged , Event::Subscriber(&CEGUI::MultiColumnList::handleSortColumnChange, this));
00628 d_header->subscribeEvent(ListHeader::EventSortDirectionChanged, Event::Subscriber(&CEGUI::MultiColumnList::handleSortDirectionChange, this));
00629 d_header->subscribeEvent(ListHeader::EventSplitterDoubleClicked, Event::Subscriber(&CEGUI::MultiColumnList::handleHeaderSegDblClick, this));
00630 d_horzScrollbar->subscribeEvent(Scrollbar::EventScrollPositionChanged, Event::Subscriber(&CEGUI::MultiColumnList::handleHorzScrollbar, this));
00631
00632
00633 setSortDirection(ListHeaderSegment::None);
00634
00635
00636 configureScrollbars();
00637 layoutComponentWidgets();
00638 }
00639
00640
00641
00642
00643
00644 void MultiColumnList::resetList(void)
00645 {
00646 if (resetList_impl())
00647 {
00648 WindowEventArgs args(this);
00649 onListContentsChanged(args);
00650 }
00651
00652 }
00653
00654
00655
00656
00657
00658 void MultiColumnList::addColumn(const String& text, uint col_id, float width)
00659 {
00660 insertColumn(text, col_id, width, getColumnCount());
00661 }
00662
00663
00664
00665
00666
00667 void MultiColumnList::insertColumn(const String& text, uint col_id, float width, uint position)
00668 {
00669
00670 if (position > getColumnCount())
00671 {
00672 position = getColumnCount();
00673 }
00674
00675
00676 if (getMetricsMode() == Relative)
00677 {
00678 width = relativeToAbsoluteX(width);
00679 }
00680
00681
00682 d_header->insertColumn(text, col_id, d_header->absoluteToRelativeX(width), position);
00683
00684
00685 for (uint i = 0; i < getRowCount(); ++i)
00686 {
00687 d_grid[i].d_items.insert(d_grid[i].d_items.begin() + position, NULL);
00688 }
00689
00690
00691 if ((d_nominatedSelectCol >= position) && (getColumnCount() > 1))
00692 {
00693 d_nominatedSelectCol++;
00694 }
00695
00696
00697 WindowEventArgs args(this);
00698 onListContentsChanged(args);
00699 }
00700
00701
00702
00703
00704
00705 void MultiColumnList::removeColumn(uint col_idx)
00706 {
00707
00708 if (col_idx >= getColumnCount())
00709 {
00710 throw InvalidRequestException((utf8*)"MultiColumnList::removeColumn - the specified column index is out of range.");
00711 }
00712 else
00713 {
00714
00715 if (d_nominatedSelectCol == col_idx)
00716 {
00717 d_nominatedSelectCol = 0;
00718 }
00719
00720
00721 for (uint i = 0; i < getRowCount(); ++i)
00722 {
00723
00724 ListboxItem* item = d_grid[i][col_idx];
00725
00726
00727 d_grid[i].d_items.erase(d_grid[i].d_items.begin() + col_idx);
00728
00729
00730 if ((item != NULL) && item->isAutoDeleted())
00731 {
00732 delete item;
00733 }
00734
00735 }
00736
00737
00738 d_header->removeColumn(col_idx);
00739
00740
00741 WindowEventArgs args(this);
00742 onListContentsChanged(args);
00743 }
00744
00745 }
00746
00747
00748
00749
00750
00751 void MultiColumnList::removeColumnWithID(uint col_id)
00752 {
00753 removeColumn(getColumnWithID(col_id));
00754 }
00755
00756
00757
00758
00759
00760 void MultiColumnList::moveColumn(uint col_idx, uint position)
00761 {
00762
00763 d_header->moveColumn(col_idx, position);
00764 }
00765
00766
00767
00768
00769
00770 void MultiColumnList::moveColumnWithID(uint col_id, uint position)
00771 {
00772 moveColumn(getColumnWithID(col_id), position);
00773 }
00774
00775
00776
00777
00778
00779 uint MultiColumnList::addRow(void)
00780 {
00781 return addRow(NULL, 0);
00782 }
00783
00784
00785
00786
00787
00788 uint MultiColumnList::addRow(ListboxItem* item, uint col_id)
00789 {
00790 uint col_idx = 0;
00791
00792
00793 ListRow row;
00794 row.d_sortColumn = getSortColumn();
00795 row.d_items.resize(getColumnCount(), NULL);
00796
00797 if (item != NULL)
00798 {
00799
00800 col_idx = getColumnWithID(col_id);
00801
00802
00803 item->setOwnerWindow(this);
00804 row[col_idx] = item;
00805 }
00806
00807 uint pos;
00808
00809
00810 if (getSortDirection() != ListHeaderSegment::None)
00811 {
00812
00813 pos = (uint)std::distance(d_grid.begin(), d_grid.insert(std::upper_bound(d_grid.begin(), d_grid.end(), row), row));
00814 }
00815
00816 else
00817 {
00818 pos = getRowCount();
00819 d_grid.push_back(row);
00820 }
00821
00822
00823 WindowEventArgs args(this);
00824 onListContentsChanged(args);
00825
00826 return pos;
00827 }
00828
00829
00830
00831
00832
00833 uint MultiColumnList::insertRow(uint row_idx)
00834 {
00835 return insertRow(NULL, 0, row_idx);
00836 }
00837
00838
00839
00840
00841
00842 uint MultiColumnList::insertRow(ListboxItem* item, uint col_id, uint row_idx)
00843 {
00844
00845 if (getSortDirection() != ListHeaderSegment::None)
00846 {
00847 return addRow(item, col_id);
00848 }
00849 else
00850 {
00851 uint col_idx = 0;
00852
00853
00854 ListRow row;
00855 row.d_sortColumn = getSortColumn();
00856 row.d_items.resize(getColumnCount(), NULL);
00857
00858
00859 if (row_idx > getRowCount())
00860 {
00861 row_idx = getRowCount();
00862 }
00863
00864 d_grid.insert(d_grid.begin() + row_idx, row);
00865
00866
00867 setItem(item, col_id, row_idx);
00868
00869
00870 WindowEventArgs args(this);
00871 onListContentsChanged(args);
00872
00873 return row_idx;
00874 }
00875
00876 }
00877
00878
00879
00880
00881
00882 void MultiColumnList::removeRow(uint row_idx)
00883 {
00884
00885 if (row_idx >= getRowCount())
00886 {
00887 throw InvalidRequestException((utf8*)"MultiColumnList::removeRow - The specified row index is out of range.");
00888 }
00889 else
00890 {
00891
00892 for (uint i = 0; i < getColumnCount(); ++i)
00893 {
00894 ListboxItem* item = d_grid[row_idx][i];
00895
00896 if ((item != NULL) && item->isAutoDeleted())
00897 {
00898 delete item;
00899 }
00900
00901 }
00902
00903
00904 d_grid.erase(d_grid.begin() + row_idx);
00905
00906
00907 if (d_nominatedSelectRow == row_idx)
00908 {
00909 d_nominatedSelectRow = 0;
00910 }
00911
00912
00913 WindowEventArgs args(this);
00914 onListContentsChanged(args);
00915 }
00916
00917 }
00918
00919
00920
00921
00922
00923
00924 void MultiColumnList::setItem(ListboxItem* item, const MCLGridRef& position)
00925 {
00926
00927 if (position.column >= getColumnCount())
00928 {
00929 throw InvalidRequestException((utf8*)"MultiColumnList::setItem - the specified column index is invalid.");
00930 }
00931 else if (position.row >= getRowCount())
00932 {
00933 throw InvalidRequestException((utf8*)"MultiColumnList::setItem - the specified row index is invalid.");
00934 }
00935
00936
00937 ListboxItem* oldItem = d_grid[position.row][position.column];
00938
00939 if ((oldItem != NULL) && item->isAutoDeleted())
00940 {
00941 delete oldItem;
00942 }
00943
00944
00945 item->setOwnerWindow(this);
00946 d_grid[position.row][position.column] = item;
00947
00948
00949
00950 WindowEventArgs args(this);
00951 onListContentsChanged(args);
00952 }
00953
00954
00955
00956
00957
00958
00959 void MultiColumnList::setItem(ListboxItem* item, uint col_id, uint row_idx)
00960 {
00961 setItem(item, MCLGridRef(row_idx, getColumnWithID(col_id)));
00962 }
00963
00964
00965
00966
00967
00968 void MultiColumnList::setSelectionMode(MultiColumnList::SelectionMode sel_mode)
00969 {
00970 if (d_selectMode != sel_mode)
00971 {
00972 d_selectMode = sel_mode;
00973
00974 clearAllSelections();
00975
00976 switch(d_selectMode)
00977 {
00978 case RowSingle:
00979 d_multiSelect = false;
00980 d_fullRowSelect = true;
00981 d_fullColSelect = false;
00982 d_useNominatedCol = false;
00983 d_useNominatedRow = false;
00984 break;
00985
00986 case RowMultiple:
00987 d_multiSelect = true;
00988 d_fullRowSelect = true;
00989 d_fullColSelect = false;
00990 d_useNominatedCol = false;
00991 d_useNominatedRow = false;
00992 break;
00993
00994 case CellSingle:
00995 d_multiSelect = false;
00996 d_fullRowSelect = false;
00997 d_fullColSelect = false;
00998 d_useNominatedCol = false;
00999 d_useNominatedRow = false;
01000 break;
01001
01002 case CellMultiple:
01003 d_multiSelect = true;
01004 d_fullRowSelect = false;
01005 d_fullColSelect = false;
01006 d_useNominatedCol = false;
01007 d_useNominatedRow = false;
01008 break;
01009
01010 case NominatedColumnSingle:
01011 d_multiSelect = false;
01012 d_fullRowSelect = false;
01013 d_fullColSelect = false;
01014 d_useNominatedCol = true;
01015 d_useNominatedRow = false;
01016 break;
01017
01018 case NominatedColumnMultiple:
01019 d_multiSelect = true;
01020 d_fullRowSelect = false;
01021 d_fullColSelect = false;
01022 d_useNominatedCol = true;
01023 d_useNominatedRow = false;
01024 break;
01025
01026 case ColumnSingle:
01027 d_multiSelect = false;
01028 d_fullRowSelect = false;
01029 d_fullColSelect = true;
01030 d_useNominatedCol = false;
01031 d_useNominatedRow = false;
01032 break;
01033
01034 case ColumnMultiple:
01035 d_multiSelect = true;
01036 d_fullRowSelect = false;
01037 d_fullColSelect = true;
01038 d_useNominatedCol = false;
01039 d_useNominatedRow = false;
01040 break;
01041
01042 case NominatedRowSingle:
01043 d_multiSelect = false;
01044 d_fullRowSelect = false;
01045 d_fullColSelect = false;
01046 d_useNominatedCol = false;
01047 d_useNominatedRow = true;
01048 break;
01049
01050 case NominatedRowMultiple:
01051 d_multiSelect = true;
01052 d_fullRowSelect = false;
01053 d_fullColSelect = false;
01054 d_useNominatedCol = false;
01055 d_useNominatedRow = true;
01056 break;
01057
01058 default:
01059 throw InvalidRequestException((utf8*)"MultiColumnList::setSelectionMode - invalid or unknown SelectionMode value supplied.");
01060 break;
01061
01062 }
01063
01064
01065 WindowEventArgs args(this);
01066 onSelectionModeChanged(args);
01067 }
01068
01069 }
01070
01071
01072
01073
01074
01075 void MultiColumnList::setNominatedSelectionColumnID(uint col_id)
01076 {
01077 setNominatedSelectionColumn(getColumnWithID(col_id));
01078 }
01079
01080
01081
01082
01083
01084 void MultiColumnList::setNominatedSelectionColumn(uint col_idx)
01085 {
01086 if (d_nominatedSelectCol != col_idx)
01087 {
01088 clearAllSelections();
01089
01090 d_nominatedSelectCol = col_idx;
01091
01092
01093 WindowEventArgs args(this);
01094 onNominatedSelectColumnChanged(args);
01095 }
01096
01097 }
01098
01099
01100
01101
01102
01103 void MultiColumnList::setNominatedSelectionRow(uint row_idx)
01104 {
01105 if (d_nominatedSelectRow != row_idx)
01106 {
01107 clearAllSelections();
01108
01109 d_nominatedSelectRow = row_idx;
01110
01111
01112 WindowEventArgs args(this);
01113 onNominatedSelectRowChanged(args);
01114 }
01115
01116 }
01117
01118
01119
01120
01121
01122 void MultiColumnList::setSortDirection(ListHeaderSegment::SortDirection direction)
01123 {
01124 if (getSortDirection() != direction)
01125 {
01126
01127 d_header->setSortDirection(direction);
01128 }
01129
01130 }
01131
01132
01133
01134
01135
01136 void MultiColumnList::setSortColumn(uint col_idx)
01137 {
01138 if (getSortColumn() != col_idx)
01139 {
01140
01141 d_header->setSortColumn(col_idx);
01142 }
01143
01144 }
01145
01146
01147
01148
01149
01150 void MultiColumnList::setSortColumnByID(uint col_id)
01151 {
01152 if (d_header->getSegmentFromColumn(getSortColumn()).getID() != col_id)
01153 {
01154
01155 d_header->setSortColumnFromID(col_id);
01156 }
01157
01158 }
01159
01160
01161
01162
01163
01164 void MultiColumnList::setShowVertScrollbar(bool setting)
01165 {
01166 if (d_forceVertScroll != setting)
01167 {
01168 d_forceVertScroll = setting;
01169
01170 configureScrollbars();
01171
01172
01173 WindowEventArgs args(this);
01174 onVertScrollbarModeChanged(args);
01175 }
01176
01177 }
01178
01179
01180
01181
01182
01183 void MultiColumnList::setShowHorzScrollbar(bool setting)
01184 {
01185 if (d_forceHorzScroll != setting)
01186 {
01187 d_forceHorzScroll = setting;
01188
01189 configureScrollbars();
01190
01191
01192 WindowEventArgs args(this);
01193 onHorzScrollbarModeChanged(args);
01194 }
01195
01196 }
01197
01198
01199
01200
01201
01202 void MultiColumnList::clearAllSelections(void)
01203 {
01204
01205 if (clearAllSelections_impl())
01206 {
01207
01208 WindowEventArgs args(this);
01209 onSelectionChanged(args);
01210 }
01211
01212
01213 }
01214
01215
01216
01217
01218
01219 void MultiColumnList::setItemSelectState(ListboxItem* item, bool state)
01220 {
01221 setItemSelectState(getItemGridReference(item), state);
01222 }
01223
01224
01225
01226
01227
01228 void MultiColumnList::setItemSelectState(const MCLGridRef& grid_ref, bool state)
01229 {
01230 if (setItemSelectState_impl(grid_ref, state))
01231 {
01232
01233 WindowEventArgs args(this);
01234 onSelectionChanged(args);
01235 }
01236
01237 }
01238
01239
01240
01241
01242
01243
01244 void MultiColumnList::handleUpdatedItemData(void)
01245 {
01246 configureScrollbars();
01247 requestRedraw();
01248 }
01249
01250
01251
01252
01253
01254
01255 void MultiColumnList::setColumnHeaderWidth(uint col_idx, float width)
01256 {
01257 if (getMetricsMode() == Relative)
01258 {
01259 width = relativeToAbsoluteX(width);
01260 }
01261
01262 d_header->setColumnPixelWidth(col_idx, width);
01263 }
01264
01265
01266
01267
01268
01269 void MultiColumnList::addMultiColumnListboxEvents(void)
01270 {
01271 addEvent(EventSelectionModeChanged); addEvent(EventNominatedSelectColumnChanged);
01272 addEvent(EventNominatedSelectRowChanged); addEvent(EventVertScrollbarModeChanged);
01273 addEvent(EventHorzScrollbarModeChanged); addEvent(EventSelectionChanged);
01274 addEvent(EventListContentsChanged); addEvent(EventSortColumnChanged);
01275 addEvent(EventSortDirectionChanged); addEvent(EventListColumnMoved);
01276 addEvent(EventListColumnSized);
01277 }
01278
01279
01280
01281
01282
01283
01284 void MultiColumnList::configureScrollbars(void)
01285 {
01286 float totalHeight = getTotalRowsHeight();
01287 float fullWidth = d_header->getTotalSegmentsPixelExtent();
01288
01289
01290
01291
01292
01293 if ((totalHeight > getListRenderArea().getHeight()) || d_forceVertScroll)
01294 {
01295 d_vertScrollbar->show();
01296
01297
01298 if ((fullWidth > getListRenderArea().getWidth()) || d_forceHorzScroll)
01299 {
01300 d_horzScrollbar->show();
01301 }
01302 else
01303 {
01304 d_horzScrollbar->hide();
01305 }
01306
01307 }
01308 else
01309 {
01310
01311 if ((fullWidth > getListRenderArea().getWidth()) || d_forceHorzScroll)
01312 {
01313 d_horzScrollbar->show();
01314
01315
01316 if ((totalHeight > getListRenderArea().getHeight()) || d_forceVertScroll)
01317 {
01318 d_vertScrollbar->show();
01319 }
01320 else
01321 {
01322 d_vertScrollbar->hide();
01323 }
01324
01325 }
01326 else
01327 {
01328 d_vertScrollbar->hide();
01329 d_horzScrollbar->hide();
01330 }
01331
01332 }
01333
01334
01335
01336
01337 Rect renderArea(getListRenderArea());
01338
01339 d_vertScrollbar->setDocumentSize(totalHeight);
01340 d_vertScrollbar->setPageSize(renderArea.getHeight());
01341 d_vertScrollbar->setStepSize(ceguimax(1.0f, renderArea.getHeight() / 10.0f));
01342 d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition());
01343
01344 d_horzScrollbar->setDocumentSize(fullWidth);
01345 d_horzScrollbar->setPageSize(renderArea.getWidth());
01346 d_horzScrollbar->setStepSize(ceguimax(1.0f, renderArea.getWidth() / 10.0f));
01347 d_horzScrollbar->setScrollPosition(d_horzScrollbar->getScrollPosition());
01348 }
01349
01350
01351
01352
01353
01354 bool MultiColumnList::selectRange(const MCLGridRef& start, const MCLGridRef& end)
01355 {
01356 MCLGridRef tmpStart(start);
01357 MCLGridRef tmpEnd(end);
01358
01359
01360 if (tmpStart.column > tmpEnd.column)
01361 {
01362 tmpStart.column = tmpEnd.column;
01363 tmpEnd.column = start.column;
01364 }
01365
01366 if (tmpStart.row > tmpEnd.row)
01367 {
01368 tmpStart.row = tmpEnd.row;
01369 tmpEnd.row = start.row;
01370 }
01371
01372 bool modified = false;
01373
01374
01375 for (uint i = tmpStart.row; i <= tmpEnd.row; ++i)
01376 {
01377 for (uint j = tmpStart.column; j <= tmpEnd.column; ++j)
01378 {
01379 ListboxItem* item = d_grid[i][j];
01380
01381 if (item != NULL)
01382 {
01383 modified |= setItemSelectState_impl(getItemGridReference(item), true);
01384 }
01385
01386 }
01387
01388 }
01389
01390 return modified;
01391 }
01392
01393
01394
01395
01396
01397 float MultiColumnList::getTotalRowsHeight(void) const
01398 {
01399 float height = 0.0f;
01400
01401 for (uint i = 0; i < getRowCount(); ++i)
01402 {
01403 height += getHighestRowItemHeight(i);
01404 }
01405
01406 return height;
01407 }
01408
01409
01410
01411
01412
01413 float MultiColumnList::getWidestColumnItemWidth(uint col_idx) const
01414 {
01415 if (col_idx >= getColumnCount())
01416 {
01417 throw InvalidRequestException((utf8*)"MultiColumnList::getWidestColumnItemWidth - specified column is out of range.");
01418 }
01419 else
01420 {
01421 float width = 0.0f;
01422
01423
01424 for (uint i = 0; i < getRowCount(); ++i)
01425 {
01426 ListboxItem* item = d_grid[i][col_idx];
01427
01428
01429 if (item != NULL)
01430 {
01431 Size sz(item->getPixelSize());
01432
01433
01434 if (sz.d_width > width)
01435 {
01436
01437 width = sz.d_width;
01438 }
01439
01440 }
01441
01442 }
01443
01444
01445 return width;
01446 }
01447
01448 }
01449
01450
01451
01452
01453
01454 float MultiColumnList::getHighestRowItemHeight(uint row_idx) const
01455 {
01456 if (row_idx >= getRowCount())
01457 {
01458 throw InvalidRequestException((utf8*)"MultiColumnList::getHighestRowItemHeight - specified row is out of range.");
01459 }
01460 else
01461 {
01462 float height = 0.0f;
01463
01464
01465 for (uint i = 0; i < getColumnCount(); ++i)
01466 {
01467 ListboxItem* item = d_grid[row_idx][i];
01468
01469
01470 if (item != NULL)
01471 {
01472 Size sz(item->getPixelSize());
01473
01474
01475 if (sz.d_height > height)
01476 {
01477
01478 height = sz.d_height;
01479 }
01480
01481 }
01482
01483 }
01484
01485
01486 return height;
01487 }
01488
01489 }
01490
01491
01492
01493
01494
01495 bool MultiColumnList::clearAllSelections_impl(void)
01496 {
01497
01498 bool modified = false;
01499
01500 for (uint i = 0; i < getRowCount(); ++i)
01501 {
01502 for (uint j = 0; j < getColumnCount(); ++j)
01503 {
01504 ListboxItem* item = d_grid[i][j];
01505
01506
01507 if ((item != NULL) && item->isSelected())
01508 {
01509
01510 item->setSelected(false);
01511 modified = true;
01512 }
01513
01514 }
01515
01516 }
01517
01518
01519 return modified;
01520 }
01521
01522
01523
01524
01525
01526 ListboxItem* MultiColumnList::getItemAtPoint(const Point& pt) const
01527 {
01528 Rect listArea(getListRenderArea());
01529
01530 float y = listArea.d_top - d_vertScrollbar->getScrollPosition();
01531 float x = listArea.d_left - d_horzScrollbar->getScrollPosition();
01532
01533 for (uint i = 0; i < getRowCount(); ++i)
01534 {
01535 y += getHighestRowItemHeight(i);
01536
01537
01538 if (pt.d_y < y)
01539 {
01540
01541 for (uint j = 0; j < getColumnCount(); ++j)
01542 {
01543 x += d_header->getColumnPixelWidth(j);
01544
01545
01546 if (pt.d_x < x)
01547 {
01548
01549 return d_grid[i][j];
01550 }
01551
01552 }
01553
01554 }
01555
01556 }
01557
01558 return NULL;
01559 }
01560
01561
01562
01563
01564
01565
01566
01567 bool MultiColumnList::setItemSelectState_impl(const MCLGridRef grid_ref, bool state)
01568 {
01569
01570 if (grid_ref.column >= getColumnCount())
01571 {
01572 throw InvalidRequestException((utf8*)"MultiColumnList::setItemSelectState - the specified column index is invalid.");
01573 }
01574 else if (grid_ref.row >= getRowCount())
01575 {
01576 throw InvalidRequestException((utf8*)"MultiColumnList::setItemSelectState - the specified row index is invalid.");
01577 }
01578
01579
01580 if (d_grid[grid_ref.row][grid_ref.column]->isSelected() != state)
01581 {
01582
01583 if ((!d_useNominatedCol || (d_nominatedSelectCol == grid_ref.column)) &&
01584 (!d_useNominatedRow || (d_nominatedSelectRow == grid_ref.row)))
01585 {
01586
01587 if (state && (!d_multiSelect))
01588 {
01589 clearAllSelections_impl();
01590 }
01591
01592
01593 if (d_fullRowSelect)
01594 {
01595
01596 setSelectForItemsInRow(grid_ref.row, state);
01597 }
01598
01599 else if (d_fullColSelect)
01600 {
01601
01602 setSelectForItemsInColumn(grid_ref.column, state);
01603
01604 }
01605
01606 else
01607 {
01608 d_grid[grid_ref.row][grid_ref.column]->setSelected(state);
01609 }
01610
01611 return true;
01612 }
01613
01614 }
01615
01616 return false;
01617 }
01618
01619
01620
01621
01622
01623 void MultiColumnList::setSelectForItemsInRow(uint row_idx, bool state)
01624 {
01625 for (uint i = 0; i < getColumnCount(); ++i)
01626 {
01627 ListboxItem* item = d_grid[row_idx][i];
01628
01629 if (item != NULL)
01630 {
01631 item->setSelected(state);
01632 }
01633
01634 }
01635
01636 }
01637
01638
01639
01640
01641
01642 void MultiColumnList::setSelectForItemsInColumn(uint col_idx, bool state)
01643 {
01644 for (uint i = 0; i < getRowCount(); ++i)
01645 {
01646 ListboxItem* item = d_grid[i][col_idx];
01647
01648 if (item != NULL)
01649 {
01650 item->setSelected(state);
01651 }
01652
01653 }
01654
01655 }
01656
01657
01658
01659
01660
01661
01662
01663 void MultiColumnList::moveColumn_impl(uint col_idx, uint position)
01664 {
01665
01666 if (col_idx >= getColumnCount())
01667 {
01668 throw InvalidRequestException((utf8*)"MultiColumnList::moveColumn - the specified source column index is out of range.");
01669 }
01670 else
01671 {
01672
01673 if (position > getColumnCount())
01674 {
01675 position = getColumnCount();
01676 }
01677
01678
01679 if (d_nominatedSelectCol == col_idx)
01680 {
01681 d_nominatedSelectCol = position;
01682 }
01683 else if ((col_idx < d_nominatedSelectCol) && (position >= d_nominatedSelectCol))
01684 {
01685 d_nominatedSelectCol--;
01686 }
01687 else if ((col_idx > d_nominatedSelectCol) && (position <= d_nominatedSelectCol))
01688 {
01689 d_nominatedSelectCol++;
01690 }
01691
01692
01693 for (uint i = 0; i < getRowCount(); ++i)
01694 {
01695
01696 ListboxItem* item = d_grid[i][col_idx];
01697
01698
01699 d_grid[i].d_items.erase(d_grid[i].d_items.begin() + col_idx);
01700
01701
01702 d_grid[i].d_items.insert(d_grid[i].d_items.begin() + position, item);
01703 }
01704
01705 }
01706
01707 }
01708
01709
01710
01711
01712
01713
01714 void MultiColumnList::drawSelf(float z)
01715 {
01716
01717 renderListboxBaseImagery(z);
01718
01719
01720
01721
01722 Vector3 itemPos;
01723 Size itemSize;
01724 Rect itemClipper;
01725
01726
01727 Rect absarea(getListRenderArea());
01728 absarea.offset(getUnclippedPixelRect().getPosition());
01729
01730
01731 Rect clipper(absarea.getIntersection(getPixelRect()));
01732
01733
01734 itemPos.d_y = PixelAligned(absarea.d_top - d_vertScrollbar->getScrollPosition());
01735 itemPos.d_z = System::getSingleton().getRenderer()->getZLayer(3);
01736
01737 float alpha = getEffectiveAlpha();
01738
01739
01740 for (uint i = 0; i < getRowCount(); ++i)
01741 {
01742
01743 itemPos.d_x = PixelAligned(absarea.d_left - d_horzScrollbar->getScrollPosition());
01744
01745
01746 itemSize.d_height = getHighestRowItemHeight(i);
01747
01748
01749 for (uint j = 0; j < getColumnCount(); ++j)
01750 {
01751
01752 itemSize.d_width = d_header->getColumnPixelWidth(j);
01753
01754 ListboxItem* item = d_grid[i][j];
01755
01756
01757 if (item != NULL)
01758 {
01759
01760 itemClipper.d_left = itemPos.d_x;
01761 itemClipper.d_top = itemPos.d_y;
01762 itemClipper.setSize(itemSize);
01763 itemClipper = itemClipper.getIntersection(clipper);
01764
01765
01766 if (itemClipper.getWidth() == 0)
01767 {
01768 itemPos.d_x += PixelAligned(itemSize.d_width);
01769 continue;
01770 }
01771
01772
01773 item->draw(itemPos, alpha, itemClipper);
01774 }
01775
01776
01777 itemPos.d_x += PixelAligned(itemSize.d_width);
01778 }
01779
01780
01781 itemPos.d_y += PixelAligned(itemSize.d_height);
01782 }
01783
01784 }
01785
01786
01787
01788
01789
01790 void MultiColumnList::onSelectionModeChanged(WindowEventArgs& e)
01791 {
01792 fireEvent(EventSelectionModeChanged, e, EventNamespace);
01793 }
01794
01795
01796
01797
01798
01799 void MultiColumnList::onNominatedSelectColumnChanged(WindowEventArgs& e)
01800 {
01801 fireEvent(EventNominatedSelectColumnChanged, e, EventNamespace);
01802 }
01803
01804
01805
01806
01807
01808 void MultiColumnList::onNominatedSelectRowChanged(WindowEventArgs& e)
01809 {
01810 fireEvent(EventNominatedSelectRowChanged, e, EventNamespace);
01811 }
01812
01813
01814
01815
01816
01817 void MultiColumnList::onVertScrollbarModeChanged(WindowEventArgs& e)
01818 {
01819 fireEvent(EventVertScrollbarModeChanged, e, EventNamespace);
01820 }
01821
01822
01823
01824
01825
01826 void MultiColumnList::onHorzScrollbarModeChanged(WindowEventArgs& e)
01827 {
01828 fireEvent(EventHorzScrollbarModeChanged, e, EventNamespace);
01829 }
01830
01831
01832
01833
01834
01835 void MultiColumnList::onSelectionChanged(WindowEventArgs& e)
01836 {
01837 requestRedraw();
01838 fireEvent(EventSelectionChanged, e, EventNamespace);
01839 }
01840
01841
01842
01843
01844
01845 void MultiColumnList::onListContentsChanged(WindowEventArgs& e)
01846 {
01847 configureScrollbars();
01848 requestRedraw();
01849 fireEvent(EventListContentsChanged, e, EventNamespace);
01850 }
01851
01852
01853
01854
01855
01856 void MultiColumnList::onSortColumnChanged(WindowEventArgs& e)
01857 {
01858 requestRedraw();
01859 fireEvent(EventSortColumnChanged, e, EventNamespace);
01860 }
01861
01862
01863
01864
01865
01866 void MultiColumnList::onSortDirectionChanged(WindowEventArgs& e)
01867 {
01868 requestRedraw();
01869 fireEvent(EventSortDirectionChanged, e, EventNamespace);
01870 }
01871
01872
01873
01874
01875
01876 void MultiColumnList::onListColumnSized(WindowEventArgs& e)
01877 {
01878 configureScrollbars();
01879 requestRedraw();
01880 fireEvent(EventListColumnSized, e, EventNamespace);
01881 }
01882
01883
01884
01885
01886
01887 void MultiColumnList::onListColumnMoved(WindowEventArgs& e)
01888 {
01889 requestRedraw();
01890 fireEvent(EventListColumnMoved, e, EventNamespace);
01891 }
01892
01893
01894
01895
01896
01897 void MultiColumnList::onSized(WindowEventArgs& e)
01898 {
01899
01900 Window::onSized(e);
01901
01902 configureScrollbars();
01903 layoutComponentWidgets();
01904
01905 e.handled = true;
01906 }
01907
01908
01909
01910
01911
01912 void MultiColumnList::onMouseButtonDown(MouseEventArgs& e)
01913 {
01914
01915 Window::onMouseButtonDown(e);
01916
01917 if (e.button == LeftButton)
01918 {
01919 bool modified = false;
01920
01921
01922 if (!(e.sysKeys & Control) || !d_multiSelect)
01923 {
01924 modified = clearAllSelections_impl();
01925 }
01926
01927 Point localPos(screenToWindow(e.position));
01928
01929 if (getMetricsMode() == Relative)
01930 {
01931 localPos = relativeToAbsolute(localPos);
01932 }
01933
01934 ListboxItem* item = getItemAtPoint(localPos);
01935
01936 if (item != NULL)
01937 {
01938 modified = true;
01939
01940
01941 if (((e.sysKeys & Shift) && (d_lastSelected != NULL)) && d_multiSelect)
01942 {
01943 modified |= selectRange(getItemGridReference(item), getItemGridReference(d_lastSelected));
01944 }
01945 else
01946 {
01947 modified |= setItemSelectState_impl(getItemGridReference(item), item->isSelected() ^ true);
01948 }
01949
01950
01951 d_lastSelected = item->isSelected() ? item : NULL;
01952 }
01953
01954
01955 if (modified)
01956 {
01957 WindowEventArgs args(this);
01958 onSelectionChanged(args);
01959 }
01960
01961 e.handled = true;
01962 }
01963
01964 }
01965
01966
01967
01968
01969
01970 void MultiColumnList::onMouseWheel(MouseEventArgs& e)
01971 {
01972
01973 Window::onMouseWheel(e);
01974
01975 if (d_vertScrollbar->isVisible() && (d_vertScrollbar->getDocumentSize() > d_vertScrollbar->getPageSize()))
01976 {
01977 d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition() + d_vertScrollbar->getStepSize() * -e.wheelChange);
01978 }
01979 else if (d_horzScrollbar->isVisible() && (d_horzScrollbar->getDocumentSize() > d_horzScrollbar->getPageSize()))
01980 {
01981 d_horzScrollbar->setScrollPosition(d_horzScrollbar->getScrollPosition() + d_horzScrollbar->getStepSize() * -e.wheelChange);
01982 }
01983
01984 e.handled = true;
01985 }
01986
01987
01988
01989
01990
01991 bool MultiColumnList::handleHeaderScroll(const EventArgs& e)
01992 {
01993
01994 d_horzScrollbar->setScrollPosition(d_header->relativeToAbsoluteX(d_header->getSegmentOffset()));
01995
01996 return true;
01997 }
01998
01999
02000
02001
02002
02003 bool MultiColumnList::handleHeaderSegMove(const EventArgs& e)
02004 {
02005 moveColumn_impl(((HeaderSequenceEventArgs&)e).d_oldIdx, ((HeaderSequenceEventArgs&)e).d_newIdx);
02006
02007
02008 WindowEventArgs args(this);
02009 onListColumnMoved(args);
02010
02011 return true;
02012 }
02013
02014
02015
02016
02017
02018
02019 bool MultiColumnList::handleColumnSizeChange(const EventArgs& e)
02020 {
02021 configureScrollbars();
02022
02023
02024 WindowEventArgs args(this);
02025 onListColumnSized(args);
02026
02027 return true;
02028 }
02029
02030
02031
02032
02033
02034 bool MultiColumnList::handleHorzScrollbar(const EventArgs& e)
02035 {
02036
02037 d_header->setSegmentOffset(d_header->absoluteToRelativeX(d_horzScrollbar->getScrollPosition()));
02038
02039 return true;
02040 }
02041
02042
02043
02044
02045
02046 bool MultiColumnList::handleSortColumnChange(const EventArgs& e)
02047 {
02048 uint col = getSortColumn();
02049
02050
02051 for (uint i = 0; i < getRowCount(); ++i)
02052 {
02053 d_grid[i].d_sortColumn = col;
02054 }
02055
02056
02057 ListHeaderSegment::SortDirection dir = getSortDirection();
02058
02059 if (dir == ListHeaderSegment::Descending)
02060 {
02061 std::sort(d_grid.begin(), d_grid.end());
02062 }
02063 else if (dir == ListHeaderSegment::Ascending)
02064 {
02065 std::sort(d_grid.begin(), d_grid.end(), pred_descend);
02066 }
02067
02068
02069
02070
02071 WindowEventArgs args(this);
02072 onSortColumnChanged(args);
02073
02074 return true;
02075 }
02076
02077
02078
02079
02080
02081 bool MultiColumnList::handleSortDirectionChange(const EventArgs& e)
02082 {
02083
02084 ListHeaderSegment::SortDirection dir = getSortDirection();
02085
02086 if (dir == ListHeaderSegment::Descending)
02087 {
02088 std::sort(d_grid.begin(), d_grid.end());
02089 }
02090 else if (dir == ListHeaderSegment::Ascending)
02091 {
02092 std::sort(d_grid.begin(), d_grid.end(), pred_descend);
02093 }
02094
02095
02096
02097
02098 WindowEventArgs args(this);
02099 onSortDirectionChanged(args);
02100
02101 return true;
02102 }
02103
02104
02105
02106
02107
02108 bool MultiColumnList::handleHeaderSegDblClick(const EventArgs& e)
02109 {
02110
02111 uint col = d_header->getColumnFromSegment((ListHeaderSegment&)*((WindowEventArgs&)e).window);
02112
02113 autoSizeColumnHeader(col);
02114
02115 return true;
02116 }
02117
02118
02119
02120
02121
02122
02123 void MultiColumnList::setUserSortControlEnabled(bool setting)
02124 {
02125 d_header->setSortingEnabled(setting);
02126 }
02127
02128
02129
02130
02131
02132 void MultiColumnList::setUserColumnSizingEnabled(bool setting)
02133 {
02134 d_header->setColumnSizingEnabled(setting);
02135 }
02136
02137
02138
02139
02140
02141 void MultiColumnList::setUserColumnDraggingEnabled(bool setting)
02142 {
02143 d_header->setColumnDraggingEnabled(setting);
02144 }
02145
02146
02147
02148
02149
02150 uint MultiColumnList::getColumnID(uint col_idx) const
02151 {
02152 return d_header->getSegmentFromColumn(col_idx).getID();
02153 }
02154
02155
02156
02157
02158
02159 bool MultiColumnList::pred_descend(const ListRow& a, const ListRow& b)
02160 {
02161 return a > b;
02162 }
02163
02164
02165
02166
02167
02168 bool MultiColumnList::isVertScrollbarAlwaysShown(void) const
02169 {
02170 return d_forceVertScroll;
02171 }
02172
02173
02174
02175
02176
02177 bool MultiColumnList::isHorzScrollbarAlwaysShown(void) const
02178 {
02179 return d_forceHorzScroll;
02180 }
02181
02182
02183
02184
02185
02186 void MultiColumnList::addMultiColumnListProperties(void)
02187 {
02188 addProperty(&d_columnsSizableProperty);
02189 addProperty(&d_columnsMovableProperty);
02190 addProperty(&d_forceHorzScrollProperty);
02191 addProperty(&d_forceVertScrollProperty);
02192 addProperty(&d_nominatedSelectColProperty);
02193 addProperty(&d_nominatedSelectRowProperty);
02194 addProperty(&d_selectModeProperty);
02195 addProperty(&d_sortColumnIDProperty);
02196 addProperty(&d_sortDirectionProperty);
02197 addProperty(&d_sortSettingProperty);
02198 }
02199
02200
02201
02202
02203
02204 bool MultiColumnList::resetList_impl(void)
02205 {
02206
02207 if (getRowCount() == 0)
02208 {
02209 return false;
02210 }
02211
02212 else
02213 {
02214 for (uint i = 0; i < getRowCount(); ++i)
02215 {
02216 for (uint j = 0; j < getColumnCount(); ++j)
02217 {
02218 ListboxItem* item = d_grid[i][j];
02219
02220
02221 if ((item != NULL) && item->isAutoDeleted())
02222 {
02223 delete item;
02224 }
02225
02226 }
02227
02228 }
02229
02230
02231 d_grid.clear();
02232
02233
02234 d_nominatedSelectRow = 0;
02235 d_lastSelected = NULL;
02236
02237 return true;
02238 }
02239
02240 }
02241
02242
02243
02244
02245
02246
02247 void MultiColumnList::autoSizeColumnHeader(uint col_idx)
02248 {
02249
02250 if (col_idx >= getColumnCount())
02251 {
02252 throw InvalidRequestException((utf8*)"MultiColumnList::isListboxItemInColumn - the column index given is out of range.");
02253 }
02254 else
02255 {
02256
02257 float width = ceguimax(getWidestColumnItemWidth(col_idx), ListHeader::MinimumSegmentPixelWidth);
02258
02259
02260 if (getMetricsMode() == Relative)
02261 {
02262 width = absoluteToRelativeX(width);
02263 }
02264
02265
02266 setColumnHeaderWidth(col_idx, width);
02267 }
02268
02269 }
02270
02271
02273
02274
02275
02277
02278
02279
02280 bool MultiColumnList::ListRow::operator<(const ListRow& rhs) const
02281 {
02282 ListboxItem* a = d_items[d_sortColumn];
02283 ListboxItem* b = rhs.d_items[d_sortColumn];
02284
02285
02286 if (b == NULL)
02287 {
02288 return false;
02289 }
02290 else if (a == NULL)
02291 {
02292 return true;
02293 }
02294 else
02295 {
02296 return a->getText() < b->getText();
02297 }
02298
02299 }
02300
02301
02302
02303
02304
02305 bool MultiColumnList::ListRow::operator>(const ListRow& rhs) const
02306 {
02307 ListboxItem* a = d_items[d_sortColumn];
02308 ListboxItem* b = rhs.d_items[d_sortColumn];
02309
02310
02311 if (a == NULL)
02312 {
02313 return false;
02314 }
02315 else if (b == NULL)
02316 {
02317 return true;
02318 }
02319 else
02320 {
02321 return a->getText() > b->getText();
02322 }
02323
02324 }
02325
02326
02328
02329
02330
02332
02333
02334
02335 MCLGridRef& MCLGridRef::operator=(const MCLGridRef& rhs)
02336 {
02337 column = rhs.column;
02338 row = rhs.row;
02339 return *this;
02340 }
02341
02342
02343
02344
02345
02346 bool MCLGridRef::operator<(const MCLGridRef& rhs) const
02347 {
02348 if ((row < rhs.row) ||
02349 ((row == rhs.row) && (column < rhs.column)))
02350 {
02351 return true;
02352 }
02353 else
02354 {
02355 return false;
02356 }
02357 }
02358
02359
02360
02361
02362
02363 bool MCLGridRef::operator<=(const MCLGridRef& rhs) const
02364 {
02365 return !operator>(rhs);
02366 }
02367
02368
02369
02370
02371
02372 bool MCLGridRef::operator>(const MCLGridRef& rhs) const
02373 {
02374 return (operator<(rhs) || operator==(rhs)) ? false : true;
02375 }
02376
02377
02378
02379
02380
02381 bool MCLGridRef::operator>=(const MCLGridRef& rhs) const
02382 {
02383 return !operator<(rhs);
02384 }
02385
02386
02387
02388
02389
02390 bool MCLGridRef::operator==(const MCLGridRef& rhs) const
02391 {
02392 return ((column == rhs.column) && (row == rhs.row)) ? true : false;
02393 }
02394
02395
02396
02397
02398
02399 bool MCLGridRef::operator!=(const MCLGridRef& rhs) const
02400 {
02401 return !operator==(rhs);
02402 }
02403
02404 }