Articles Archive
Articles Search
Director Wiki
 

Formatting Text with Lingo

November 28, 1999
by Pat McClellan

Dear Multimedia Handyman,

One can create text members with multiple fonts and sizes and colors manually, but can you do this with lingo? Something like this?

sprite(1).member.text.line[1].char[2..4].font = "bodoni"

stephen turbek

Stephen,

Almost. Text members had a number of properties which can be controlled through Lingo. Take a look at page 465 of your Lingo Dictionary (D7 version). There's a list of just about anything you could want to format. (NOTE: typo... "fontf" should just be "font".) I tried manipulating most of these properties and found a few that only work on field members (not text members) such as backcolor. Note that some of these properties can be isolated to a specific character or text chunk, while others can only apply to a paragraph (tabs, for example). Still others can only be used to affect the entire text member.

It's interesting to note that by using some of these Lingo commands, you can exert formatting control that is not otherwise available in Director. Take a look at the topSpacing and bottomSpacing commands. I don't know how to do what they do any other way.

Notice that this list of properties doesn't include the most basic: text. They include "text" on the previous page, with regard to manipulating strings, which brings us back to your question and the line of code you asked about. When you talk about the text of a member, you're really talking about a string of characters. Since the value is in string format, it carries no formatting data whatsoever. So think about the text separate from the formatting. Now you'll see why the code above doesn't work: there can be no font information contained within the text of a member. Instead, it would be accessed this way:

sprite(1).member.line[1].char[2..4].font

I based this line on your example line above. You don't have to use both line and char, but you can. Since this is line[1], it's redundant. Also, you don't have to reference the sprite since the properties are really member properties. If you knew the name of the member ("myText" for example), you could also say:

member("myText").char[2..4].font

And based on the list on page 465 (Lingo Dictionary), you could also use these:

member("myText").char[2..4].fontSize
member("myText").char[2..4].fontStyle
member("myText").char[2..4].color
member("myText").char[2..4].charSpacing
member("myText").char[2..4].fontSpacing

And for paragraphs:

member("myText").paragraph[1].tabs
member("myText").paragraph[1].topSpacing

And for the non-chunk specific properties...

member("myText").alignment
member("myText").bgColor
member("myText").antiAlias
member("myText").kerning

Remember that I'm using a hypothetical text member named "myText". You'll need to substitute the name of your text cast member, or reference it some other way. Experiment with these command and the others listed in the Lingo Dictionary.

Here's a demo that shows many of the formatting controls you can create with Lingo. It's not comprehensive, but it covers the most common commands.

A sample movie is available for download in Mac or PC format. This is a D7 movie.

To create this demo, I started with a behavior which is applied to the text member itself. When you mouseUp or select text within the member, the behavior stores the starting and ending character range and sends out a message to all sprites reporting the formatting status of those characters. In response, a behavior on the buttons and other formattting controls takes this info and displays the current formatting. The behaviors on the formatting control buttons toggle or increment their respective properties and send a message back to the text member to format the text, supplying the particular operation and value.

Here's the code for the formatter behavior (on the text member):

-- formatter behavior
-- copyright © 1999, ZZP Online, LLC
-- free use for Director Online readers
property pMem, pStartChar, pEndChar, spriteNum
on beginSprite me
  pMem = sprite(me.spriteNum).member
  pMem.editable = TRUE
  getSelection me
end
on keyUp me
  getSelection
  pass
end
on mouseUp me
  getSelection me
  reportStatus me
end mouseUp
on getSelection me
  pStartChar = pMem.selection[1] + 1
  pEndChar =  pMem.selection[2]
end getSelection
on reportStatus me
  tempEndChar = pEndChar
  if tempEndChar < pStartChar then tempEndChar = pStartChar
  styleList = pMem.char[pStartChar..tempEndChar].fontStyle
  stringStyles = string(styleList)
  boldStatus = stringStyles contains "bold"
  underlineStatus = stringStyles contains "underline"
  italicStatus = stringStyles contains "italic"
  myProps = [:]
  
  addProp myProps, #myFont, pMem.char[pStartChar..¬
    tempEndChar].font
  addProp myProps, #myFontSize, pMem.char[pStartChar..¬
    tempEndChar].fontSize
  addProp myProps, #myColor, pMem.char[pStartChar..¬
    tempEndChar].color
  addProp myProps, #myCharSpacing, pMem.char¬
    [pStartChar..tempEndChar].charSpacing
  addProp myProps, #bold, boldStatus
  addProp myProps, #underline, underlineStatus
  addProp myProps, #italic, italicStatus 
  addProp myProps, #alignment, pMem.alignment
  
  sendAllSprites (#selectionStatus, myProps, spriteNum)
  
end
on formatText me, whichOperation, whichProp, value
  if pStartChar > pEndChar then 
    reportStatus me
  else
    call (whichOperation, me, whichProp, value)
  end if
  
end formatText me
on setFontStyle me, whichProp, value
  styleList = pMem.char[pStartChar..pEndChar].fontStyle
  
  if getOne(styleList, whichProp) then
    deleteOne(styleList, whichProp)
    
    if styleList.count = 0 then
      add(styleList, #plain)
    end if
    
  else
  
    deleteOne(styleList, #plain)
    add(styleList, whichProp)
  end if
  
  pMem.char[pStartChar..pEndChar].fontStyle = styleList
  
end setFontStyle
on setFontSize me, whichProp, value
  pMem.char[pStartChar..pEndChar].fontSize = value
  reportStatus me
end setFontSize
on setCharSpacing me, whichProp, value
  pMem.char[pStartChar..pEndChar].charSpacing = value
  reportStatus me
end
on setFontColor me, whichProp, value
  pMem.char[pStartChar..pEndChar].color = value
  reportStatus me
end
on setAlignment me, value
  pMem.alignment = value
  reportStatus me
end

The formatControl behavior is attached to all of the buttons:

-- formatController behavior
-- copyright © 1999, ZZP Online, LLC
-- free use for Director Online readers
-- use in conjunction with the formatter behavior
property pMyProp, pMyValue, spriteNum, pTextSpriteNum
property pWhichOperation, pIncrement
on beginSprite me
  pMyValue = 0
  case pMyProp of
    #bold, #underline, #italic: 
      pWhichOperation = #setFontStyle
    #myFont: 
      pWhichOperation = #setFont
    #myFontSize: 
      pWhichOperation = #setFontSize
    #myCharSpacing: 
      pWhichOperation = #setCharSpacing
  end case
  
end beginSprite
on selectionStatus me, myPropList, textSpriteNum
  pTextSpriteNum = textSpriteNum
  --  put "textSpriteNum received by" && pMyProp &":" ¬
    && pTextspriteNum
  pMyValue = getaProp(myPropList, pMyProp)
  --  put pMyProp & ":" && pMyValue
  displayStatus me
  
end selectionStatus
on displayStatus me
  case pMyProp of
    #myFont: 
      the text of member("fontDisplay") = string(pMyValue)
    #myFontSize: 
      the text of member("fontSizeDisplay") = string(pMyValue)
    #bold, #underline, #italic : 
      sendSprite(spriteNum,  #setToggle, pMyValue)
    #myColor: 
      member("colorChip").color = pMyValue
    #myCharSpacing: 
      the text of member("charSpacingDisplay") = string(pMyValue)
  end case  
end displayStatus
on setValue me, value
  pMyValue = value
  sendSprite(pTextSpriteNum, #formatText, pWhichOperation, ¬
    pMyProp, pMyValue)
end setValue
on incrementValue me
  pMyValue = pMyValue + pIncrement
  sendSprite(pTextSpriteNum, #formatText, pWhichOperation, ¬
    pMyProp, pMyValue)
end
on getPropertyDescriptionList me
  propOptions = [#myFont, #bold, #underline, #italic, ¬
    #myFontSize,  #myColor, #myCharSpacing] 
  set pdlist to [:]
  
  addprop pdlist, #pMyProp, [#comment:"Which property?", ¬
    #format:#symbol, #default:#myFont, #range: propOptions]
  addprop pdlist, #pIncrement, [#comment:"Increment:", #format:¬
    #integer, #default: 1, #range: [#min:-3,#max:3]]
  
  return pdlist
  
end getPropertyDescriptionList

Note that the formatController behavior doesn't control the button toggles. For that, I use standard toggle and pushbutton behaviors. You can download the movie to see exactly how all of that works. Have fun experimenting with text formatting. When you've allowed the user to format the text, you can try exporting the rtf of the member as a text file (using FileIO). Good luck!

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.

Copyright 1997-2017, Director Online. Article content copyright by respective authors.