MultiColumnList

From CEGUI Wiki - Crazy Eddie's GUI System (Open Source)
Revision as of 10:39, 27 September 2005 by Van (Talk | contribs) (How to implement the MultiColumnList widget.)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Since I have been harping about documentation in the forums, I thought it best that I put my money where my mouth is. I am not an expert but I would like to share what I have learned and gleaned about the MultiColumnList widget.

If you are familiar with the Listbox widget then the MultiColumnList will be a natural progression for you. The one thing you need to remember is that every column entry in the MultiColumnList will have its own instance of a ListboxItem or ListboxTextItem. The MultiColumnList has some very nice features built directly into the widged. By default your users can: a) re-arrange the column display order; b)sort (Ascending and Descending) rows by a column; c) change the width of a column. These features can be disabled.

API References: MultiColumnList ListboxItem ListboxTextItem WindowManager


Take a look at this code: Please note that the following source code was gleaned and edited from project specific code so there may be some syntax errors.

// Get the CEGUI Window Manager
CEGUI::WindowManager *mWinMgr = CEGUI::WindowManager::getSingletonPtr();

// Create the CEGUI MultiColumnList window
CEGUI::MultiColumnList *mListBox = (CEGUI::MultiColumnList *)mWinMgr->createWindow(
(CEGUI::utf8*)CEGUILOOK"/MultiColumnList", (CEGUI::utf8*)"MyListBox");
// Don't forget to add this window to another window and set its other properties
// like position, size, etc. Use the methods you prefer.
mListBox->setPosition( CEGUI::Point(0.05f, 0.1f) );
mListBox->setSize( CEGUI::Size(0.90f, 0.80f) );
// mSomeWindow->addChild(mListBox);

// Set the users selection ability
mListBox->setSelectionMode(CEGUI::MultiColumnList::SelectionMode::RowMultiple);

// Add some column headers
mListBox->addColumn("Column1", 0, 0.10f);
mListBox->addColumn("Column2", 1, 0.25f);
mListBox->addColumn("Column3", 2, 0.25f);
mListBox->addColumn("Column4", 3, 0.45f);
// I don't know why, but you have set the column header widths via this function.
// The Column Header widths are not assumed from the "addColumn" function. Bug?
mListBox->setColumnHeaderWidth(0, 0.10f);
mListBox->setColumnHeaderWidth(1, 0.25f);
mListBox->setColumnHeaderWidth(2, 0.25f);
mListBox->setColumnHeaderWidth(3, 0.45f);


Note these lines in the code:

// I don't know why, but you have set the column headerwidths via this function.
// The Column Header widths are not assumed from the "addColumn" function.
mListBox->setColumnHeaderWidth(0, 0.10f);
mListBox->setColumnHeaderWidth(1, 0.25f);
mListBox->setColumnHeaderWidth(2, 0.10f);
mListBox->setColumnHeaderWidth(3, 0.25f);

If you don't set the column header widths with the setColumnHeaderWidth method then the columns will appear to be stacked on top of one another. This may be a bug in the library. The numbers I used for the widths are arbitrary. You can make them anything you like.


Now, lets create a method to add data to our MultiColumnList. Review this code:

void addListboxItem(char *c1, char *c2, char *c3, char *c4, bool isSelected)
{
  // First, we need to add a new row to the Listbox
  unsigned int mRow = mListBox->addRow();

  // Remember, each column is a 'ListboxTextitem' so we need to
  // create a new instance for each column.

  // Column1
  // Create our ListboxTextItem instance...
  CEGUI::ListboxTextItem* item = new CEGUI::ListboxTextItem((CEGUI::utf8*)c1, 0);
  // Note that in 'setItem' we specify '0' for the index/column we want this
  // ListboxTextItem to be attached too.
  mListBox->setItem(item, 0, mRow);
  // Should it be selected? I know this appears weird but yes you can have columns be
  // selected or not selected. In other words, its not ROW based, its COLUMN based 
  // selection. Why? more options and flexibilty!
  item->setSelected(isSelected);
  // Don't forget to set the selection brush or your item won't get highlighted.
  item->setSelectionBrushImage( (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)GEGUI_SelectionBrushImage);
  // You could attach some data to this column that is important to you by
  // using the 'setUserData' function. Each column could point to a different
  // user data source or the same user data source, or nothing at all.
  // item->setUserData(MyPointerToSomeData);

  // Column2
  item = new CEGUI::ListboxTextItem((CEGUI::utf8*)c2, 0);
  mListBox->setItem(item, 1, mRow);
  item->setSelected(isSelected);
  item->setSelectionBrushImage( (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)GEGUI_SelectionBrushImage);

  // Column3
  item = new CEGUI::ListboxTextItem((CEGUI::utf8*)c3, 0);
  mListBox->setItem(item, 2, mRow);
  item->setSelected(isSelected);
  item->setSelectionBrushImage( (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)GEGUI_SelectionBrushImage);

  //Column4
  item = new CEGUI::ListboxTextItem((CEGUI::utf8*)c4, 0);
  mListBox->setItem(item, 3, mRow);
  item->setSelected(isSelected);
  item->setSelectionBrushImage( (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)GEGUI_SelectionBrushImage);

} // addListboxItem


Now, somewhere in your code, call the addListboxItem function like this:

  ...
  addListboxItem("Item1 Col1", "Item1 Col2", "Item1 Col3", "Item1 Col4", true);
  addListboxItem("Item2 Col1", "Item2 Col2", "Item2 Col3", "Item2 Col4", false);
  addListboxItem("Item3 Col1", "Item3 Col2", "Item3 Col3", "Item3 Col4", false);
  addListboxItem("Item4 Col1", "Item4 Col2", "Item4 Col3", "Item4 Col4", true);
  ...

You will note that in the above source code I have specified two rows to be highlighted. This is possible because of the

mListBox->setSelectionMode(CEGUI::MultiColumnList::SelectionMode::RowMultiple);

statement from above. Review the API documentation about the setSelectionMode. You can make it single row based or column based.

Another thing to note that after the window is created the columns may appear funny - that is, the columns and the data won't appear aligned. There appears to be an initial 'redraw' bug in the library. If you manually resize a column (yes, with the mouse like in windows) it will correct the column layout, spacing and alignment. Program this and give it a try. When you run your program don't forget to re-arrange the column order (drag and drop the column header), resize columns and double click a column header to sort the rows via the clicked column.