Word-Wrap ListboxItem

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

Erebus
Just popping in
Just popping in
Posts: 6
Joined: Wed Feb 13, 2008 08:58
Location: United States
Contact:

Word-Wrap ListboxItem

Postby Erebus » Sat Feb 23, 2008 04:08

I know, I know....

The idea is to make a derived ListboxTextItem Class that does the wrapping, and add that to the Listbox. My question is: how do you accomplish wrapping even within the derived class?

What I've been thinking about, is maybe getlistrenderarea of the listbox, and if so, split the string with a \n at the closes word location to that rect... but how are you supposed to figure that out? Also, I tried a simple attempt of making a string in a listboxtextitem contain a couple \n's, which don't show up in the listbox.... I've read all over the forums about how to make a subclassed version (your own listitem widget), but no ideas about how to make it wrap. if I were to divide the text into 2 listboxitem entries, how would I make that functional in the derived class?

Any ideas are greatly appreciated...

Erebus

Erebus
Just popping in
Just popping in
Posts: 6
Joined: Wed Feb 13, 2008 08:58
Location: United States
Contact:

Postby Erebus » Tue Feb 26, 2008 17:20

Nothing?

Rackle
CEGUI Team (Retired)
Posts: 534
Joined: Mon Jan 16, 2006 11:59
Location: Montréal

Postby Rackle » Tue Feb 26, 2008 19:22

I do not know.

Pompei2
Home away from home
Home away from home
Posts: 489
Joined: Tue May 23, 2006 16:31

Postby Pompei2 » Tue Feb 26, 2008 21:34

maybe there is a way to create a listbox that uses "StaticText" kind of items, these implement word-warp on themselve. This should not be too difficult, there are several "custon" listbox element samples out here, like checkboxes as listbox elements, just use StaticText instead.

Erebus
Just popping in
Just popping in
Posts: 6
Joined: Wed Feb 13, 2008 08:58
Location: United States
Contact:

Postby Erebus » Thu Feb 28, 2008 19:13

Alright, this very likely is the worst possible method and implementation of word-wrapping I have ever made or seen, but since I can't seem to find any other method (using code, Pompei2's idea was a great one, but does quite a bit on the outside of code, in the xml files). Anyway, I made a class to handle word-wrapping with a CEGUI::Listbox, the concept is extremely inefficient, but it works. If someone finds a way to tweak it, or use the idea to make a better version, please let me know. At present, the code gets the list render area of the listbox, and basically makes an instance of ListboxTextItem, appending each character of the message and checking if it is still in range. Nasty hack, but it seems to work.

It handles wrapping by word, (if spaces exist) and if not, splits by the text at the character position. It also takes into account the vertical scroll bar, but be warned, that if there is no vertical scrollbar, CEGUI will throw an UnknownObjectException, so, it's a good idea to keep the scrollbar always visible, or remove that portion of the following code.

The main method strToItemList, returns a vector of CEGUI::ListboxTextItem pointers, basically the code sees if there needs to be a split of the message (if not, it returns a vector with 1 item in it... the entire message). If so, it splits the message into the needed number of listboxtextitems... so a line that just needs one split (that is, just a little too long) will return 2 items in the vector (2 listboxtextitems). One thing I plan to do with this in my own code, is to create an init method, that will get the size of all the keyboard characters, so that it can just compare the already known values, saving a lot of processing time. Hopefully someone has some idea's to make it better, but for now:

lbwraptext.h

Code: Select all

/* Taken From Anepsosis */
#ifndef LBWrapText_H
#define LBWrapText_H

#include <vector>
#include <CEGUI/CEGUI.h>

using namespace std;

class LBWrapText
{
public:
   LBWrapText();
   ~LBWrapText();

   bool isInRange(CEGUI::Listbox *lb, std::string message);
   std::vector<CEGUI::ListboxTextItem*> strToItemList(CEGUI::Listbox *lb, std::string message);

private:
};
#endif


lbwraptext.cpp

Code: Select all

/* Taken From Anepsosis */
#include <CEGUI/CEGUI.h>
#include <iostream>
#include <vector>
#include "lbwraptext.h"

using namespace std;

LBWrapText::LBWrapText()
{
}

LBWrapText::~LBWrapText()
{
}

// Method Used Just To Check If The String Is Too Long Or Not
bool LBWrapText::isInRange(CEGUI::Listbox *lb, std::string message)
{
   // Get The Size Of The Message In Pixels
   CEGUI::ListboxTextItem *chatItem = new CEGUI::ListboxTextItem(message);
   CEGUI::Size lbti = chatItem->getPixelSize();

   // Get The Widths Of The Listbox And Item In Floats
   float lblength = lb->getListRenderArea().getWidth();
   float itemlen = lbti.d_width;


   // Clean Up Our Mess, And Check If The
   // ListboxItem is Too Long
   delete chatItem;
   if (itemlen < lblength) {
      return true;
   } else {
      return false;
   }
}

std::vector<CEGUI::ListboxTextItem*> LBWrapText::strToItemList(CEGUI::Listbox *lb, std::string message)
{
   // Clear The Vector, And Get The Number Of Needed Splits
   std::vector<CEGUI::ListboxTextItem*> lstItems;
   std::vector<std::string> msgparts;
   CEGUI::ListboxTextItem *chatItem;

   // CAUTION!!! This Line Might Cause An UnknownObjectException
   // You Need To Ensure That You Have Vertical ScrollBar Always
   // Visible With: setShowVertScrollbar (bool setting)
   CEGUI::Window *lbscrollbar = static_cast<CEGUI::Window*>(lb->getVertScrollbar());
   CEGUI::UDim sbwidth = lbscrollbar->getWidth();
   CEGUI::Size lbti;

   // Empty Our Vectors
   lstItems.clear();
   msgparts.clear();

   // Get Some Float Values For The Listbox / Item
   float lblength = lb->getListRenderArea().getWidth();
   float lbsbwidth = sbwidth.d_offset;
   float itemlen = 0;

   int charlen = 0;
   int ccount = 0;

   // Create Listbox Item Or Items
   if (this->isInRange(lb, message) == false) {

      // Get The Max Length Of Characters Of The Listbox
      std::string tmpbuf = "";
      for (size_t i=0; i < message.length(); i++) {
         tmpbuf += message[i];
         chatItem = new CEGUI::ListboxTextItem(tmpbuf);
         lbti = chatItem->getPixelSize();
         itemlen = lbti.d_width;

         // If We've Reached The End Of The Listbox
         // (Taking Into Account For The Scrollbar
         if (itemlen >= (lblength - lbsbwidth)) {
            size_t pos;
            pos = i;

            // If We Landed On A Space
            if (message[pos] == ' ') {
               msgparts.push_back(message.substr(0, i));
               message.erase(0, i + 1);
            } else {
               // If Not, Loop Until We Find One,
               // Or Our String Runs Out
               if (message.find(" ") != std::string::npos) {
                  while (message[pos] != ' ') {
                     if (pos >= 0) {
                        // Finally Found A Previous Space
                        if (message[pos] == ' ') {
                           msgparts.push_back(message.substr(0, pos));
                           message.erase(0, pos + 1);
                           break;
                        } else {
                           pos--;
                        }
                     } else {
                        // No Space Found Behind Us... Cut It Here
                        msgparts.push_back(message.substr(0, i));
                        message.erase(0, i + 1);
                        pos--;
                        break;
                     }
                  }
               } else {
                  // No Space In The String... Cut It By Letter
                  msgparts.push_back(message.substr(0, i));
                  message.erase(0, i);
               }
            }

            // Clean Up Used Heap
            delete chatItem;
         }
      }

      // Gather The Remaining Chunks Of Message
      msgparts.push_back(message);

      // Generate The ListboxTextItems   
      for (size_t i=0; i < msgparts.size(); i++) {
         lstItems.push_back(new CEGUI::ListboxTextItem(msgparts[i]));
      }
   } else {
      lstItems.push_back(new CEGUI::ListboxTextItem(message));
   }

   // Return The Vector
   return lstItems;
}


use case:

Code: Select all

std::vector<CEGUI::ListboxTextItem *> chatitemlist;

LBWrapText wraptext;
chatitemlist = wraptext.strToItemList(listBoxptr, "Some Very Looooooooooooong Text String, That Should Ideally Be Too Long To Fit In One Or Two Lines.  This Line Just Isn't Long Enough For Testing....");
for (size_t i=0; i < chatitemlist.size(); i++) {
   listBoxptr->addItem(chatitemlist[i]);
}


Return to “Help”

Who is online

Users browsing this forum: No registered users and 15 guests