Page 1 of 1

[solved] MultiColumnList: fast change text in all items

Posted: Thu Mar 19, 2009 13:52
by fixus971
Hi to all and thanks to Crazy Eddie for project..

I'm new in forum but I have just raised a minimum experience with CEGUI.
I'm use this GUI into SFML project of a small(for now) / nice game similar to Monopoly (started in 1990 or before with GWBasic ^_^)

Now I have some beginner problem with MultiColumnList.
I just generated it as in general examples / sample but
I don't found good/clear code for necessity after generated grid:
How can I quick change text in all items
example: I have a table with 5 players data to update at every frames because is a Debug window and data as position change continuously.

I don't think that recreating item object at every frame is so efficient, or not?

I see in http://www.cegui.org.uk/wiki/index.php/ ... ColumnList:

Code: Select all

         itemMultiColumnList = new ListboxTextItem("A2", 201);
            itemMultiColumnList->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
            multiColumnList->setItem(itemMultiColumnList, 0, 1); // ColumnID, RowID
         itemMultiColumnList = new ListboxTextItem("B2", 202);
            itemMultiColumnList->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
            multiColumnList->setItem(itemMultiColumnList, 1, 1); // ColumnID, RowID
         itemMultiColumnList = new ListboxTextItem("C2", 203);
            itemMultiColumnList->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
            multiColumnList->setItem(itemMultiColumnList, 2, 1); // ColumnID, RowID

Code: Select all

         MCLGridRef grid_ref(1, 0); // Select according to a grid reference; second row
         multiColumnList->setItemSelectState(grid_ref, true);
         ListboxItem* listboxItem = multiColumnList->getFirstSelectedItem();
         uint valueColumnA = listboxItem->getID(); // Retrieve the value of the selected item from column A
         listboxItem = multiColumnList->getNextSelected(listboxItem);
         uint valueColumnB = listboxItem->getID(); // Retrieve the value of the selected item from column B
         listboxItem = multiColumnList->getNextSelected(listboxItem);
         uint valueColumnC = listboxItem->getID(); // Retrieve the value of the selected item from column C

Second part of code can help me to point to items for change that? or what?

I need to make some as:

Code: Select all

for r = 0 to 5;
// Column Name unchanged
  mcl -> getItemAt( r, 1 ) -> setText( tostring(someVarA) );
  mcl -> getItemAt( r, 2 ) -> setText( tostring(someVarB) );
  mcl -> getItemAt( r, 3 ) -> setText( tostring(someVarC) );
//..
next;


in http://www.cegui.org.uk/phpBB2/viewtopi ... columnlist:

Code: Select all

If you want to find an item with a specified string, you can use MultiColumnList::findListItemWithText which you pass in a string and get back a pointer to the item.

If you have the item and want the grid location, you can use MultiColumnList::getItemGridReference

If these answers are no good, please specify what information you have that you can pass as input, and what you want back as output.

I find CEGUI::getItemAtGridReference


I think that

Code: Select all

findListItemWithText       in my code can slow down

getItemGridReference    reverse

ListboxItem *    getItemAtGridReference (const MCLGridRef &grid_ref) const
    Return a pointer to the ListboxItem at the specified grid reference.


GridReference stand for original creation sequence position or visual position after some user column move?

Looking at first code reported..
can I use item reference codifing as 102 for row=1 column=2
to find item after creation?


in http://www.cegui.org.uk/phpBB2/viewtopi ... columnlist

Code: Select all

you can edit multiple items before having to do a redraw which is more efficient. Its a basic transaction mechanism.

I can confirm the reason for non-automatic updates is for efficiency reasons.

BTW, the correct member to notify of changes is CEGUI::MultiColumnList::handleUpdatedItemData


Ok, I think it is the best method but first I need code to change all texts

Thanks for patience boys.

Re: MultiColumnList:: fast change text in all items method

Posted: Thu Mar 19, 2009 15:13
by Jamarr
GridReference stand for original creation sequence position or visual position after some user column move?


visual-position; aka current position. You cannot use the MCLGridRef as a handle to a specific item if your rows or columns can move. If you have disabled dragging and sorting you can cheat a little bit by using the row and column (MCLGridRef) indicies directly. Otherwise...

How can I quick change text in all items
example: I have a table with 5 players data to update at every frames because is a Debug window and data as position change continuously.


I would suggest you take advantage of the ColumnID and RowID attributes. Ex:

Code: Select all

// define column id's
enum{ COLA, COLB, COLC };


Code: Select all

// create columns
mcl->addColumn("COLA" ,COLA, CEGUI::UDim(.3f, 0));
mcl->addColumn("COLB" ,COLB, CEGUI::UDim(.3f, 0));
mcl->addColumn("COLC" ,COLC, CEGUI::UDim(.3f, 0));


Code: Select all

// create a new row
CEGUI::ListboxTextItem* cola = new CEGUI::ListboxTextItem("cola");
CEGUI::ListboxTextItem* colb = new CEGUI::ListboxTextItem("colb");
CEGUI::ListboxTextItem* colc = new CEGUI::ListboxTextItem("colc");

CEGUI::uint rx = mcl->insertRow(0, player1_id);
mcl->setItem(cola, COLA, rx);
mcl->setItem(colb, COLB, rx);
mcl->setItem(colc, COLC, rx);


Code: Select all

// update existing row
CEGUI::uint rx = mcl->getRowWithID(player1_id);
CEGUI::uint ca = mcl->getColumnWithID(COLA);
CEGUI::uint cb = mcl->getColumnWithID(COLB);
CEGUI::uint cc = mcl->getColumnWithID(COLC);

mcl->getItemAtGridReference(CEGUI::MCLGridRef(rx, ca))->setText("COLA");
mcl->getItemAtGridReference(CEGUI::MCLGridRef(rx, cb))->setText("COLB");
mcl->getItemAtGridReference(CEGUI::MCLGridRef(rx, cc))->setText("COLC");


Code: Select all

// apply changes
mcl->handleUpdatedItemData();

Posted: Thu Mar 19, 2009 18:09
by fixus971
:lol: Great.. I think that it can be run well
Now go to work at this..

1000 Thanks Jamarr :wink:

Posted: Fri Mar 20, 2009 02:18
by fixus971
Ok Jamarr.. all run well testing with 2 MCL continuously updated and moving cols on the run.

I'm post here my MCL init function for all CE boy friends.

function in GUIManager:

Code: Select all

CEGUI::Window* GUIManager::initMCL(CEGUI::Window* wmcl, int cols, int rows)
{
   CEGUI::MultiColumnList* mcl = static_cast<CEGUI::MultiColumnList*> (wmcl);
   CEGUI::ListboxTextItem* imcl;
   for(unsigned int ic=0; ic<cols; ic++)
   {
      mcl->addColumn("_" , ic, CEGUI::UDim(0.97f/cols,0));
   }
   mcl->setSelectionMode(CEGUI::MultiColumnList::RowSingle); // mcl::RowMultiple
   for(unsigned int ir=0; ir<rows; ir++)
   {
      mcl->addRow(ir); //CEGUI::uint rx = mcl->insertRow(0, ir); //mcl->setItem(cola, COLA, rx);
      for(unsigned int ic=0; ic<cols; ic++)
      {
         imcl = new CEGUI::ListboxTextItem(".", ir*100+ic);
         mcl->setItem(imcl, ic, ir); // ColumnID, RowID
      }
   }
   imcl->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
   return wmcl;
}


init in app:

Code: Select all

      CEGUI::Window* w;

      CEGUI::FrameWindow* cePlsState = mGUIManager.newWindow(ceRoot, "Players state", 1,320, 400,228);
      w = mGUIManager.newBox(cePlsState, "MultiColumnList", "aMultiColumnList", 8,36, 384,188);
      mGUIManager.initMCL(w, 6,5);


update in app:

Code: Select all

   if (winMgr.isWindowPresent("aMultiColumnList"))
    {
        CEGUI::Window* w = winMgr.getWindow("aMultiColumnList");
      CEGUI::MultiColumnList* mcl = static_cast<CEGUI::MultiColumnList*> (w);
      //CEGUI::ListboxTextItem* imcl;
      for(unsigned int ipl=0; ipl<mPlayersCC.size(); ipl++)
      {
         Player*   pl   = &mPlayersCC.at(ipl);
         int      id   = pl->getID();
         intxy   pxy   = pl->getPos();
         char   st   = pl->getStatus();
         int      cash= pl->getCash();
         int      cred= pl->getCredit();
         int      d1   = pl->getDice1();
         int      d2   = pl->getDice2();
         int      ds   = pl->getDicesSum();
         CEGUI::uint ri = mcl->getRowWithID(ipl); /// get actual row index on video
         mcl->getItemAtGridReference(CEGUI::MCLGridRef(ri, mcl->getColumnWithID(0)))->setText( tostring(ipl) );
         mcl->getItemAtGridReference(CEGUI::MCLGridRef(ri, mcl->getColumnWithID(1)))->setText( tostring(st) );
         mcl->getItemAtGridReference(CEGUI::MCLGridRef(ri, mcl->getColumnWithID(2)))->setText( tostring(pxy.x) +","+ tostring(pxy.y) );
         mcl->getItemAtGridReference(CEGUI::MCLGridRef(ri, mcl->getColumnWithID(3)))->setText( tostring(ds) );
         mcl->getItemAtGridReference(CEGUI::MCLGridRef(ri, mcl->getColumnWithID(4)))->setText( tostring(cash) );
         mcl->getItemAtGridReference(CEGUI::MCLGridRef(ri, mcl->getColumnWithID(5)))->setText( tostring(cred) );
      }
      mcl->handleUpdatedItemData();   /// apply changes
   } //if (winMgr.isWindowPresent("aMultiColumnList"))



Only one last question:
What can you suggest me to manage columns names in MCL init function?
How to pass cols names to function (variable cols number for every init call)
How to setup names after MCL init (on the run)

10'000 Thanks :wink:

Posted: Fri Mar 20, 2009 16:25
by Jamarr
fixus971 wrote:What can you suggest me to manage columns names in MCL init function? How to pass cols names to function (variable cols number for every init call)

Why not just pass a list (like std::vector) full of column names into the function? Eg:

Code: Select all

typedef std::vector<std::string> MCLColumnNames;

CEGUI::Window* GUIManager::initMCL(CEGUI::Window* wmcl, int cols, int rows, MCLColumnNames col_names)
{
   CEGUI::MultiColumnList* mcl = static_cast<CEGUI::MultiColumnList*> (wmcl);
   CEGUI::ListboxTextItem* imcl;
   for(unsigned int ic=0; ic<cols; ic++)
   {
      mcl->addColumn(col_names[ic] , ic, CEGUI::UDim(0.97f/cols,0));
   }
   mcl->setSelectionMode(CEGUI::MultiColumnList::RowSingle); // mcl::RowMultiple
   for(unsigned int ir=0; ir<rows; ir++)
   {
      mcl->addRow(ir); //CEGUI::uint rx = mcl->insertRow(0, ir); //mcl->setItem(cola, COLA, rx);
      for(unsigned int ic=0; ic<cols; ic++)
      {
         imcl = new CEGUI::ListboxTextItem(".", ir*100+ic);
         mcl->setItem(imcl, ic, ir); // ColumnID, RowID
      }
   }
   imcl->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
   return wmcl;
}


How to setup names after MCL init (on the run)


You can use the CEGUI::ListHeaderSegment object to manipulate existing column headers. Ex:

Code: Select all

int xb = mcl->getColumnWithID(COLB);
CEGUI::ListHeaderSegment& cb = mcl->getHeaderSegmentForColumn(xb);
cb.setText("COLB_");

Posted: Sat Mar 21, 2009 14:39
by fixus971
:lol: Thanks a lot for all!! :lol:

Perfect Jamarr.. you're a great friend.