How much text fits in textbox?

I am creating a reusable textbox. I got started with the supplied typewriter.lua by Neven Mrgn to write text to a sprite. I am not now trying to determine the amount of text that fits within the gfx.drawTextInRect allowing for pageup and pagedown functionality. I am using the default font.

I need a little direction on how to accomplish this
Should I be using rect width / font char width * rows? Is font fixed width? if so how to get. it's width?
Alternatively is there a way to determine where the rect is clipping? SDK docs looks like it only tells you it is clipped (true/false). Thanks for looking.

local gfx <const> = pd.graphics

local tb = gfx.sprite.new()
tb.width = 350
tb.height = 190
tb.padding = 10
tb:setSize(tb.width, tb.height)
tb:moveTo(200, 120)
tb:setZIndex(900)
tb.text = "" -- this is blank for now; we can set it at any point
tb.currentChar = 1 -- we'll use these for the animation
tb.currentText = ""
tb.typing = true
tb.typewriter = false

function tb:update()
	if not self.typewriter then
		tb.currentText = self.text
		self:markDirty()
	else
		self.currentChar = self.currentChar + 1
		if self.currentChar > #self.text then
			self.currentChar = #self.text
		end
		
		if self.typing and self.currentChar <= #self.text then
			tb.currentText = string.sub(self.text, 1, self.currentChar)		
			self:markDirty() -- this tells the sprite that it needs to redraw
		end
		
		-- end typing
		if self.currentChar == #self.text then
			self.currentChar = 1
			self.typing = false
		end
	end
end

function tb:draw()
	
	-- pushing context means, limit all the drawing config to JUST this block
	-- that way, the colors we set etc. won't be stuck
	gfx.pushContext()
	
		-- draw the box				
		gfx.setColor(gfx.kColorWhite)
		gfx.fillRect(0,0,self.width,self.height)
		
		-- border
		gfx.setLineWidth(5)
		gfx.setColor(gfx.kColorBlack)
		gfx.drawRect(0,0,self.width,self.height)
		
		-- draw the text!
		gfx.drawTextInRect(self.currentText, self.padding, self.padding, self.width - self.padding, self.height- self.padding)
	
	gfx.popContext()
end

I will soon be facing a similar need: arbitrary text that has to scroll or page. Any recommendations are welcome! As far as I can tell, you can't just get text to auto-wrap as needed within a given width. If I have that right, manual line breaks with \n newline chars will be needed.

Then graphics.getTextSize() can be used to find the width (which you already pretty much know if you manually inserted line breaks) and the height of the entire text block.

You could then take that height and divide it up as needed into "pages," always in multiples of the line height so it cuts cleanly. You'd render the whole text, but reveal only one "page" out of it at a time, in whatever way works with your UI. (I intend to have the entire text block sit behind the rest of my UI, and simply scroll it up and down—probably one line at a time with a little animation—showing through that "window.")

Going further, I might experiment with automatic line breaks: converting spaces to newlines whenever a line goes over a certain width limit.

One approach to that: parse the long text string into a table of words, delimited by the spaces (and maybe other chars). Then rebuild the string word by word from the table. I intend to use graphics.font.getTextWidth() to check each line of text (words after the previous newline) and as soon as the width goes over, don't add the last word. Add a newline before that word instead, and proceed with that word starting the next line. And so forth.

Or maybe this can all be done without inventing the wheel and I just don't know it yet :thinking:

The typewriter example does thankfully word wrap already.
Screen Shot 2022-04-29 at 8.01.04 PM

1 Like

Oh nice! I'll download that to look at how that works.

I had the same issue/requirement (?) a couple of weeks back, I rolled up a solution by first picking an arbitrary width for my text box and then passing my text and that fixed width to playdate.graphics.getTextSizeForMaxWidth.

Tweaked with a bit of fudge and it works a treat.

1 Like

I think that's all I need too. I'm making a "document" system able to flow text around arbitrary graphics, at least in a primitive way. My built-in help is going to be thorough!

Take a look at this, optimised source included

1 Like