Tutorial 3: A treeview
Step 1: Including the OneSprite Widget libraries
Create a new movie and either attach the "OSW_behaviours", "OSW_Factories" and "OWS_Core" casts to your movie or import the contents to your movie.
Step 2: Create a placeholder bitmap
Create a simple blank bitmap cast member that is the size you want your treeview to be. Position this bitmap on stage at the location you want, then drag the "Proxy.TreeView" behaviour from the 'OWS_behaviours' cast on to the sprite.
Step 3. Configure the Widget
When you attached the behaviour, the GetPropertyDescriptionList dialog will appear. Leave all the settings at their default for now.
Step 4. Create a "TreeviewController" behaviour
Create a new behaviour and add this to the sprite with the treeview behaviour. Call this second behaviour "TreeviewController" or something. The add some lingo like this
on NodeTreeReady (me, sender, id)
nodeTree = []
nodeTree.add( [#Label: "Node 1"])
nodeTree.add( [#Label: "Node 2"])
nodeTree.add( [#Label: "Node 3"])
sender.Display(nodeTree)
sender.addListener(me)
end
on NodeTreeClick (me, sender, args)
put args
end
When the 'TreeviewController' receives the 'NodeTreeReady' message, it constructs a simple list for the node tree to display and then tells the nodetree to display it. The result will look like this:
The list that the node tree accepts is a linear list of 'nodes'. Nodes are property lists which describe that node. The simplest node can have a single property - #Label. This determines the text that will appear in the node tree.
Nodes can also have a #children property which is a list of nodes which appear as 'children' of the node. For example:
on NodeTreeReady (me, sender, id)
nodeTree = []
nodeTree.add( [#Label: "Node 1"])
nodeTree.add( [#Label: "Node 2"])
nodeTree.add( [#Label: "Node 3", #children: [[#Label: "Node 3-1"]]])
sender.Display(nodeTree)
sender.addListener(me)
end
on NodeTreeClick (me, sender, args)
put args
end
The third node now has a child, and the result looks like this:
The following is a slightly more complex example. This code creates a node tree list of all the casts and members of the current movie.
-- Behaviour 'CastBrowser'
property myNodeTreeRef
on NodeTreeReady (me, sender, id)
nodeTree = []
repeat with i = 1 to the number of castlibs
children = []
repeat with j =1 to the number of members of castlib i
whatName = member(j,i).name
if whatName = "" then whatName = "<no name>"
aNode = [#Label: whatName]
children.add(aNode)
end repeat
whatName = castlib(i).name
if whatName = "" then whatName = "<no name>"
aNode = [#Label: whatName, #Children: Children]
nodeTree.add(aNode)
end repeat
myNodeTreeRef = sender
myNodeTreeRef.Display(nodeTree)
myNodeTreeRef.addListener(me)
end
on NodeTreeClick (me, sender, args)
put "NODE SELECTED: " & args
end
You can also specify a #Icon property for a node. The value should either be the name of a bitmap, a cast member reference or an image object. You can also specify other properties for the node. These extra property/value pairs are returned as parameters when the node is selected.
In this next example, each cast member.type is checked, and a corresponding icon is assigned to the node. The member type is also stored with the node.
-- Behaviour 'CastBrowserWithIcons'
-- treeview of the cast members of the current movie
-- (with icons)
property myNodeTreeRef
on NodeTreeReady (me, sender, id)
nodeTree = []
repeat with i = 1 to the number of castlibs
children = []
repeat with j =1 to the number of members of castlib i
aNode = [:]
aNode[#Label] = member(j,i).name
if aNode[#Label] = "" then aNode[#Label] = "<no name>"
aNode[#EntryType] = "CastMember"
if member(j,i).type = #script then
aNode[#Icon] = string(member(j,i).Scripttype) & "script"
else
aNode[#Icon] = string(member(j,i).type)
end if
children.add(aNode)
end repeat
aNode = [:]
aNode[#Label] = castlib(i).name
aNode[#EntryType] = "CastLib"
aNode[#children] = children
nodeTree.add(aNode)
end repeat
myNodeTreeRef = sender
myNodeTreeRef.Display(nodeTree)
myNodeTreeRef.addListener(me)
end
on NodeTreeClick (me, sender, args)
put "NODE SELECTED: " & args
end
The final example demonstrates how you can change the node tree using the SetNodeValue() and Setchildren() methods. This behaviour creates a 'file browser'. Whenever a directory is clicked and opened, it checks whether the node represents a directory or a file. If it was a directory, it builds a list of the directory's contents and updates the node tree. Whenever a file is clicked and opened, it changes the name of the file to 'opening' (this is just to illustrate how individual nodes in the tree can be updated)
-- Behaviour 'FileBrowser'
-- Uses BuddyAPI to build a 'tree' of files and folders
property myNodeTreeRef
on NodeTreeReady (me, sender, id)
-- build a 'nodetree' list from the directory contents
-- starting with the contents of 'the applicationPath'
nodeTree = []
-- first, list all the folders
folders = baFolderList(the applicationPath)
repeat with aFolder in folders
nodeTree.add([#Label: aFolder, #EntryType: #Directory, #Children:[]])
end repeat
-- second, list all the files
files = baFileList(the applicationPath, "*")
repeat with aFile in files
nodeTree.add([#Label: aFile, #EntryType: #File])
end repeat
myNodeTreeRef = sender
myNodeTreeRef.Display(nodeTree)
myNodeTreeRef.addListener(me)
end
on NodeTreeClick (me, sender, args)
put args
case( args.eventType) of
#NodeOpened:
-- a node has been opened
sep = the last char of the applicationPath
pathToNode = myNodeTreeRef.GetValueFromPath(args.path)
pathToOpen = the applicationPath & Implode(sep, pathToNode)
if args.EntryType = #Directory then
-- list the contents of this directory
subFolder = []
folders = baFolderList(pathToOpen)
repeat with aFolder in folders
subFolder.add([#Label: aFolder, #EntryType: #Directory, #Children:[]])
end repeat
files = baFileList(pathToOpen, "*")
repeat with aFile in files
subFolder.add([#Label: aFile, #EntryType: #File])
end repeat
myNodeTreeRef.SetChildren(subFolder, args.path )
else
-- example of changing the label
myNodeTreeRef.SetNodeValue("Opening...", args.path )
end if
#NodeClosed:
sep = the last char of the applicationPath
pathToNode = myNodeTreeRef.GetValueFromPath(args.path)
pathToOpen = the applicationPath & Implode(sep, pathToNode)
if args.EntryType = #Directory then
-- remove the subfolder of this directory from current tree
myNodeTreeRef.SetChildren([], args.path )
else
-- example of changing the label
myNodeTreeRef.SetNodeValue("Closing...", args.path )
end if
end case
end