Styling specific line of Text on Jetpack Compose - android-jetpack-compose

So, it's kind of a simple styling.
Text(
text = "some text which can extends to many lines"
)
how would someone build an annotated string to style only specif lines of the text? And by line I mean what it's actually rendering as a line - and not something predefined as a list of sub strings.
I've imagine to make a use of combined textLayoutResult with the annotated capability, but by reading the documentation I don't have much clue how to do so.
The plan was to the TextLayoutResult to retrieve the number of lines rendered on text. Then, it should be theoretically possible to retrieve the sub string on each of the lines rendered. And by pushing them on the annotated processor, the desired results would be achieved.
What am I missing?

I've managed to achieve the desired effect.
For those who want to do, you will need at least:
Two Text components;
A mutable state to keep track of offset on the text;
You limit the first Text by the number of maxLines - 1 and uses TextLayoutResult to retrieve the last offset of the last line. Then, you just update the state on the composable and create another Text component with the substring which starts from the last one. Then, you can apply the filters that you wish on this one.
Repeate the process for as many lines as you wish.

Related

Fitting multi-line text into a dynamically size-changing node

A multiline auto typing text box class (which uses an SKNode as the parent) is created using basically 2 elements:
an SKSpriteNode that acts as text box frame & background image/texture holder.
an NSMutableArray containing a set limited amount (rows) of NSStrings that each have a set character length.
After modifying this text box class so that it can be initialized with any frame width & height, I realized I didn't program the NSMutableArray to automatically change its content in a such way that it nicely fits within the background node (with a bit of padding involved as well). So here I am wondering how to do that since NSString's can only return the character count and not the width & height of each string in points (points could have maybe helped me create character constraints in some way).
Right now, the NSMutableArray uses a hardcoded maximum character count per NSString & a maximum row count for the entire array (it's 5 rows right now and when that limit is reached, a new "page"/array is created). This forces me to manually re-adjust these parameters every time I change the background node frame size which defeats the purpose of the class allowing the background frame to change.
Thing is, I'm trying to solve this in such a way that when I post this class on github, I want the solution to take into consideration any fontName & fontSize.
What are my options for solving this problem?
I've done something similar to this. It doesn't work 100% as to what you want, but should be similar enough. It uses a root node and from there, it will build multi-line text using an array of NSString which will in turn be used to build the SKLabelNode.
I'll outline what I did. I should also say I only run this when new text is set. In other words, I do not incur the penalty of deriving the information every frame. Only once.
The generalized steps are:
You will iterate over each character in the text string. Note I do this because my code supports word wrapping as well as other alignment capabilities. So for me, I want that level of control. As this is being done only upon creation, I'm fine with the overhead. If you don't want to word wrap you could always just create an array of words and work from there.
As you iterate over each character, you'll be generating an array of lines. Where each line in the array is a line that will fit in your frame. For now let's not worry about vertical constraints. So here we are primarily worried about width. For the current line, each character you are iterating over will get added to the current line. For this potential line string, you will use NSString's sizeWithAttributes, which is configured for your font. For example in my code it is an NSDictionary which contains: NSFontAttributeName : [UIFont fontWithName:self.fontName size:self.size]. This will be used to check the width, if that width exceeds the frame width, you are overrunning the line.
So the code may look something like:
size = [line sizeWithAttributes:attributes];
if (size.width > maxTextWidth) {
needNewline = YES;
}
If you have overrun a line, you need to determine if you are word wrapping. If you are, you can just add the current line (minus one character) to the lines array. If not you have prune off the last word in the current line and then add that to the array of lines.
The tricky parts are dealing with whitespace and handling non-word wrapped overflow. I have not addressed whitespace but you need to consider this very much in your code. Additionally, you also do want to factor in leading pixels, etc.
Once you have your array of lines, you can then create your children SKLabelNodes. I add them to the root, which allows me to move the group anywhere it needs to be.
The real key here is the lines array generation.

How to clear the output in a cell in itorch notebook?

In itorch notebook, Is there a way to clear the output of a cell with code?
What I would like to do is to dynamically display the progress, like a loading bar.
The reason for this is when a lot of computation is involved, I would like to track how far the progress has gotten, and whether it froze or not.
So basically I would like to print the number of iteration I'm in in percentage form and overwrite it in the next iteration.
Any ideas?
You can use the carriage return character (\r) to overwrite the same line in a cell.
For example:
io.write("Hello") -- No newline
io.write("\rWorld")
just displays
World
You can use this to write several times the progress of your process, without adding multiple lines.

How do you rotate a text

There is a video on how to rotate an object around a point but I fail to select the text.
I wanted to do the same thing and saw your question before figuring this out.
1. The "Geogebra Way"
In the Algebra Perspective enter the following RotateText commands in the Input box at the bottom:
RotateText["Rotated text using degrees.", 45°]
RotateText["Rotated text using radians.", 0.785398]
In the Construction Protocol view, this is represented by
"rotatebox{45}{ \text{Rotated text using degrees.} }"
"rotatebox{44.9999999}{ \text{Rotated text using radians.} }"
Note that the radian form of the RotateText command is converted to degrees in the construction step. So this creates an graphical object that renders the text in a LaTeX "rotatebox". It's rather strange that the system doesn't have a tool to create rotateable text.
You can attach the text to an object via the object's Properties->Position->Starting Point. Only certain types of objects can be used, and the text can only be placed/moved underneath the object, which is odd. You can get around this by creating a line segment, attaching the rotateable text object to a desired end-point on the line segment above the location you want the final text, and then hiding the line segment.
2. A better, "undocumented" Geogebra method!
One can actually use LaTeX in captions of objects. Here's how you would enter the text:
$\rotatebox{45}{ \text{Rotated text using standard text box!} }$
A nice thing about this is the caption can be easily placed above the object. Notice that LaTeX commands are surrounded by the dollar sign. Also notice that there is a backslash as part of the \rotatebox command.
Also, one can use the standard text tool to do the same thing. This has the advantage that the text can be dynamic! Create some text anywhere. Then edit it's properties on the Text tab. Check the LaTeX checkbox, and enter the following for the text:
$\rotatebox{45}{ \text{} }$
Then inside the \text{} brackets, select an object. The text will be updated with the object's value. Or a combined form:
$\rotatebox{45}{ \text{"The value is:" + SliderObject} }$
I've tried to put an object in the "degreees" field, but could not get that to work.
Use the RotateText command like this:
RotateText("What ever text you want", angle)

Word Openxml: how to get a text box the right size?

I'm using PHP to generate docx documents from a database. The generated document contains column charts which have labels attached (i.e. user shapes containing textboxes). In an attempt to get the textboxes to accommodate and display all of the text (i.e. it shouldn't be necessary for the user to resize a textbox to see all the text) my code calculates how many characters will fit into 3cm, adds linefeeds to the string as required and tells me how many lines of text are needed. I have:
<a:xfrm xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:off x="1638276" y="1676399"/>
<a:ext cx="1257325" cy="'.(252000 * $labelLeftLines).'"/>
</a:xfrm>
which I believe should give me a text box around 3.5cm wide (extra .5 for the internal padding) and a height of .7cm multiplied by whatever is the value of $labelLeftLines. However, the text box always turns up as 3.cm wide by .86cm high, which only ever displays one line of text.
If I add in 'autofit':
<a:bodyPr xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" vertOverflow="clip" wrap="square" rtlCol="0">
<a:spAutoFit/>
</a:bodyPr>
the generated file looks just the same, though, when I right click on the textbox to inspect the properties, 'autofit' is indeed applied. I have to uncheck it and recheck it to make it affect the textbox.
Any openXML gurus out there?
Hmm, some random floundering around revealed that the values I need to manipulate are here:
<cdr:relSizeAnchor xmlns:cdr="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing">
<cdr:from>
<cdr:x>0.47</cdr:x>
<cdr:y>0.75</cdr:y>
</cdr:from>
<cdr:to>
<cdr:x>0.67</cdr:x>
<cdr:y>1</cdr:y>
</cdr:to>
Changing those values does actually change the size of the texbox, though I haven't a clue what units are being used. From 0.75 to 1 produces a height of 1.43cm.
One day I'll maybe be able to find my way around the doucmentation.

BiDi text in Delphi - How do you select text to edit by language like this pic?

I saw this picture and now wondering if/how you can do this in Delphi. The highlighted/selected text shows two forms of formatting, i.e. highlight color and hash lines.
http://img9.imageshack.us/img9/4121/easilyselecttextofonela.jpg
I've done something very similar recently in a bible application, also done in Delphi.
The user can select a single verse and single words of the selected verses. (But this feature is not released yet, so don't bother looking for it)
I used the web browser control from Microsoft and added my own kind of selection handling.
I've done the formatting by enclosing the relevant parts with span elements and changing their CSS style. When the selection gets removed, I also remove the enclosing elements.
The hard part was backing the "visual" selections with a selection data structure and handling all the selection events (clicking, shift-clicking, shift-ctrl-clicking, ...)
Embedding IE seems to be an easier way to do this as DR says, but you can also do this manually by drawing it all on a canvas, an easy way would be to create two bitmaps (one without a selection and another selected (could be as complicated as you like - dashed, colored, ... )), and you need to know the positions/rects of all your characters which would be somewhat difficult for long texts.
You basically show the unselected bitmap, and overlap the selected parts by portions of the second image.
You would also need to handle the selection manually by OnMouseDown, OnMouseMove, OnMouseUp...

Resources