Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I draw text which flows around objects at the top and bottom right?

I have a problem similar to this question but more complex. I'm trying to draw text in a table view cell which has a date label top right and a badge bottom right, like so:

+-----------------------+----+
| Lorem ipsum dolor sit |DATE|
| amet, consectetur     +----+
| adipiscing elit. Integer   |
| ligula lectus, convallis   |
| non scelerisque      +-----+
| quis, tempor at nibh |BADGE|
+----------------------+-----+

I want the cell to be larger or smaller if there is more or less text:

+-----------------------+----+
| Lorem ipsum dolor sit |DATE|
| amet, consectetur     +----+
| adipiscing elit. Integer   |
| ligula lectus, convallis   |
| non scelerisque quis,      |
| tempor at nibh.  Curabitur |
| eget diam ligula.          |
| Pellentesque a elit        |
| dolor, a ullamcorper +-----+
| risus.               |BADGE|
+----------------------+-----+

The answer to the older question links to a project which shows how to flow text around known shapes. But I don't know the shape in advance, as I need the badge to align with the bottom of the text.

Is this even possible? If so, how do I draw the text, and how do I work out how tall it will be?

like image 656
Simon Avatar asked Oct 06 '22 01:10

Simon


2 Answers

Your case is not too bad since everything is a rectangle and it appears that the width is fixed. For some starter code, see ColumnView.

Here's how I would attack it:

  • There are three rectangles: top, middle, and bottom. The top and bottom have known dimensions. Only the middle can stretch vertically.
  • Create a CTFrameSetter. Create a path for the top box and create a CTFrame to lay that out. That part is certain, so hold onto it. If all the text fit, then you're done.
  • Create a path for the middle box immediately below the top box. Make it as short as you're willing for it to be (I assume you want some space there even if the text could fit in the top and bottom boxes).
  • Create a path for the bottom box immediately below the middle frame.
  • Use CTFrameSetter to create frames for the middle and bottom frames. Ask it how much text it was able to layout. If it finished everything, you're done. This is the smallest box you're willing to draw.
  • If it overflowed, increase the size of the middle box by a line. Try laying out the middle and bottom boxes again. Repeat until it fits.
  • Now you know the size of the entire view and can lay everything out.

There are a few places to optimize in there, but it's probably faster than you think.

like image 173
Rob Napier Avatar answered Oct 10 '22 04:10

Rob Napier


I struggled with this for a long time trying to get a popup box to size itself based on the text I sent to it. Usually the width is fixed and you are only trying to calculate the height. There is an article in the developer docs here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html

There is also a good set of reusable categories I found here: http://sheepsystems.com/sourceCode/sourceStringGeometrics.html

Even being able to resize the cells properly, changing the shape of the text box and overlaying the date and badge on the cell and having the text flow around it is going to be no easy task. You may want to think about redesigning the table cell to make it a little easier on yourself. Something like this:

+-----------------------+----+
| BADGE|                |DATE|
|+-----+      TITLE     +----+
| dolor sit amet, consectetur|     
| adipiscing elit. Integer   |
| ligula lectus, convallis   |
| non scelerisque quis,      |
| tempor at nibh.  Curabitur |
| eget diam ligula.          |
| Pellentesque a elit        |
| dolor, a ullamcorper risus.|
+----------------------------+
like image 31
JiuJitsuCoder Avatar answered Oct 10 '22 03:10

JiuJitsuCoder