Jump to content




Wordwrap as you type

api lua utility

8 replies to this topic

#1 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 18 May 2015 - 11:30 AM

Hey guys,

just wondering if any of you wonderful fellow have got any solutions to a wordwrap API as you type. I already have a word wrap function, but it it only wraps static content, I need something that will wrap as I type, so I give it a x, y, height and width, and then it will stay between that section and allow me to type and it shall auto line, and if I get to the bottom of the box I give it, it will move a line up and hide the line. So for example:

I have a box that is 1, 10 across and only goes two lines down (so two lines to type on), I want to be able to type like so:

Hello worl <- at this point it needs to auto line me down, and do this:

Hello
World

Now if I try and add to that like so:
Hello
all you gu <- here it needs to move a line up and append the current word to the next line so it looks like this:

all you
guys

As hello is not in the text box, I wish to do something like that? Any ideas if it has already been done because i really do not wish to try this xD I won't get far.

For you guys who know HTML & CSS I wish to do a normal text box and use an overflow-y: height, so yeah, any ideas? :D/>...?

EDIT:
Even have a scroll function to scroll through the text? That would be super awesome! :D

Edited by DannySMc, 18 May 2015 - 11:32 AM.


#2 InDieTasten

  • Members
  • 357 posts
  • LocationGermany

Posted 18 May 2015 - 02:30 PM

I would just go for the conventional approach, and check for every new character added(I don't know wether you are wanting to allow changes/deletions), if it fits into the current line. If not, take all the characters in front of it until you hit a space and wrap it at that point to the new line.
Whenever a new line doesn't fit into the current box, you would scroll up your text.
Clamping the text so that it wraps to the correct X coordinate and also hides lines out of the boundary should be fairly easy to implement also ;)

I hope that is to some extent the answer you are looking for. If you are requesting a fully-featured textbox as exmple code, I cannot help you with that. I'm sure though, that there are already plenty of textboxes out in the wild working similar to what you described.

#3 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited States of America

Posted 18 May 2015 - 02:38 PM

I don't have a text box, but I can provide a simple pattern to match the last word on a line.

str:match( "%S+$" )

This matches for non-space characters (%S) from the right side of the string ($).

I'd store separate lines in a table, easily allowing for scrolling / cursor moving within your text box.

#4 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 18 May 2015 - 03:27 PM

I actually wrote one few days ago for the Bedrock framework for my own SocialClient (a GUI for Danny's SocialNet). I will try to explain how it works when I get home. But one note: the wrapped lines should only be an 'illusion', the textbox on the code side should see the lines as one line.

BTW, I posted a tweet about the textbox on the SocialNet through my client which (the tweet) I wrote in that textbox :lol:

#5 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 18 May 2015 - 03:40 PM

Thanks guys, Errr it needs to be able to like:

+ backspace, space, enter etc, and it needs to just be like a text box in html, but it will have an overflow so when you say you go over the max height then it will not show the first few lines and only show the last lines that fit in the box, and it auto lines when you press enter and then yeah idk, like OEED's ink can do? But it is buggy as hell so maybe a better version?

:P.

I don't want it to be awkward to use or have new characters I want it to be lua just it displays each line as a table entry..
{
    "line1",
    "line2",
}

and each line is wrapped so it will fit inside the width length.

#6 TheOddByte

    Lazy Coder

  • Members
  • 1,607 posts
  • LocationSweden

Posted 18 May 2015 - 04:13 PM

If you'd like you could check this out https://github.com/T...lasses/Text.lua

#7 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 18 May 2015 - 04:32 PM

View PostTheOddByte, on 18 May 2015 - 04:13 PM, said:

If you'd like you could check this out https://github.com/T...lasses/Text.lua

I already have a word wrapper,
Spoiler

I need one as I type... which works so it auto lines as I type and text stays between a set width and height, like a text box in html...

#8 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 18 May 2015 - 06:24 PM

So here I'm going to explain how my multiline textbox works with a text wrapping feature.

First off, don't think about wrapping text yet. Actually the wrapping of text is only needed when displaying the text, most of textbox's functions are independent of the text wrapping! To store the text we store each separate line as a separate index in a table. For example:

local Text = {
  "line 1",
  "this is line 2"
}

Note: each line is not an actual line of already wrapped text. Each line is more like a paragraph - at the end of each line (paragraph) there's a newline (\n) character. The text would look like this:

line 1
this is line 2

Now we'll need two variables to mark where our cursor is. One marks the line on which the cursor is (CursorY) and the other marks the character on which the cursor is (CursorX). So if the cursor is on the second line and just after the word 'line' (imagine that '_' is the cursor):

line 1
this is line_2

then our cursor's position would be: CursorY = 2; CursorX = 13. I'm counting this starting from the number 1, so the top-left corner would be: CursorY = 1; CursorX = 1.

Now when drawing the text, then we need to wrap it. Imagine the textbox's width is 8. So this is what it would look like when drawn:

+--------+
|line 1  |
|this is |
|line 2  |
+--------+

I made a function which returned two tables:

local SeparateLines, AllLines = GetWrappedText()

SeparateLines = {
  {
    "line 1"
  },
  {
    "this is ",
    "line 2"
  }
}

AllLines = {
  "line 1",
  "this is ",
  "line 2"
}

So the first, SeparateLines, table holds all the lines as they were in the original Text table, but returns each line wrapped. We can see that the first line's table holds only one string - that means the text wasn't wrapped because there was no need for it. In the second's line table we can see that there are two strings - that means that the second line's text was wrapped into two lines.

The second, AllLines, table just holds all the lines that we will display in order.

Now as for where to put the cursor on the display and how to react to keys like [enter] or [backspace] I'm not going to get into that. It's simply math, I'm not even sure how my textbox reacts to keys exactly :lol:

I suggest for the logic just take out a piece of paper, a pen and then just draw or write everything you need. Even though I wrote my textbox in only about a day it still was a challenge, especially when the cursor goes out of the textbox and then you type something in, the letters don't appear, but the cursor comes back onto the screen, and you try to write again, but then the character is written on the wrong spot, etc... You'll just have to write and test, write and test. Then sleep, eat, come back to the code and realize what you were doing wrong.

This is how my sheets of paper look after making my textbox:

Posted Image

It's a mess, isn't it :P. And here's the source code of my textbox (it's made to work with Bedrock). It uses my own text wrapping function which only wraps but doesn't truncate the string. That why there's a space in my example above in the string "this is ".

Spoiler

Edited by MKlegoman357, 18 May 2015 - 06:28 PM.


#9 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 18 May 2015 - 09:04 PM

View PostMKlegoman357, on 18 May 2015 - 06:24 PM, said:

So here I'm going to explain how my multiline textbox works with a text wrapping feature.

First off, don't think about wrapping text yet. Actually the wrapping of text is only needed when displaying the text, most of textbox's functions are independent of the text wrapping! To store the text we store each separate line as a separate index in a table. For example:

local Text = {
  "line 1",
  "this is line 2"
}

Note: each line is not an actual line of already wrapped text. Each line is more like a paragraph - at the end of each line (paragraph) there's a newline (\n) character. The text would look like this:

line 1
this is line 2

Now we'll need two variables to mark where our cursor is. One marks the line on which the cursor is (CursorY) and the other marks the character on which the cursor is (CursorX). So if the cursor is on the second line and just after the word 'line' (imagine that '_' is the cursor):

line 1
this is line_2

then our cursor's position would be: CursorY = 2; CursorX = 13. I'm counting this starting from the number 1, so the top-left corner would be: CursorY = 1; CursorX = 1.

Now when drawing the text, then we need to wrap it. Imagine the textbox's width is 8. So this is what it would look like when drawn:

+--------+
|line 1  |
|this is |
|line 2  |
+--------+

I made a function which returned two tables:

local SeparateLines, AllLines = GetWrappedText()

SeparateLines = {
  {
	"line 1"
  },
  {
	"this is ",
	"line 2"
  }
}

AllLines = {
  "line 1",
  "this is ",
  "line 2"
}

So the first, SeparateLines, table holds all the lines as they were in the original Text table, but returns each line wrapped. We can see that the first line's table holds only one string - that means the text wasn't wrapped because there was no need for it. In the second's line table we can see that there are two strings - that means that the second line's text was wrapped into two lines.

The second, AllLines, table just holds all the lines that we will display in order.

Now as for where to put the cursor on the display and how to react to keys like [enter] or [backspace] I'm not going to get into that. It's simply math, I'm not even sure how my textbox reacts to keys exactly :lol:

I suggest for the logic just take out a piece of paper, a pen and then just draw or write everything you need. Even though I wrote my textbox in only about a day it still was a challenge, especially when the cursor goes out of the textbox and then you type something in, the letters don't appear, but the cursor comes back onto the screen, and you try to write again, but then the character is written on the wrong spot, etc... You'll just have to write and test, write and test. Then sleep, eat, come back to the code and realize what you were doing wrong.

This is how my sheets of paper look after making my textbox:

Posted Image

It's a mess, isn't it :P. And here's the source code of my textbox (it's made to work with Bedrock). It uses my own text wrapping function which only wraps but doesn't truncate the string. That why there's a space in my example above in the string "this is ".

Spoiler

Well thank you for the explanation, I do not use bedrock, but I will look for something similar online:)





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users