Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

CEGUIMultiColumnList.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002         filename:       CEGUIMultiColumnList.cpp
00003         created:        13/4/2004
00004         author:         Paul D Turner
00005         
00006         purpose:        Implementation of MultiColumnList widget base class
00007 *************************************************************************/
00008 /*************************************************************************
00009     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00010     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00011 
00012     This library is free software; you can redistribute it and/or
00013     modify it under the terms of the GNU Lesser General Public
00014     License as published by the Free Software Foundation; either
00015     version 2.1 of the License, or (at your option) any later version.
00016 
00017     This library is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020     Lesser General Public License for more details.
00021 
00022     You should have received a copy of the GNU Lesser General Public
00023     License along with this library; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // Start of CEGUI namespace section
00037 namespace CEGUI
00038 {
00039 const String MultiColumnList::EventNamespace("MultiColumnList");
00040 
00041 /*************************************************************************
00042         Properties for this class
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         Constants
00058 *************************************************************************/
00059 // Event names
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         Constructor for the Multi-column list base class
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         // add multi-column list box specific events
00085         addMultiColumnListboxEvents();
00086 
00087         // add properties
00088         addMultiColumnListProperties();
00089 
00090         // set default selection mode
00091         d_selectMode = CellSingle;              // hack to ensure call below does what it should.
00092         setSelectionMode(RowSingle);
00093 }
00094 
00095 
00096 /*************************************************************************
00097         Destructor for the multi-column list base class.
00098 *************************************************************************/
00099 MultiColumnList::~MultiColumnList(void)
00100 {
00101         // delete any items we are supposed to
00102         resetList_impl();
00103 }
00104 
00105 
00106 /*************************************************************************
00107         Return whether user manipulation of the sort column and direction
00108         is enabled.
00109 *************************************************************************/
00110 bool MultiColumnList::isUserSortControlEnabled(void) const
00111 {
00112         return d_header->isSortingEnabled();
00113 }
00114 
00115 
00116 /*************************************************************************
00117         Return whether the user may size column segments.       
00118 *************************************************************************/
00119 bool MultiColumnList::isUserColumnSizingEnabled(void) const
00120 {
00121         return d_header->isColumnSizingEnabled();
00122 }
00123 
00124 
00125 /*************************************************************************
00126         Return whether the user may modify the order of the columns.    
00127 *************************************************************************/
00128 bool MultiColumnList::isUserColumnDraggingEnabled(void) const
00129 {
00130         return d_header->isColumnDraggingEnabled();
00131 }
00132 
00133 
00134 /*************************************************************************
00135         Return the number of columns in the multi-column list   
00136 *************************************************************************/
00137 uint MultiColumnList::getColumnCount(void) const
00138 {
00139         return d_header->getColumnCount();
00140 }
00141 
00142 
00143 /*************************************************************************
00144         Return the number of rows in the multi-column list.     
00145 *************************************************************************/
00146 uint MultiColumnList::getRowCount(void) const
00147 {
00148         return (uint)d_grid.size();
00149 }
00150 
00151 
00152 /*************************************************************************
00153         Return the zero based index of the current sort column.  There must
00154         be at least one column to successfully call this method.
00155 *************************************************************************/
00156 uint MultiColumnList::getSortColumn(void) const
00157 {
00158         return d_header->getSortColumn();
00159 }
00160 
00161 
00162 /*************************************************************************
00163         Return the zero based column index of the column with the specified ID.
00164 *************************************************************************/
00165 uint MultiColumnList::getColumnWithID(uint col_id) const
00166 {
00167         return d_header->getColumnFromID(col_id);
00168 }
00169 
00170 
00171 /*************************************************************************
00172         Return the zero based index of the column whos header text matches
00173         the specified text.     
00174 *************************************************************************/
00175 uint MultiColumnList::getColumnWithHeaderText(const String& text) const
00176 {
00177         return d_header->getColumnWithText(text);
00178 }
00179 
00180 
00181 /*************************************************************************
00182         Return the total width of all column headers.
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         Return the width of the specified column header.        
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         Return the currently set sort direction.
00215 *************************************************************************/
00216 ListHeaderSegment::SortDirection MultiColumnList::getSortDirection(void) const
00217 {
00218         return d_header->getSortDirection();
00219 }
00220 
00221 
00222 /*************************************************************************
00223         Return the ListHeaderSegment object for the specified column
00224 *************************************************************************/
00225 ListHeaderSegment& MultiColumnList::getHeaderSegmentForColumn(uint col_idx) const
00226 {
00227         return d_header->getSegmentFromColumn(col_idx);
00228 }
00229 
00230 
00231 /*************************************************************************
00232         return index of row containing the given ListboxItem
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         // item is not attached to the list box, throw...
00246         throw InvalidRequestException((utf8*)"MultiColumnList::getItemRowIndex - the given ListboxItem is not attached to this MultiColumnList.");
00247 }
00248 
00249 
00250 /*************************************************************************
00251         return the index of the column containing the given ListboxItem
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         // item is not attached to the list box, throw...
00265         throw InvalidRequestException((utf8*)"MultiColumnList::getItemColumnIndex - the given ListboxItem is not attached to this MultiColumnList.");
00266 }
00267 
00268 
00269 /*************************************************************************
00270         return an MCLGridRef for the given ListboxItem.
00271 *************************************************************************/
00272 MCLGridRef MultiColumnList::getItemGridReference(const ListboxItem* item) const
00273 {
00274         return MCLGridRef(getItemRowIndex(item), getItemColumnIndex(item));
00275 }
00276 
00277 
00278 /*************************************************************************
00279         return a ListboxItem pointer for the given reference.
00280         May be NULL if position is blank.  Throws on out of range.
00281 *************************************************************************/
00282 ListboxItem* MultiColumnList::getItemAtGridReference(const MCLGridRef& grid_ref) const
00283 {
00284         // check for invalid grid ref
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         return true if the given item is in the given column.
00303 *************************************************************************/
00304 bool MultiColumnList::isListboxItemInColumn(const ListboxItem* item, uint col_idx) const
00305 {
00306         // check for invalid index
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                 // Item was not in the column.
00323                 return false;
00324         }
00325 
00326 }
00327 
00328 
00329 /*************************************************************************
00330         return true if the given item is in the given row.
00331 *************************************************************************/
00332 bool MultiColumnList::isListboxItemInRow(const ListboxItem* item, uint row_idx) const
00333 {
00334         // check for invalid index
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                 // Item was not in the row.
00351                 return false;
00352         }
00353 
00354 }
00355 
00356 
00357 /*************************************************************************
00358         return true if the given item is somewhere in the list box.
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         Search the items in column 'col_idx' and return the first item after
00381         'start_item' that matches the specified text.  If 'start_item' is NULL
00382         searching start at (and includes) the first item in the column.
00383 *************************************************************************/
00384 ListboxItem* MultiColumnList::findColumnItemWithText(const String& text, uint col_idx, const ListboxItem* start_item) const
00385 {
00386         // ensure column is valid
00387         if (col_idx >= getColumnCount())
00388         {
00389                 throw InvalidRequestException((utf8*)"MultiColumnList::findColumnItemWithText - specified column index is out of range.");
00390         }
00391 
00392         // find start position for search
00393         uint i = (start_item == NULL) ? 0 : getItemRowIndex(start_item) + 1;
00394 
00395         for ( ; i < getRowCount(); ++i)
00396         {
00397                 // does this item match?
00398                 if (d_grid[i][col_idx]->getText() == text)
00399                 {
00400                         return d_grid[i][col_idx];
00401                 }
00402 
00403         }
00404 
00405         // no matching item.
00406         return NULL;
00407 }
00408 
00409 
00410 /*************************************************************************
00411         Search the items in row 'row_idx' and return the first item after
00412         'start_item' that matches the specified text.  If 'start_item' is NULL
00413         searching start at (and includes) the first item in the row.
00414 *************************************************************************/
00415 ListboxItem* MultiColumnList::findRowItemWithText(const String& text, uint row_idx, const ListboxItem* start_item) const
00416 {
00417         // ensure row is valid
00418         if (row_idx >= getRowCount())
00419         {
00420                 throw InvalidRequestException((utf8*)"MultiColumnList::findRowItemWithText - specified row index is out of range.");
00421         }
00422 
00423         // find start position for search
00424         uint i = (start_item == NULL) ? 0 : getItemColumnIndex(start_item) + 1;
00425 
00426         for ( ; i < getColumnCount(); ++i)
00427         {
00428                 // does this item match?
00429                 if (d_grid[row_idx][i]->getText() == text)
00430                 {
00431                         return d_grid[row_idx][i];
00432                 }
00433 
00434         }
00435 
00436         // no matching item.
00437         return NULL;
00438 }
00439 
00440 
00441 /*************************************************************************
00442         Search the list and return the first item after 'start_item' that
00443         matches the specified text.  If 'start_item' is NULL searching starts
00444         at (and includes) the first item in the list.
00445 
00446         Searching proceeds across the columns and down the rows.
00447 *************************************************************************/
00448 ListboxItem* MultiColumnList::findListItemWithText(const String& text, const ListboxItem* start_item) const
00449 {
00450         MCLGridRef startRef(0, 0);
00451         
00452         // get position of start_item if it's not NULL
00453         if (start_item != NULL)
00454         {
00455                 startRef = getItemGridReference(start_item);
00456                 ++startRef.column;
00457         }
00458 
00459         // perform the search
00460         for (uint i = startRef.row; i < getRowCount(); ++i)
00461         {
00462                 for (uint j = startRef.column; j < getColumnCount(); ++j)
00463                 {
00464                         // does this item match?
00465                         if (d_grid[i][j]->getText() == text)
00466                         {
00467                                 return d_grid[i][j];
00468                         }
00469 
00470                 }
00471 
00472         }
00473 
00474         // No match
00475         return NULL;
00476 }
00477 
00478 
00479 /*************************************************************************
00480         Scan the list (across columns for each row) and return the first
00481         selected item.
00482 *************************************************************************/
00483 ListboxItem* MultiColumnList::getFirstSelectedItem(void) const
00484 {
00485         return getNextSelected(NULL);
00486 }
00487 
00488 
00489 /*************************************************************************
00490         Search the list and return the first item after 'start_item' that
00491         is selected.  If 'start_item' is NULL searching starts at (and
00492         includes) the first item in the list.
00493 
00494         Searching proceeds across the columns and down the rows.
00495 *************************************************************************/
00496 ListboxItem* MultiColumnList::getNextSelected(const ListboxItem* start_item) const
00497 {
00498         MCLGridRef startRef(0, 0);
00499 
00500         // get position of start_item if it's not NULL
00501         if (start_item != NULL)
00502         {
00503                 startRef = getItemGridReference(start_item);
00504                 ++startRef.column;
00505         }
00506 
00507         // perform the search
00508         for (uint i = startRef.row; i < getRowCount(); ++i)
00509         {
00510                 for (uint j = startRef.column; j < getColumnCount(); ++j)
00511                 {
00512                         // does this item match?
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         // No match
00525         return NULL;
00526 }
00527 
00528 
00529 /*************************************************************************
00530         Return the total number of selected items
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         Return whether the item at the given grid position is selected.
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         // if no item exists here, then it can't be selected.
00568         return false;
00569 }
00570 
00571 
00572 /*************************************************************************
00573         Return the ID of the nominated selection column
00574 *************************************************************************/
00575 uint MultiColumnList::getNominatedSelectionColumnID(void) const
00576 {
00577         return d_header->getSegmentFromColumn(d_nominatedSelectCol).getID();
00578 }
00579 
00580 
00581 /*************************************************************************
00582         Return the nominated selection column
00583 *************************************************************************/
00584 uint MultiColumnList::getNominatedSelectionColumn(void) const
00585 {
00586         return d_nominatedSelectCol;
00587 }
00588 
00589 
00590 /*************************************************************************
00591         Return the nominated selection row.
00592 *************************************************************************/
00593 uint MultiColumnList::getNominatedSelectionRow(void) const
00594 {
00595         return d_nominatedSelectRow;
00596 }
00597 
00598 
00599 /*************************************************************************
00600         Return the active selection mode.
00601 *************************************************************************/
00602 MultiColumnList::SelectionMode MultiColumnList::getSelectionMode(void) const
00603 {
00604         return d_selectMode;
00605 }
00606 
00607 
00608 /*************************************************************************
00609         Initialise the Window based object ready for use.
00610 *************************************************************************/
00611 void MultiColumnList::initialise(void)
00612 {
00613         // create the component sub-widgets
00614         d_vertScrollbar = createVertScrollbar();
00615         d_horzScrollbar = createHorzScrollbar();
00616         d_header                = createListHeader();
00617 
00618         // add components
00619         addChildWindow(d_vertScrollbar);
00620         addChildWindow(d_horzScrollbar);
00621         addChildWindow(d_header);
00622 
00623         // subscribe some events
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         // final initialisation now widget is complete
00633         setSortDirection(ListHeaderSegment::None);
00634 
00635         // Perform initial layout
00636         configureScrollbars();
00637         layoutComponentWidgets();
00638 }
00639 
00640 
00641 /*************************************************************************
00642         Remove all items from the list.
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         Add a column to the table.
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         Insert a column into the table.
00666 *************************************************************************/
00667 void MultiColumnList::insertColumn(const String& text, uint col_id, float width, uint position)
00668 {
00669         // if position is out of range, add item to end of current columns.
00670         if (position > getColumnCount())
00671         {
00672                 position = getColumnCount();
00673         }
00674 
00675         // get width as pixels
00676         if (getMetricsMode() == Relative)
00677         {
00678                 width = relativeToAbsoluteX(width);
00679         }
00680 
00681         // set-up the header for the new column.
00682         d_header->insertColumn(text, col_id, d_header->absoluteToRelativeX(width), position);
00683 
00684         // Insert a blank entry at the appropriate position in each row.
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         // update stored nominated selection column if that has changed.
00691         if ((d_nominatedSelectCol >= position) && (getColumnCount() > 1))
00692         {
00693                 d_nominatedSelectCol++;
00694         }
00695 
00696         // signal a change to the list contents
00697         WindowEventArgs args(this);
00698         onListContentsChanged(args);
00699 }
00700 
00701 
00702 /*************************************************************************
00703         Remove a column from the table.
00704 *************************************************************************/
00705 void MultiColumnList::removeColumn(uint col_idx)
00706 {
00707         // ensure index is valid, and throw if not.
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                 // update stored column index values
00715                 if (d_nominatedSelectCol == col_idx)
00716                 {
00717                         d_nominatedSelectCol = 0;
00718                 }
00719 
00720                 // remove the column from each row
00721                 for (uint i = 0; i < getRowCount(); ++i)
00722                 {
00723                         // extract the item pointer.
00724                         ListboxItem* item = d_grid[i][col_idx];
00725 
00726                         // remove the column entry from the row
00727                         d_grid[i].d_items.erase(d_grid[i].d_items.begin() + col_idx);
00728 
00729                         // delete the ListboxItem as needed.
00730                         if ((item != NULL) && item->isAutoDeleted())
00731                         {
00732                                 delete item;
00733                         }
00734 
00735                 }
00736 
00737                 // remove header segment
00738                 d_header->removeColumn(col_idx);
00739 
00740                 // signal a change to the list contents
00741                 WindowEventArgs args(this);
00742                 onListContentsChanged(args);
00743         }
00744 
00745 }
00746 
00747 
00748 /*************************************************************************
00749         Remove a column from the table (via ID)
00750 *************************************************************************/
00751 void MultiColumnList::removeColumnWithID(uint col_id)
00752 {
00753         removeColumn(getColumnWithID(col_id));
00754 }
00755 
00756 
00757 /*************************************************************************
00758         Move a column within the table
00759 *************************************************************************/
00760 void MultiColumnList::moveColumn(uint col_idx, uint position)
00761 {
00762         // move the segment on the header, events will ensure the items get moved also.
00763         d_header->moveColumn(col_idx, position);
00764 }
00765 
00766 
00767 /*************************************************************************
00768         Move a column (with specified ID) within the table.
00769 *************************************************************************/
00770 void MultiColumnList::moveColumnWithID(uint col_id, uint position)
00771 {
00772         moveColumn(getColumnWithID(col_id), position);
00773 }
00774 
00775 
00776 /*************************************************************************
00777         Add a row to the bottom of the table
00778 *************************************************************************/
00779 uint MultiColumnList::addRow(void)
00780 {
00781         return addRow(NULL, 0);
00782 }
00783 
00784 
00785 /*************************************************************************
00786         Add a row to the bottom of the table
00787 *************************************************************************/
00788 uint MultiColumnList::addRow(ListboxItem* item, uint col_id)
00789 {
00790         uint col_idx = 0;
00791 
00792         // Build the new row
00793         ListRow row;
00794         row.d_sortColumn = getSortColumn();
00795         row.d_items.resize(getColumnCount(), NULL);
00796 
00797         if (item != NULL)
00798         {
00799                 // discover which column to initially set
00800                 col_idx = getColumnWithID(col_id);
00801 
00802                 // establish item ownership & enter item into column
00803                 item->setOwnerWindow(this);
00804                 row[col_idx] = item;
00805         }
00806 
00807         uint pos;
00808 
00809         // if sorting is enabled, insert at an appropriate position
00810         if (getSortDirection() != ListHeaderSegment::None)
00811         {
00812                 // insert item and get insert position index.
00813                 pos = (uint)std::distance(d_grid.begin(), d_grid.insert(std::upper_bound(d_grid.begin(), d_grid.end(), row), row));
00814         }
00815         // not sorted, just stick it on the end.
00816         else
00817         {
00818                 pos = getRowCount();
00819                 d_grid.push_back(row);
00820         }
00821 
00822         // signal a change to the list contents
00823         WindowEventArgs args(this);
00824         onListContentsChanged(args);
00825 
00826         return pos;
00827 }
00828 
00829 
00830 /*************************************************************************
00831         Insert a row into the table
00832 *************************************************************************/
00833 uint MultiColumnList::insertRow(uint row_idx)
00834 {
00835         return insertRow(NULL, 0, row_idx);
00836 }
00837 
00838 
00839 /*************************************************************************
00840         Insert a row into the table
00841 *************************************************************************/
00842 uint MultiColumnList::insertRow(ListboxItem* item, uint col_id, uint row_idx)
00843 {
00844         // if sorting is enabled, use add instead of insert
00845         if (getSortDirection() != ListHeaderSegment::None)
00846         {
00847                 return addRow(item, col_id);
00848         }
00849         else
00850         {
00851                 uint col_idx = 0;
00852                 
00853                 // Build the new row (empty)
00854                 ListRow row;
00855                 row.d_sortColumn = getSortColumn();
00856                 row.d_items.resize(getColumnCount(), NULL);
00857 
00858                 // if row index is too big, just insert at end.
00859                 if (row_idx > getRowCount())
00860                 {
00861                         row_idx = getRowCount();
00862                 }
00863 
00864                 d_grid.insert(d_grid.begin() + row_idx, row);
00865 
00866                 // set the initial item in the new row
00867                 setItem(item, col_id, row_idx);
00868 
00869                 // signal a change to the list contents
00870                 WindowEventArgs args(this);
00871                 onListContentsChanged(args);
00872 
00873                 return row_idx;
00874         }
00875 
00876 }
00877 
00878 
00879 /*************************************************************************
00880         Remove a row from the list.
00881 *************************************************************************/
00882 void MultiColumnList::removeRow(uint row_idx)
00883 {
00884         // ensure row exists
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                 // delete items we are supposed to
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                 // erase the row from the grid.
00904                 d_grid.erase(d_grid.begin() + row_idx);
00905 
00906                 // if we have erased the selection row, reset that to 0
00907                 if (d_nominatedSelectRow == row_idx)
00908                 {
00909                         d_nominatedSelectRow = 0;
00910                 }
00911 
00912                 // signal a change to the list contents
00913                 WindowEventArgs args(this);
00914                 onListContentsChanged(args);
00915         }
00916 
00917 }
00918 
00919 
00920 /*************************************************************************
00921         Replace the item at grid-ref 'position' with 'item'.
00922         The old item is deleted according to the items auto-delete setting
00923 *************************************************************************/
00924 void MultiColumnList::setItem(ListboxItem* item, const MCLGridRef& position)
00925 {
00926         // validate grid ref
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         // delete old item as required
00937         ListboxItem* oldItem = d_grid[position.row][position.column];
00938 
00939         if ((oldItem != NULL) && item->isAutoDeleted())
00940         {
00941                 delete oldItem;
00942         }
00943 
00944         // set new item.
00945         item->setOwnerWindow(this);
00946         d_grid[position.row][position.column] = item;
00947 
00948 
00949         // signal a change to the list contents
00950         WindowEventArgs args(this);
00951         onListContentsChanged(args);
00952 }
00953 
00954 
00955 /*************************************************************************
00956         Replace the item in row 'row_idx', in the column with ID 'col_id'
00957         with 'item'.  The old item is deleted as required.
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         Set the current selection mode.
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                 // Fire event.
01065                 WindowEventArgs args(this);
01066                 onSelectionModeChanged(args);
01067         }
01068 
01069 }
01070 
01071 
01072 /*************************************************************************
01073         Set the nominated column for 'NominatedColumn*' selections (by ID)
01074 *************************************************************************/
01075 void MultiColumnList::setNominatedSelectionColumnID(uint col_id)
01076 {
01077         setNominatedSelectionColumn(getColumnWithID(col_id));
01078 }
01079 
01080 
01081 /*************************************************************************
01082         Set the nominated column for 'NominatedColumn*' selections (by Index)
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                 // Fire event.
01093                 WindowEventArgs args(this);
01094                 onNominatedSelectColumnChanged(args);
01095         }
01096 
01097 }
01098 
01099 
01100 /*************************************************************************
01101         Set the nominated row for 'NominatedRow*' selections
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                 // Fire event.
01112                 WindowEventArgs args(this);
01113                 onNominatedSelectRowChanged(args);
01114         }
01115 
01116 }
01117 
01118 
01119 /*************************************************************************
01120         Set the current sort direction.
01121 *************************************************************************/
01122 void MultiColumnList::setSortDirection(ListHeaderSegment::SortDirection direction)
01123 {
01124         if (getSortDirection() != direction)
01125         {
01126                 // set the sort direction on the header, events will make sure everything else is updated.
01127                 d_header->setSortDirection(direction);
01128         }
01129 
01130 }
01131 
01132 
01133 /*************************************************************************
01134         Set the current sort column (by index)
01135 *************************************************************************/
01136 void MultiColumnList::setSortColumn(uint col_idx)
01137 {
01138         if (getSortColumn() != col_idx)
01139         {
01140                 // set the sort column on the header, events will make sure everything else is updated.
01141                 d_header->setSortColumn(col_idx);
01142         }
01143 
01144 }
01145 
01146 
01147 /*************************************************************************
01148         Set the current sort column (by ID)
01149 *************************************************************************/
01150 void MultiColumnList::setSortColumnByID(uint col_id)
01151 {
01152         if (d_header->getSegmentFromColumn(getSortColumn()).getID() != col_id)
01153         {
01154                 // set the sort column on the header, events will make sure everything else is updated.
01155                 d_header->setSortColumnFromID(col_id);
01156         }
01157 
01158 }
01159 
01160 
01161 /*************************************************************************
01162         Enable / Disable forced display of the vertical scroll bar
01163 *************************************************************************/
01164 void MultiColumnList::setShowVertScrollbar(bool setting)
01165 {
01166         if (d_forceVertScroll != setting)
01167         {
01168                 d_forceVertScroll = setting;
01169 
01170                 configureScrollbars();
01171 
01172                 // Event firing.
01173                 WindowEventArgs args(this);
01174                 onVertScrollbarModeChanged(args);
01175         }
01176 
01177 }
01178 
01179 
01180 /*************************************************************************
01181         Enable / Disable forced display of the horizontal scroll bar
01182 *************************************************************************/
01183 void MultiColumnList::setShowHorzScrollbar(bool setting)
01184 {
01185         if (d_forceHorzScroll != setting)
01186         {
01187                 d_forceHorzScroll = setting;
01188 
01189                 configureScrollbars();
01190 
01191                 // Event firing.
01192                 WindowEventArgs args(this);
01193                 onHorzScrollbarModeChanged(args);
01194         }
01195 
01196 }
01197 
01198 
01199 /*************************************************************************
01200         Clear the selected state from all currently selected items.
01201 *************************************************************************/
01202 void MultiColumnList::clearAllSelections(void)
01203 {
01204         // only fire events and update if we actually made any changes
01205         if (clearAllSelections_impl())
01206         {
01207                 // Fire event.
01208                 WindowEventArgs args(this);
01209                 onSelectionChanged(args);
01210         }
01211 
01212 
01213 }
01214 
01215 
01216 /*************************************************************************
01217         Set the selected state of 'item' (must be attached to the list box)
01218 *************************************************************************/
01219 void MultiColumnList::setItemSelectState(ListboxItem* item, bool state)
01220 {
01221         setItemSelectState(getItemGridReference(item), state);
01222 }
01223 
01224 
01225 /*************************************************************************
01226         Set the selected state of the item at 'grid_ref'.
01227 *************************************************************************/
01228 void MultiColumnList::setItemSelectState(const MCLGridRef& grid_ref, bool state)
01229 {
01230         if (setItemSelectState_impl(grid_ref, state))
01231         {
01232                 // Fire event.
01233                 WindowEventArgs args(this);
01234                 onSelectionChanged(args);
01235         }
01236 
01237 }
01238 
01239 
01240 /*************************************************************************
01241         Update the list box internal state after attached items have been
01242         externally modified.
01243 *************************************************************************/
01244 void MultiColumnList::handleUpdatedItemData(void)
01245 {
01246         configureScrollbars();
01247         requestRedraw();
01248 }
01249 
01250 
01251 /*************************************************************************
01252         Set the width of the specified column header (and therefore the
01253         column itself). 
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         Add multi column list box specific events       
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         display required integrated scroll bars according to current state
01282         of the list box and update their values.        
01283 *************************************************************************/
01284 void MultiColumnList::configureScrollbars(void)
01285 {
01286         float totalHeight       = getTotalRowsHeight();
01287         float fullWidth         = d_header->getTotalSegmentsPixelExtent();
01288 
01289         //
01290         // First show or hide the scroll bars as needed (or requested)
01291         //
01292         // show or hide vertical scroll bar as required (or as specified by option)
01293         if ((totalHeight > getListRenderArea().getHeight()) || d_forceVertScroll)
01294         {
01295                 d_vertScrollbar->show();
01296 
01297                 // show or hide horizontal scroll bar as required (or as specified by option)
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                 // show or hide horizontal scroll bar as required (or as specified by option)
01311                 if ((fullWidth > getListRenderArea().getWidth()) || d_forceHorzScroll)
01312                 {
01313                         d_horzScrollbar->show();
01314 
01315                         // show or hide vertical scroll bar as required (or as specified by option)
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         // Set up scroll bar values
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         select all strings between positions 'start' and 'end'.  (inclusive)    
01353 *************************************************************************/
01354 bool MultiColumnList::selectRange(const MCLGridRef& start, const MCLGridRef& end)
01355 {
01356         MCLGridRef tmpStart(start);
01357         MCLGridRef tmpEnd(end);
01358 
01359         // ensure start is before end
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         // loop through all items selecting them.
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         Return the sum of all row heights       
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         Return the width of the widest item in the given column 
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                 // check each item in the column
01424                 for (uint i = 0; i < getRowCount(); ++i)
01425                 {
01426                         ListboxItem* item = d_grid[i][col_idx];
01427 
01428                         // if the slot has an item in it
01429                         if (item != NULL)
01430                         {
01431                                 Size sz(item->getPixelSize());
01432 
01433                                 // see if this item is wider than the previous widest
01434                                 if (sz.d_width > width)
01435                                 {
01436                                         // update current widest
01437                                         width = sz.d_width;
01438                                 }
01439 
01440                         }
01441 
01442                 }
01443 
01444                 // return the widest item.
01445                 return width;
01446         }
01447 
01448 }
01449 
01450 
01451 /*************************************************************************
01452         Return the height of the highest item in the given row. 
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                 // check each item in the column
01465                 for (uint i = 0; i < getColumnCount(); ++i)
01466                 {
01467                         ListboxItem* item = d_grid[row_idx][i];
01468 
01469                         // if the slot has an item in it
01470                         if (item != NULL)
01471                         {
01472                                 Size sz(item->getPixelSize());
01473 
01474                                 // see if this item is higher than the previous highest
01475                                 if (sz.d_height > height)
01476                                 {
01477                                         // update current highest
01478                                         height = sz.d_height;
01479                                 }
01480 
01481                         }
01482 
01483                 }
01484 
01485                 // return the hightest item.
01486                 return height;
01487         }
01488         
01489 }
01490 
01491 
01492 /*************************************************************************
01493         Clear the selected state for all items (implementation) 
01494 *************************************************************************/
01495 bool MultiColumnList::clearAllSelections_impl(void)
01496 {
01497         // flag used so we can track if we did anything.
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                         // if slot has an item, and item is selected
01507                         if ((item != NULL) && item->isSelected())
01508                         {
01509                                 // clear selection state and set modified flag
01510                                 item->setSelected(false);
01511                                 modified = true;
01512                         }
01513 
01514                 }
01515 
01516         }
01517 
01518         // signal whether or not we did anything.
01519         return modified;
01520 }
01521 
01522 
01523 /*************************************************************************
01524         Return the ListboxItem under the given window local pixel co-ordinate.  
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                 // have we located the row?
01538                 if (pt.d_y < y)
01539                 {
01540                         // scan across to find column that was clicked
01541                         for (uint j = 0; j < getColumnCount(); ++j)
01542                         {
01543                                 x += d_header->getColumnPixelWidth(j);
01544 
01545                                 // was this the column?
01546                                 if (pt.d_x < x)
01547                                 {
01548                                         // return contents of grid element that was clicked.
01549                                         return d_grid[i][j];
01550                                 }
01551 
01552                         }
01553 
01554                 }
01555 
01556         }
01557 
01558         return NULL;
01559 }
01560 
01561 
01562 /*************************************************************************
01563         Set select state for the given item.  This appropriately selects other
01564         items depending upon the select mode.  Returns true if something is
01565         changed, else false.    
01566 *************************************************************************/
01567 bool MultiColumnList::setItemSelectState_impl(const MCLGridRef grid_ref, bool state)
01568 {
01569         // validate grid ref
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         // only do this if the setting is changing
01580         if (d_grid[grid_ref.row][grid_ref.column]->isSelected() != state)
01581         {
01582                 // if using nominated selection row and/ or column, check that they match.
01583                 if ((!d_useNominatedCol || (d_nominatedSelectCol == grid_ref.column)) &&
01584                         (!d_useNominatedRow || (d_nominatedSelectRow == grid_ref.row)))
01585                 {
01586                         // clear current selection if not multi-select box
01587                         if (state && (!d_multiSelect))
01588                         {
01589                                 clearAllSelections_impl();
01590                         }
01591 
01592                         // full row?
01593                         if (d_fullRowSelect)
01594                         {
01595                                 // clear selection on all items in the row
01596                                 setSelectForItemsInRow(grid_ref.row, state);
01597                         }
01598                         // full column?
01599                         else if (d_fullColSelect)
01600                         {
01601                                 // clear selection on all items in the column
01602                                 setSelectForItemsInColumn(grid_ref.column, state);
01603 
01604                         }
01605                         // single item to be affected
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         Select all items in the given row       
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         Select all items in the given column
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         Move the column at index 'col_idx' so it is at index 'position'.
01659         
01660         Implementation version which does not move the header segment
01661         (since that may have already happned).
01662 *************************************************************************/
01663 void MultiColumnList::moveColumn_impl(uint col_idx, uint position)
01664 {
01665         // ensure index is valid, and throw if not.
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                 // if position is too big, insert at end.
01673                 if (position > getColumnCount())
01674                 {
01675                         position = getColumnCount();
01676                 }
01677 
01678                 // update select column index value if needed
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                 // move column entry in each row.
01693                 for (uint i = 0; i < getRowCount(); ++i)
01694                 {
01695                         // store entry.
01696                         ListboxItem* item = d_grid[i][col_idx];
01697 
01698                         // remove the original column for this row.
01699                         d_grid[i].d_items.erase(d_grid[i].d_items.begin() + col_idx);
01700 
01701                         // insert entry at its new position
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         renders the widget
01713 *************************************************************************/
01714 void MultiColumnList::drawSelf(float z)
01715 {
01716         // get the derived class to render general stuff before we handle the items
01717         renderListboxBaseImagery(z);
01718 
01719         //
01720         // Render list items
01721         //
01722         Vector3 itemPos;
01723         Size    itemSize;
01724         Rect    itemClipper;
01725 
01726         // calculate on-screen position of area we have to render into
01727         Rect absarea(getListRenderArea());
01728         absarea.offset(getUnclippedPixelRect().getPosition());
01729 
01730         // calculate clipper for list rendering area
01731         Rect clipper(absarea.getIntersection(getPixelRect()));
01732 
01733         // set up initial positional details for items
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         // loop through the items
01740         for (uint i = 0; i < getRowCount(); ++i)
01741         {
01742                 // set initial x position for this row.
01743                 itemPos.d_x = PixelAligned(absarea.d_left - d_horzScrollbar->getScrollPosition());
01744 
01745                 // calculate height for this row.
01746                 itemSize.d_height = getHighestRowItemHeight(i);
01747 
01748                 // loop through the columns in this row
01749                 for (uint j = 0; j < getColumnCount(); ++j)
01750                 {
01751                         // allow item to use full width of the column
01752                         itemSize.d_width = d_header->getColumnPixelWidth(j);
01753 
01754                         ListboxItem* item = d_grid[i][j];
01755 
01756                         // is the item for this column set?
01757                         if (item != NULL)
01758                         {
01759                                 // calculate clipper for this item.
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                                 // skip this item if totally clipped
01766                                 if (itemClipper.getWidth() == 0)
01767                                 {
01768                                         itemPos.d_x += PixelAligned(itemSize.d_width);
01769                                         continue;
01770                                 }
01771 
01772                                 // draw this item
01773                                 item->draw(itemPos, alpha, itemClipper);
01774                         }
01775 
01776                         // update position for next column.
01777                         itemPos.d_x += PixelAligned(itemSize.d_width);
01778                 }
01779 
01780                 // update position ready for next row
01781                 itemPos.d_y += PixelAligned(itemSize.d_height);
01782         }
01783 
01784 }
01785 
01786 
01787 /*************************************************************************
01788         Handler called when selection mode changes
01789 *************************************************************************/
01790 void MultiColumnList::onSelectionModeChanged(WindowEventArgs& e)
01791 {
01792         fireEvent(EventSelectionModeChanged, e, EventNamespace);
01793 }
01794 
01795 
01796 /*************************************************************************
01797         Handler called when the nominated selection column changes
01798 *************************************************************************/
01799 void MultiColumnList::onNominatedSelectColumnChanged(WindowEventArgs& e)
01800 {
01801         fireEvent(EventNominatedSelectColumnChanged, e, EventNamespace);
01802 }
01803 
01804 
01805 /*************************************************************************
01806         Handler called when nominated selection row changes
01807 *************************************************************************/
01808 void MultiColumnList::onNominatedSelectRowChanged(WindowEventArgs& e)
01809 {
01810         fireEvent(EventNominatedSelectRowChanged, e, EventNamespace);
01811 }
01812 
01813 
01814 /*************************************************************************
01815         Handler called when vertcial scroll bar 'force' mode changes
01816 *************************************************************************/
01817 void MultiColumnList::onVertScrollbarModeChanged(WindowEventArgs& e)
01818 {
01819         fireEvent(EventVertScrollbarModeChanged, e, EventNamespace);
01820 }
01821 
01822 
01823 /*************************************************************************
01824         Handler called when horizontal scroll bar 'force' mode changes
01825 *************************************************************************/
01826 void MultiColumnList::onHorzScrollbarModeChanged(WindowEventArgs& e)
01827 {
01828         fireEvent(EventHorzScrollbarModeChanged, e, EventNamespace);
01829 }
01830 
01831 
01832 /*************************************************************************
01833         Handler called when the current selection in the list changes.
01834 *************************************************************************/
01835 void MultiColumnList::onSelectionChanged(WindowEventArgs& e)
01836 {
01837         requestRedraw();
01838         fireEvent(EventSelectionChanged, e, EventNamespace);
01839 }
01840 
01841 
01842 /*************************************************************************
01843         Handler called when list contents changes
01844 *************************************************************************/
01845 void MultiColumnList::onListContentsChanged(WindowEventArgs& e)
01846 {
01847         configureScrollbars();
01848         requestRedraw();
01849         fireEvent(EventListContentsChanged, e, EventNamespace);
01850 }
01851 
01852 
01853 /*************************************************************************
01854         Handler called when the sort column changes
01855 *************************************************************************/
01856 void MultiColumnList::onSortColumnChanged(WindowEventArgs& e)
01857 {
01858         requestRedraw();
01859         fireEvent(EventSortColumnChanged, e, EventNamespace);
01860 }
01861 
01862 
01863 /*************************************************************************
01864         Handler called when the sort direction changes
01865 *************************************************************************/
01866 void MultiColumnList::onSortDirectionChanged(WindowEventArgs& e)
01867 {
01868         requestRedraw();
01869         fireEvent(EventSortDirectionChanged, e, EventNamespace);
01870 }
01871 
01872 
01873 /*************************************************************************
01874         Handler called when a column is sized
01875 *************************************************************************/
01876 void MultiColumnList::onListColumnSized(WindowEventArgs& e)
01877 {
01878         configureScrollbars();
01879         requestRedraw();
01880         fireEvent(EventListColumnSized, e, EventNamespace);
01881 }
01882 
01883 
01884 /*************************************************************************
01885         Handler called when a column is moved
01886 *************************************************************************/
01887 void MultiColumnList::onListColumnMoved(WindowEventArgs& e)
01888 {
01889         requestRedraw();
01890         fireEvent(EventListColumnMoved, e, EventNamespace);
01891 }
01892 
01893 
01894 /*************************************************************************
01895         Handler for when we are sized
01896 *************************************************************************/
01897 void MultiColumnList::onSized(WindowEventArgs& e)
01898 {
01899         // base class handling
01900         Window::onSized(e);
01901 
01902         configureScrollbars();
01903         layoutComponentWidgets();
01904 
01905         e.handled = true;
01906 }
01907 
01908 
01909 /*************************************************************************
01910         Handler for when mouse button is pressed
01911 *************************************************************************/
01912 void MultiColumnList::onMouseButtonDown(MouseEventArgs& e)
01913 {
01914         // base class processing
01915         Window::onMouseButtonDown(e);
01916 
01917         if (e.button == LeftButton)
01918         {
01919                 bool modified = false;
01920 
01921                 // clear old selections if no control key is pressed or if multi-select is off
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                         // select range or item, depending upon keys and last selected item
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                         // update last selected item
01951                         d_lastSelected = item->isSelected() ? item : NULL;
01952                 }
01953 
01954                 // fire event if needed
01955                 if (modified)
01956                 {
01957                         WindowEventArgs args(this);
01958                         onSelectionChanged(args);
01959                 }
01960                 
01961                 e.handled = true;
01962         }
01963 
01964 }
01965 
01966 
01967 /*************************************************************************
01968         Handler for mouse wheel changes
01969 *************************************************************************/
01970 void MultiColumnList::onMouseWheel(MouseEventArgs& e)
01971 {
01972         // base class processing.
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         Event handler for header offset changes (scrolling)
01990 *************************************************************************/
01991 bool MultiColumnList::handleHeaderScroll(const EventArgs& e)
01992 {
01993         // grab the header scroll value, convert to pixels, and set the scroll bar to match.
01994         d_horzScrollbar->setScrollPosition(d_header->relativeToAbsoluteX(d_header->getSegmentOffset()));
01995 
01996         return true;
01997 }
01998 
01999 
02000 /*************************************************************************
02001         Event handler for drag & drop of header segments
02002 *************************************************************************/
02003 bool MultiColumnList::handleHeaderSegMove(const EventArgs& e)
02004 {
02005         moveColumn_impl(((HeaderSequenceEventArgs&)e).d_oldIdx, ((HeaderSequenceEventArgs&)e).d_newIdx);
02006 
02007         // signal change to our clients
02008         WindowEventArgs args(this);
02009         onListColumnMoved(args);
02010 
02011         return true;
02012 }
02013 
02014 
02015 
02016 /*************************************************************************
02017         Event handler for when header segment size (column width) changes
02018 *************************************************************************/
02019 bool MultiColumnList::handleColumnSizeChange(const EventArgs& e)
02020 {
02021         configureScrollbars();
02022 
02023         // signal change to our clients
02024         WindowEventArgs args(this);
02025         onListColumnSized(args);
02026 
02027         return true;
02028 }
02029 
02030 
02031 /*************************************************************************
02032         Event handler for when horizontal scroll bar is moved.
02033 *************************************************************************/
02034 bool MultiColumnList::handleHorzScrollbar(const EventArgs& e)
02035 {
02036         // set header offset to match scroll position
02037         d_header->setSegmentOffset(d_header->absoluteToRelativeX(d_horzScrollbar->getScrollPosition()));
02038 
02039         return true;
02040 }
02041 
02042 
02043 /*************************************************************************
02044         Handler for when sort column in header is changed
02045 *************************************************************************/
02046 bool MultiColumnList::handleSortColumnChange(const EventArgs& e)
02047 {
02048         uint col = getSortColumn();
02049 
02050         // set new sort column on all rows
02051         for (uint i = 0; i < getRowCount(); ++i)
02052         {
02053                 d_grid[i].d_sortColumn = col;
02054         }
02055 
02056         // re-sort list according to direction
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         // else, no direction, so do not sort.
02069 
02070         // signal change to our clients
02071         WindowEventArgs args(this);
02072         onSortColumnChanged(args);
02073 
02074         return true;
02075 }
02076 
02077 
02078 /*************************************************************************
02079         Handler for when sort direction in header is changed
02080 *************************************************************************/
02081 bool MultiColumnList::handleSortDirectionChange(const EventArgs& e)
02082 {
02083         // re-sort list according to direction
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         // else, no direction, so do not sort.
02096 
02097         // signal change to our clients
02098         WindowEventArgs args(this);
02099         onSortDirectionChanged(args);
02100 
02101         return true;
02102 }
02103 
02104 
02105 /*************************************************************************
02106         Handler for when user double-clicks on header segment splitter
02107 *************************************************************************/
02108 bool MultiColumnList::handleHeaderSegDblClick(const EventArgs& e)
02109 {
02110         // get the column index for the segment that was double-clicked
02111         uint col = d_header->getColumnFromSegment((ListHeaderSegment&)*((WindowEventArgs&)e).window);
02112 
02113         autoSizeColumnHeader(col);
02114 
02115         return true;
02116 }
02117 
02118 
02119 /*************************************************************************
02120         Set whether user manipulation of the sort column and direction are
02121         enabled.        
02122 *************************************************************************/
02123 void MultiColumnList::setUserSortControlEnabled(bool setting)
02124 {
02125         d_header->setSortingEnabled(setting);
02126 }
02127 
02128 
02129 /*************************************************************************
02130         Set whether the user may size column segments.  
02131 *************************************************************************/
02132 void MultiColumnList::setUserColumnSizingEnabled(bool setting)
02133 {
02134         d_header->setColumnSizingEnabled(setting);
02135 }
02136 
02137 
02138 /*************************************************************************
02139         Set whether the user may modify the order of the columns.       
02140 *************************************************************************/
02141 void MultiColumnList::setUserColumnDraggingEnabled(bool setting)
02142 {
02143         d_header->setColumnDraggingEnabled(setting);
02144 }
02145 
02146 
02147 /*************************************************************************
02148         Return the ID code assigned to the requested column.
02149 *************************************************************************/
02150 uint MultiColumnList::getColumnID(uint col_idx) const
02151 {
02152         return d_header->getSegmentFromColumn(col_idx).getID();
02153 }
02154 
02155 
02156 /*************************************************************************
02157         std algorithm predicate used for sorting in descending order (static)
02158 *************************************************************************/
02159 bool MultiColumnList::pred_descend(const ListRow& a, const ListRow& b)
02160 {
02161         return a > b;
02162 }
02163 
02164 
02165 /*************************************************************************
02166         Return whether the vertical scroll bar is always shown.
02167 *************************************************************************/
02168 bool MultiColumnList::isVertScrollbarAlwaysShown(void) const
02169 {
02170         return d_forceVertScroll;
02171 }
02172 
02173 
02174 /*************************************************************************
02175         Return whether the horizontal scroll bar is always shown.
02176 *************************************************************************/
02177 bool MultiColumnList::isHorzScrollbarAlwaysShown(void) const
02178 {
02179         return d_forceHorzScroll;
02180 }
02181 
02182 
02183 /*************************************************************************
02184         Adds properties for MCL
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         Remove all items from the list.
02203 *************************************************************************/
02204 bool MultiColumnList::resetList_impl(void)
02205 {
02206         // just return false if the list is already empty (no rows == empty)
02207         if (getRowCount() == 0)
02208         {
02209                 return false;
02210         }
02211         // we have items to be removed and possible deleted
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                                 // delete item as needed.
02221                                 if ((item != NULL) && item->isAutoDeleted())
02222                                 {
02223                                         delete item;
02224                                 }
02225 
02226                         }
02227 
02228                 }
02229 
02230                 // clear all items from the grid.
02231                 d_grid.clear();
02232 
02233                 // reset other affected fields
02234                 d_nominatedSelectRow = 0;
02235                 d_lastSelected = NULL;
02236 
02237                 return true;
02238         }
02239 
02240 }
02241 
02242 
02243 /*************************************************************************
02244         Automatically determines the "best fit" size for the specified column
02245         and sets the column width to the same.
02246 *************************************************************************/
02247 void MultiColumnList::autoSizeColumnHeader(uint col_idx)
02248 {
02249         // check for invalid index
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                 // get the width of the widest item in the column.
02257                 float width = ceguimax(getWidestColumnItemWidth(col_idx), ListHeader::MinimumSegmentPixelWidth);
02258 
02259                 // perform metrics conversion if needed
02260                 if (getMetricsMode() == Relative)
02261                 {
02262                         width = absoluteToRelativeX(width);
02263                 }
02264 
02265                 // set new column width
02266                 setColumnHeaderWidth(col_idx, width);
02267         }
02268 
02269 }
02270 
02271 
02273 /*************************************************************************
02274         Operators for ListRow
02275 *************************************************************************/
02277 /*************************************************************************
02278         Less-than operator
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         // handle cases with empty slots
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         Greater-than operator
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         // handle cases with empty slots
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         Operators for MCLGridRef
02330 *************************************************************************/
02332 /*************************************************************************
02333         Assignment operator
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         return true if this is less than (appears before) 'rhs' in grid.
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         return true if this is less than or equal to 'rhs'
02362 *************************************************************************/
02363 bool MCLGridRef::operator<=(const MCLGridRef& rhs) const
02364 {
02365         return !operator>(rhs);
02366 }
02367 
02368 
02369 /*************************************************************************
02370         return true if this is greater than (appears after) 'rhs' in grid.
02371 *************************************************************************/
02372 bool MCLGridRef::operator>(const MCLGridRef& rhs) const
02373 {
02374         return (operator<(rhs) || operator==(rhs)) ? false : true;
02375 }
02376 
02377 
02378 /*************************************************************************
02379         return true if this is greater than or equal to 'rhs'
02380 *************************************************************************/
02381 bool MCLGridRef::operator>=(const MCLGridRef& rhs) const
02382 {
02383         return !operator<(rhs);
02384 }
02385 
02386 
02387 /*************************************************************************
02388         return true if this grid ref is equal to that in 'rhs'
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         return true if this grid ref is different to that in 'rhs'
02398 *************************************************************************/
02399 bool MCLGridRef::operator!=(const MCLGridRef& rhs) const
02400 {
02401         return !operator==(rhs);
02402 }
02403 
02404 } // End of  CEGUI namespace section

Generated on Wed Feb 16 12:41:06 2005 for Crazy Eddies GUI System by  doxygen 1.3.9.1