Word-wrapping in ListBoxes [SOLVED]

Started by Rui 'Trovatore' Pires, Tue 06/11/2007 09:10:33

Previous topic - Next topic

Rui 'Trovatore' Pires

Quick question:

For several reasons, in my IF template, I've substituted labels for list boxes. Which meant I'd have to find out a way to word-wrap (and to properly display "[" as paragraphs, but that's done, no prob). I did, but I'm not really happy with it.

Basically, when writing to the listbox, I use the following check:

desc.Length*LETTERWIDTH>lstRoomDesc.Width

"desc" is the string passed to the function this is on, i.e., it's the full string. It gets truncated as each line is added to the listbox.

LETTERWIDTH is #defined as 4. It's a guess-timate for the width of the average character in the font I'm using (default font).

lstRoomDesc.Width, as it suggests, is the width of the listbox.

Having a resizeable listbox doesn't make it any easier on myself... anyway.

The character 'i' is one pixel wide. The character 'L' is more than that. I have no idea how many pixels are in ' '. So most often, the line either wraps before reaching the end of the listbox (quite a bit before it does, in fact), or continues a bit past the end of the listbox. Fine-tuning is impossible - the difference between 3 and 4 is quite big, and I'm pretty sure I can't use a float... can I?

Basically, is there a better way to do this? I'm guessing not, but asking never hurt...
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

Khris

Have you tried using
GetTextWidth(desc.Length, lstRoomDesc.Font) > lstRoomDesc.Width
instead?

Rui 'Trovatore' Pires

#2
...wow. What a great function! Had no idea it was there! Thanks a big bunch!

EDIT - Same for the FONT property. AGS is advancing way too fast for me to keep track.

EDIT 2 - Whoops, not solved after all. Err, I need a little more help, I forgot I had a second line which needs changing.

int lastletter=lstRoomDesc.Width/LETTERWIDTH;

This declares lastletter, which was, hopefully, the last character in the bit of string that fit in the ListBox.

Or something. Tell you the truth, the meaning of whatever code I'm writing eludes me 5 minutes after I find out it works. And I just can't get my brain around what I should change this line to...

BTW, probably not necessary, but here's the whole loop as is:

Code: ags
  while (desc.Length*LETTERWIDTH>lstRoomDesc.Width) { //while (GetTextWidth(desc.Length, lstRoomDesc.Font) > lstRoomDesc.Width) {
    int lastletter=lstRoomDesc.Width/LETTERWIDTH;
    while (desc.Chars[lastletter]!=' ') lastletter--;
    lstRoomDesc.AddItem(desc.Substring(0, lastletter));
    if (lstRoomDesc.Items[lstRoomDesc.ItemCount-1].Contains("[")!=-1) {
      int temp=lstRoomDesc.Items[lstRoomDesc.ItemCount-1].Contains("[")+1;
      lstRoomDesc.Items[lstRoomDesc.ItemCount-1]=lstRoomDesc.Items[lstRoomDesc.ItemCount-1].Substring(0,temp-1);
      desc=desc.Substring(temp, desc.Length-1);
    }
    else desc=desc.Substring(lastletter, desc.Length-1);
  }
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

monkey0506

Untested but this might work.

Code: ags
  int i = 0;
  String buffer = "";
  while (i < desc.Length) {
    if (GetTextWidth(buffer.AppendChar(desc.Chars[i]), lstRoomDesc.Font) <= lstRoomDesc.Width) buffer = buffer.AppendChar(desc.Chars[i]);
    else {
      while ((buffer.Contains(" ") != -1) && (buffer.Chars[buffer.Length - 1] != ' ')) {
        buffer = buffer.Truncate(buffer.Length - 1); // since there's no reverse-contains, take off one character at a time
        i--;
        }
      lstRoomDesc.AddItem(buffer);
      i--;
      buffer = "";
      if (lstRoomDesc.Items[lstRoomDesc.ItemCount - 1].Contains("[") != -1) {
        int temp = lstRoomDesc.Items[lstRoomDesc.ItemCount - 1].Contains("[");
        buffer = lstRoomDesc.Items[lstRoomDesc.ItemCount - 1].Substring(temp + 1, lstRoomDesc.Items[lstRoomDesc.ItemCount - 1].Length);
        lstRoomDesc.Items[lstRoomDesc.ItemCount - 1] = lstRoomDesc.Items[lstRoomDesc.ItemCount - 1].Substring(0, temp);
        }
      }
    i++;
    }
  lstRoomDesc.AddItem(buffer);
  if (buffer.Contains("[") != -1) {
    int temp = buffer.Contains("[");
    lstRoomDesc.Items[lstRoomDesc.ItemCount - 1] = buffer.Truncate(temp);
    lstRoomDesc.AddItem(buffer.Substring(temp + 1, buffer.Length));
    }

Rui 'Trovatore' Pires

#4
I have no idea what all that code does, Monkey, and therefore hope I never have to edit it. But it works wonders, wonders, wonders, thanks so muchly!

EDIT - Ok, think I've got it working now. BTW, monkey, I did have to change a little bit of your code.

At the end:

if (buffer.Contains("[") != -1) {
    int temp = buffer.Contains("[");
    lstRoomDesc.Items[lstRoomDesc.ItemCount - 1] = buffer.Truncate(temp);
    lstRoomDesc.AddItem(buffer.Substring(temp + 1, buffer.Length));
    }

...so if contained *2* line breaks in a line that fits within the listbox, the last line breaks would actually show up. But a little change to care of that, I did:

  while (buffer.Contains("[") != -1) {
    int temp = buffer.Contains("[");
    lstRoomDesc.Items[lstRoomDesc.ItemCount - 1] = buffer.Truncate(temp);
    lstRoomDesc.AddItem(buffer.Substring(temp + 1, buffer.Length));
    buffer=buffer.Substring(temp + 1, buffer.Length);
    }

And I was overreacting before, I did understand what you did... eventually. I'd never have thought of doing it character by character, and then going back to erase what was left over. So - thanks again, to both of you. It seems to be solved.
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

monkey0506

Sometimes it might even be faster to seed the buffer like:

Code: ags
int i = desc.Length / 2;
String buffer = desc.Substring(0, i);


Then you could do this:

Code: ags
if (GetTextWidth(buffer.AppendChar(desc.Chars[i]), lstRoomDesc.Font) <= lstRoomDesc.Width) buffer = buffer.AppendChar(desc.Chars[i]);
else while (GetTextWidth(buffer, lstRoomDesc.Font) > lstRoomDesc.Width) {
  buffer = buffer.Truncate(buffer.Length - 1);
  i--;
  }


Glad you got it sorted out though. :)

SMF spam blocked by CleanTalk