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