Is there a way to draw formatted text on a canvas?
I have used the code below tons of times.
g.drawstring "Hello World", 10, 10
But I am wondering why I couldn’t just sent formatted text to a canvas.
Is there a way to draw formatted text on a canvas?
I have used the code below tons of times.
g.drawstring "Hello World", 10, 10
But I am wondering why I couldn’t just sent formatted text to a canvas.
[quote=226524:@Edwin van den Akker]Is there a way to draw formatted text on a canvas?
I have used the code below tons of times.
g.drawstring "Hello World", 10, 10
But I am wondering why I couldn’t just sent formatted text to a canvas.[/quote]
What do you mean by " sent formatted text to a canvas" ? You mean styled ?
Yep
Graphicshas several properties for setting various styling attributes like color etc
http://documentation.xojo.com/index.php/Graphics
[quote=226529:@Norman Palardy]Graphicshas several properties for setting various styling attributes like color etc
http://documentation.xojo.com/index.php/Graphics[/quote]
Thanks Norman. I do make great use of those styling attributes in the graphics object. But what if I have a chunk of data that contains Styled Text… I would love to have that be drawn on a canvas. I have been dealing with parsing the styled text, and drawing it in chucks. But with wrapping it all goes wrong. Words are cut in pieces… there must be an easier way, not?
would be nice but no
graphics has no way to draw styled text
I know this all too well since thats the way the IDE does the code editor
Its basically a canvas
TextArea.DrawInto could be a way.
or just interate thru the styleruns in the styled text and alter the graphics attributes and use DRAWSTRING
I offer this code AS-IS… but I think it contains everything you need to do what you are asking… I dug it uup from an old project
it is directly from a XOJO_CODE file so there are extra tags and such
#tag Module
Protected Module StyledTextDrawing
#tag Method, Flags = &h21
Private Sub DrawLIne(theLine as DrawnLine, g as Graphics, x As Integer, y As Integer, theWidth As Integer)
#If Not DebugBuild
#pragma DisableBackgroundTasks
#pragma DisableBoundsChecking
#pragma DisableAutoWaitCursor
#EndIf
Dim currLineAscent As Integer = theLine.LineTextAscent
Dim s As DrawnSection
Dim currX As Integer
Select Case theLine.LineAlignment
Case 0, 1 // normal (left aligned)
currX = x
Case 2 // centered
currX = x + (theWidth-theLine.LineWidth)/2
Case 3 // right aligned
currX = x + (theWidth-theLine.LineWidth)
End Select
For Each s In theLine.Sections
s.SetTo g
If g.ForeColor=color_white And Dragging_Text_Mode=1 Then g.ForeColor=Color_OffWhite
g.DrawString s.SectionText, currX, y + currLineAscent
currX = currX + g.StringWidth(s.SectionText)
Next
End Sub
#tag EndMethod
#tag Method, Flags = &h0
Sub DrawStyledText(g as Graphics, theStyledText as StyledText, x As Integer = 0, y As Integer = 0, wrapWidth As Integer = 9999)
#If Not DebugBuild
#pragma DisableBackgroundTasks
#pragma DisableBoundsChecking
#pragma DisableAutoWaitCursor
#EndIf
Dim line As DrawnLine
Dim lastY As Integer = y
Dim st As New FormattedText(theStyledText)
SaveGraphicsSettings g
While UBound(st.StyleRuns) >= 0
line = PrepareLine(st, wrapWidth)
DrawLIne line, g, x, lastY, wrapWidth
lastY = lastY + line.LineTextHeight
Wend
RestoreGraphicsSettings g
End Sub
#tag EndMethod
#tag Method, Flags = &h21
Private Function PrepareLine(theStyledText as FormattedText, theWidth As Integer = 9999) As DrawnLine
#If Not DebugBuild
#pragma DisableBackgroundTasks
#pragma DisableBoundsChecking
#pragma DisableAutoWaitCursor
#EndIf
Dim lastWidth As Integer
Dim wordIdx As Integer
Dim numWords As Integer
Dim sec(), d As DrawnSection
Dim currRun As FormattedTextRun
Dim l As New DrawnLine
While (UBound(theStyledText.StyleRuns) >= 0) And Not UserCancelled
currRun = theStyledText.StyleRuns(0)
l.LineAlignment = currRun.Alignment // We store alignment on a per-line basis, since it's easier that way.
d = New DrawnSection
d.SetFrom currRun // Sets formatting aspects of the section we are trying to append
// First see if we can fit the whole run on the current line...
d.SectionText = currRun.Text
sec.Append d
If lastWidth + d.SectionWidth < theWidth Then
// we can fit the whole run on, so delete it from theStyledText...
theStyledText.StyleRuns.Remove 0
If InStr(d.SectionText, EndOfLine) > 0 Then Exit
lastWidth = lastWidth + d.SectionWidth
Else
// nope, doesn't fit the whole run on. Let's try it word-by-word...
d.SectionText = ""
wordIdx = 1
numWords = CountFields(currRun.Text, " ")
While (lastWidth + d.SectionWidth < theWidth) And (wordIdx <= numWords)
d.SectionText = d.SectionText + NthField(currRun.Text, " ", wordIdx) + " "
wordIdx = wordIdx + 1
Wend
// Now that we've found the shortest string that is too long,
// shave off the last word to make it fit...
d.SectionText = Mid(d.SectionText, 1, Len(d.SectionText)-Len(NthField(currRun.Text, " ", wordIdx-1))-1)
currRun.Text = Mid(currRun.Text, Len(d.SectionText)+1) // +1 to get rid of trailing space
Exit
End If
Wend
l.Sections = sec
Return l
End Function
#tag EndMethod
#tag Method, Flags = &h21
Private Sub RestoreGraphicsSettings(g as Graphics)
g.TextFont = gTextFont
g.TextSize = gTextSize
g.ForeColor = gTextColor
g.Bold = gBold
g.Italic = gItalic
g.Underline = gUnderline
End Sub
#tag EndMethod
#tag Method, Flags = &h21
Private Sub SaveGraphicsSettings(g as Graphics)
gTextFont = g.TextFont
gTextSize = g.TextSize
gTextColor = g.ForeColor
gBold = g.Bold
gItalic = g.Italic
gUnderline = g.Underline
End Sub
#tag EndMethod
#tag Property, Flags = &h21
Private gBold As Boolean
#tag EndProperty
#tag Property, Flags = &h21
Private gItalic As Boolean
#tag EndProperty
#tag Property, Flags = &h21
Private gTextColor As Color = &c000000
#tag EndProperty
#tag Property, Flags = &h21
Private gTextFont As String
#tag EndProperty
#tag Property, Flags = &h21
Private gTextSize As Integer
#tag EndProperty
#tag Property, Flags = &h21
Private gUnderline As Boolean
#tag EndProperty
#tag ViewBehavior
#tag ViewProperty
Name="Index"
Visible=true
Group="ID"
InitialValue="-2147483648"
Type="Integer"
#tag EndViewProperty
#tag ViewProperty
Name="Left"
Visible=true
Group="Position"
InitialValue="0"
Type="Integer"
#tag EndViewProperty
#tag ViewProperty
Name="Name"
Visible=true
Group="ID"
Type="String"
#tag EndViewProperty
#tag ViewProperty
Name="Super"
Visible=true
Group="ID"
Type="String"
#tag EndViewProperty
#tag ViewProperty
Name="Top"
Visible=true
Group="Position"
InitialValue="0"
Type="Integer"
#tag EndViewProperty
#tag EndViewBehavior
End Module
#tag EndModule
You could also consider an invisible TextArea, using it’s StyledTextPrinter to Draw the text. I haven’t used it real world applications, but it does seem to work very well.
Here’s an example in the paint event of a canvas. Textarea1 is an invisible textarea with styled turned on.
[code] dim t as TextArea=TextArea1
t.text=“a,b,c,d,e,f”
t.SelStart=0
t.SelLength=1
t.SelBold=true
t.SelStart=2
t.SelTextColor=&cff0000
t.selstart=4
t.SelBold=false
t.SelStart=6
t.SelTextColor=&cff00ff
t.SelStart=8
t.SelTextColor=&c00ff00
dim p as StyledTextPrinter=t.styledTextPrinter(g,20)
p.DrawBlock(0,0,300)
[/code]
You could also just set the styledText property directly, or feed it RTF data and render that to screen…
Not any more, necessarily: “StyledTextPrinter no longer works on Windows starting with 2016r4.”
You guys can always use DynaPDF to make a temporary in memory PDF with text, render it to picture and draw to window.
Or use native functions like NSAttributeStringMBS and NSGraphicsMBS classes in MBS Xojo Plugins.
[quote=226532:@Norman P]would be nice but no
graphics has no way to draw styled text
I know this all too well since thats the way the IDE does the code editor
Its basically a canvas[/quote]
Is that why when pressing the space bar on repeat, the cursor might basically disappear until you let go of the space bar? This happens if the blinking cursor happened to be “off” when the repeat started.
Rendering to PDF seems overkill to me, and probably is also not performing too well when you’re trying to render 100s of little Excel cells into a Canvas, like I do
On macOS very likely
Windows draws the cursor differently