The TreeView is an extended ListView control with the ability to accept and display hierachical or complex data. The TreeView is equipped with an internal lineariser, which maps the given complex data structure to a linear list by maintaining expanded and collapsed items. The TreeView can be customised in several ways. This document describes all the possibilities to configure a TreeView control.
TreeView demo application
Click the image below for an interactive interface demo of the TreeView control. The demo lets you change data, styles and functionality of the component and provides information about the events dispatched and styles set.
If the popup does not do well, click here.
Setting up the data
The TreeView can work with any kind of hierachical data. There is no restriction in the type of the particular data source items. Its also possible to mix different types in one data source. The TreeView only needs to know for each item, how many children it contains (numItems) and how to get a child item at a specific index (getItemAt). There are three ways to provide this information.
- Using a supported data source type without any preperation.
- Implementing the IDataProvider interface in all item classes, if you are free in designing the data source.
- Setting up a data source adapter, if you want to use a given (closed) object as the data source of the tree.
Using a supported data source
The TreeView already comes with support for a few types, from that it automatically extracts the numItems and getItemAt information.
- XML
- Array
- All maps, sets and the ArrayList from the AS3Commons Collections package
Look at the DataSourceAdapterFactory.as and see, how the TreeView handles the different item types. The example below shows an XML acting as the data source of the TreeView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.sibirjak.asdpc.treeview { import com.sibirjak.asdpc.common.Example; public class TreeViewExample extends Example { public function TreeViewExample() { var treeView : TreeView = new TreeView(); treeView.dataSource = new XML( <item name="Root"> <item name="Node_1"> <item name="Node_1_1" /> <item name="Node_1_2" /> </item> <item name="Node_2" /> </item> ); addChild(treeView); } } } |
Implementing the data provider interface
The two requirements above are modelled in a very small IDataProvider interface.
1 2 3 4 5 6 | package com.sibirjak.asdpc.core.dataprovider { public interface IDataProvider { function getItemAt(index : uint) : *; function get numItems() : uint; } } |
Building a complex data source by implementing this interface is easy and may look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | package com.sibirjak.asdpc.treeview { import com.sibirjak.asdpc.common.Example; public class SimpleDataProviderExample extends Example { public function SimpleDataProviderExample() { var dataSource : Node = new Node("Root"); var node_1 : Node = new Node("Node_1"); node_1.addNode(new Node("Node_1_1")); node_1.addNode(new Node("Node_1_2")); dataSource.addNode(node_1); dataSource.addNode(new Node("Node_2")); var treeView : TreeView = new TreeView(); treeView.dataSource = dataSource; addChild(treeView); } } } import com.sibirjak.asdpc.core.dataprovider.IDataProvider; internal class Node implements IDataProvider { private var _name : String; private var _childNodes : Array = new Array(); public function Node(name : String) { _name = name; } public function addNode(node : Node) : void { _childNodes.push(node); } public function getItemAt(index : uint) : * { return _childNodes[index]; } public function get numItems() : uint { return _childNodes.length; } public function get name() : String { return _name; } } |
Creating a data source adapter
If the data source cannot implement the IDataProvider interace, it is necessary to write a custom data source adapter by implementing the IDataSourceAdapter interface. The adapter accepts an item from the original data source and knows how to retrieve numItems and getItemAt information from this item.
1 2 3 4 5 6 | package com.sibirjak.asdpc.core.dataprovider { public interface IDataSourceAdapter extends IDataProvider { function get dataSource() : *; function cleanUp() : void; } } |
Creating a custom data source adapter is a two-step procedure.
- Creating the adapter
- Creating a data source adapter factory function
Creating an adapter is as simple as it could be. Let’s assume our data source item is a Node object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | internal class Node { private var _name : String; private var _childNodes : Array = new Array(); public function Node(name : String) { _name = name; } public function addNode(node : Node) : void { _childNodes.push(node); } public function get name() : String { return _name; } public function get childNodes() : Array { return _childNodes; } } |
The data source adapter then will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import com.sibirjak.asdpc.core.dataprovider.IDataSourceAdapter; internal class NodeAdapter implements IDataSourceAdapter { private var _node : Node; public function NodeAdapter(node : Node) { _node = node; } public function get dataSource() : * { return _node; } public function getItemAt(index : uint) : * { return _node.childNodes[index]; } public function get numItems() : uint { return _node.childNodes.length; } public function cleanUp() : void { // empty } } |
We now have to tell the TreeView that it should use the NodeAdapter if it encounters a Node object. To do so, we write da data source adapter function.
1 2 3 4 | private function getAdapter(item : *) : IDataProvider { if (item is Node) return new NodeAdapter(item); return null; } |
Finally, we assign this function to the appropriate TreeView property.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package com.sibirjak.asdpc.treeview { import com.sibirjak.asdpc.common.Example; import com.sibirjak.asdpc.core.dataprovider.IDataProvider; public class SimpleDataSourceAdapterExample extends Example { public function SimpleDataSourceAdapterExample() { var dataSource : Node = new Node("Root"); var node_1 : Node = new Node("Node_1"); node_1.addNode(new Node("Node_1_1")); node_1.addNode(new Node("Node_1_2")); dataSource.addNode(node_1); dataSource.addNode(new Node("Node_2")); var treeView : TreeView = new TreeView(); treeView.dataSource = dataSource; treeView.dataSourceAdapterFunction = getAdapter; addChild(treeView); } private function getAdapter(item : *) : IDataProvider { if (item is Node) return new NodeAdapter(item); return null; } } } |
Example: Visualising the display List
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package com.sibirjak.asdpc.treeview { import com.sibirjak.asdpc.common.Example; import com.sibirjak.asdpc.core.dataprovider.IDataProvider; import flash.display.DisplayObjectContainer; public class DisplayListExample extends Example { public function DisplayListExample() { var treeView : TreeView = new TreeView(); treeView.setSize(440, 360); treeView.dataSource = stage; treeView.dataSourceAdapterFunction = getAdapter; treeView.expandNodeAt(0); addChild(treeView); } private function getAdapter(item : *) : IDataProvider { if (item is DisplayObjectContainer) { return new DOCAdapter(item); } return null; } } } import com.sibirjak.asdpc.core.dataprovider.IDataSourceAdapter; import flash.display.DisplayObjectContainer; internal class DOCAdapter implements IDataSourceAdapter { private var _view : DisplayObjectContainer; public function DOCAdapter(view : DisplayObjectContainer) { _view = view; } public function get dataSource() : * { return _view; } public function getItemAt(index : uint) : * { return _view.getChildAt(index); } public function get numItems() : uint { return _view.numChildren; } public function cleanUp() : void { // empty } } |
Creating a label function
By default, the TreeView looks for the public properties “label” or “name” to extract a suitable label text, that can be displayed. Look at the genericToStringFunction.as and see, how the TreeView extracts the label text from an item. However, in some cases such a property does not exist or a different than the default value should be displayed. Here it is possible to assign a label function, wich is used instead of the generic toString function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | package com.sibirjak.asdpc.treeview { import com.sibirjak.asdpc.common.Example; import com.sibirjak.asdpc.listview.renderer.ListItemContent; public class LabelFunctionExample extends Example { public function LabelFunctionExample() { var dataSource : Node = new Node("Root"); var node_1 : Node = new Node("Node_1"); node_1.addNode(new Node("Node_1_1")); node_1.addNode(new Node("Node_1_2")); dataSource.addNode(node_1); dataSource.addNode(new Node("Node_2")); var treeView : TreeView = new TreeView(); treeView.dataSource = dataSource; treeView.setStyle( ListItemContent.style.labelFunction, labelFunction ); addChild(treeView); } private function labelFunction(data : TreeNodeData) : String { return Node(data.item).key; } } } import com.sibirjak.asdpc.core.dataprovider.IDataProvider; internal class Node implements IDataProvider{ public var key : String; public var childNodes : Array = new Array(); public function Node(theKey : String) { key = theKey; } public function addNode(node : Node) : void { childNodes.push(node); } public function getItemAt(index : uint) : *{ return childNodes[index]; } public function get numItems() : uint{ return childNodes.length; } } |
The label function is set as a style with the constant “ListItemContent.style.labelFunction” used as the property name. All styles properties within the ASDPC have their particular constant. This can be useful, if your IDE supports property completion. The style “labelFunction” is defined for the class ListItemContent, which finally renders the item. More to this in the Styling the TreeView section.
Using the public interface
The public interface of the TreeView control extends the ListView control interface and offers expand/collapse, selection and scroll operations beside the possibilities to set and retrieve data information. Visit the APIdoc for a comprehensive description of the TreeView interface.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | package com.sibirjak.asdpc.treeview { import com.sibirjak.asdpc.common.Example; public class PublicInterfaceExample extends Example { public function PublicInterfaceExample() { // Fully expanded var treeView : TreeView = new TreeView(); treeView.setSize(200, 200); treeView.dataSource = getDataSource(); treeView.expandNodeAt(0, true); addChild(treeView); // Expanded and selected treeView = new TreeView(); treeView.setSize(200, 80); treeView.dataSource = getDataSource(); treeView.expandNodeAt(0); treeView.selectItemAt(1); treeView.moveTo(210, 0); addChild(treeView); // Fully expanded and scrolled treeView = new TreeView(); treeView.setSize(200, 100); treeView.dataSource = getDataSource(); treeView.expandNodeAt(0, true); treeView.scrollToItemAt(2); treeView.moveTo(210, 100); addChild(treeView); } private function getDataSource() : * { return new XML( <item name="Root"> <item name="Node_1"> <item name="Node_1_1" /> <item name="Node_1_2"> <item name="Node_1_2_1" /> <item name="Node_1_2_2" /> </item> <item name="Node_1_3" /> </item> <item name="Node_2"> <item name="Node_2_1" /> <item name="Node_2_2" /> </item> </item> ); } } } |
Styling the TreeView
The TreeView (as with all ASDPC controls) can be extensively customised in functionality and appearance using styles. Most of the styles can be set or reset at runtime, wich means after the control has been added to the stage the first time.
Style management
The ASDPC style management is pretty easy to understand. Styles can be set directly to an object that defines that styles:
scrollBar.setSyle(ScrollBar.style.scrollButtonVisibility, false);
In composite structures (such as all controls are) you may set a sub component style also to the containing object:
treeView.setSyle(TreeNodeRenderer.style.indent, 24);
To work with styles it is then necessary to know:
- The structure of the control that should by styled
- The style properties of the control and of all its sub components
TreeView structure
The structure of a TreeView and all available styles are visualised in the info window of the demo application. Here again a short list of all sub components of a TreeView. Please refer to the APIDoc and to the source code to get informed about the particular styling possibilies of each sub component.
TreeNodeRenderer
ListItemBackgroundSkin
ConnectorContainer
Connector
DottedConnectorSkin
ListItemContent
Label
DirectoryIcon
DisclosureButton
ScrollBar
Button
ButtonSkin
ScrollButtonIconSkin
Track
ScrollTrackSkin
Thumb
ButtonSkin
ScrollThumbIconSkin
Style property definitions
Styles in the ASDPC library are always defined in the class, that use the style. The label font size is defined by the Label class. The button background color is defined by the ButtonSkin class, and the color of the scroll button triangle icon is defined by the ScrollButtonIconSkin class.
By convention, a style property name includes the name of the class, which it defines. E.g. the style property name for the visibility of the root node of the TreeView is “treeView_showRoot”. You do not know those constant values, since all style properties are available as ActionScript constants. The constant for the root node visibility is simply TreeView.style.showRoot. Style property constants are either defined in a separate style object or directly to the class, that use the style. Examples:
- Label color: Label.style.color
- List item height: ListView.style.itemSize
- Scroll button visibility: ScrollBar.style.scrollButtonVisibility
- Button background colors: ButtonSkin.style_backgroundColors
- Tooltip border color: ToolTipSkin.style_borderColor
Styling example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | package com.sibirjak.asdpc.treeview { import com.sibirjak.asdpc.common.Example; import com.sibirjak.asdpc.core.constants.Visibility; import com.sibirjak.asdpc.scrollbar.ScrollBar; import com.sibirjak.asdpc.treeview.renderer.ConnectorContainer; import com.sibirjak.asdpc.treeview.renderer.DisclosureButton; import com.sibirjak.asdpc.treeview.renderer.TreeNodeRenderer; import com.sibirjak.asdpc.treeview.renderer.skins.DisclosureButtonBoxIconSkin; /** * @author jes 04.02.2010 */ public class StylingExample extends Example { public function StylingExample() { var treeView : TreeView = new TreeView(); treeView.setSize(260, 125); treeView.expandNodeAt(0); treeView.dataSource = new XML( <item name="Root"> <item name="Node_1"> <item name="Node_1_1" /> <item name="Node_1_2" /> <item name="Node_1_3" /> </item> <item name="Node_2" /> </item> ); treeView.setStyles([ // item size TreeView.style.itemSize, 25, // scrollbar and button visibility TreeView.style.scrollBarVisibility, Visibility.VISIBLE, ScrollBar.style.scrollButtonVisibility, Visibility.VISIBLE, // box shaped disclosure button DisclosureButton.style_expandedIconSkin, DisclosureButtonBoxIconSkin, DisclosureButton.style_collapsedIconSkin, DisclosureButtonBoxIconSkin, DisclosureButton.style_size, 9, DisclosureButtonBoxIconSkin.style_fillColor, 0x000000, DisclosureButtonBoxIconSkin.style_iconColor, 0xFFFFFF, // connectors below button and icon ConnectorContainer.style_connectorAtButton, true, ConnectorContainer.style_connectorAtIcon, true, // list item indent TreeNodeRenderer.style.indent, 26, // list item colors TreeNodeRenderer.style.separator, true, TreeNodeRenderer.style.separatorColor, 0xDDDDDD, TreeNodeRenderer.style.evenIndexBackgroundColors, [0xFFFFFF, 0xEEEEEE], TreeNodeRenderer.style.oddIndexBackgroundColors, [0xFFFFFF, 0xEEEEEE], TreeNodeRenderer.style.overBackgroundColors, [0xDDDDDD, 0xBBBBBB], TreeNodeRenderer.style.selectedBackgroundColors, [0x666666, 0x999999], ]); addChild(treeView); } } } |
Setting custom icons
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | package com.sibirjak.asdpc.treeview { import com.sibirjak.asdpc.common.Example; import com.sibirjak.asdpc.treeview.renderer.DirectoryIcon; import com.sibirjak.asdpc.treeview.renderer.DisclosureButton; public class DynamicIconExample extends Example { [Embed(source="assets/plus.png")] private var _plus : Class; [Embed(source="assets/minus.png")] private var _minus : Class; [Embed(source="assets/document.png")] private var _document : Class; [Embed(source="assets/folder.png")] private var _folder : Class; [Embed(source="assets/folder_open.png")] private var _folder_open : Class; [Embed(source="assets/as.png")] private var _as : Class; [Embed(source="assets/html.png")] private var _html : Class; [Embed(source="assets/php.png")] private var _php : Class; [Embed(source="assets/pdf.png")] private var _pdf : Class; [Embed(source="assets/htdocs.png")] private var _htdocs : Class; [Embed(source="assets/htdocs_open.png")] private var _htdocs_open : Class; public function DynamicIconExample() { var treeView : TreeView = new TreeView(); treeView.dataSource = new XML( <folder name="C:\\"> <folder name="documents"> <file name="serialz.txt" /> <file name="asdoc.pdf" /> <file name="images.zip" /> </folder> <folder name="htdocs"> <file name="index.php" /> <file name="contact.html" /> <file name="popup.html" /> </folder> <file name="manual.pdf" /> <file name="asdpc.exe" /> </folder> ); // disclosure buttons treeView.setStyles([ DisclosureButton.style_collapsedIconSkin, _plus, DisclosureButton.style_expandedIconSkin, _minus, DisclosureButton.style_size, 16]); // default icons treeView.setStyles([ DirectoryIcon.style.branchClosedIconSkin, _folder, DirectoryIcon.style.branchOpenIconSkin, _folder_open, DirectoryIcon.style.leafIconSkin, _document ]); // dynamic icons var iconFunction : Function = function (data : TreeNodeData) : Class { var label : String = XML(data.item).attribute("name"); if (label.indexOf(".as") > -1) return _as; else if (label.indexOf(".php") > -1) return _php; else if (label.indexOf(".pdf") > -1) return _pdf; else if (label.indexOf(".html") > -1) return _html; else if (label.indexOf("htdocs") > -1) { if (data.isExpanded) return _htdocs_open; return _htdocs; } return null; // else use default icon }; treeView.setStyle(DirectoryIcon.style.iconSkinFunction, iconFunction); treeView.expandNodeAt(0); addChild(treeView); } } } |

RSS





29 Comments
Lukas
Great work! I have a problem though.
I want to change icons of the items depending on their data.
Could you tell me how can I style a specific item in the list? Something like myTreeView.getItemAt(4).setStyle(…) would be nice
Jens Struwe
I have added an example how to change the icon of a tree item. You have here 3 possibilities:
1. Change one or all of the default icons (branch, branch open, leaf)
2. Set custom icon depending on the current data
3. Set custom icon depending on the data and on the state of the node (open, closed, leaf)
Setting custom icons
Lukas
Thank you! These components are great – clean and easy to use (after you know how).
peter
hello, at thanks for your great work. i’m playing for a while but i don’t know how i can set up this navigation panel on the right side. could you explain the starting point? peter
peter
i think it’s the pinbar class, but what i want to do is the colorpicker and other tools in this panel without windows….
Lukas
Hi, how do I update the treeview icons? I end up with collapsing the entire tree and expanding it – but its messing up the scroll position. There is probably an easy way to do it, right?
Jens Struwe
@Peter, the PinBar component is not documented. You need to dig in the example code on your own.
@Lukas, the icons can be customized as described in the chapter Setting custom icons in this article.
Lukas
Thanks for the reply. I set the icons and they update OK when I scroll the tree or collapse the parent node. But how can I update the tree without clicking it?
Jens Struwe
Could you please post example code that does not work?
Jens Struwe
Lukas did send me an email with example code. The problem he encountered was that the internal state of a data item (within the data source structure) has been changed and the tree still did not reflect that change. The solution is to let the data item dispatch an ordinary Event.CHANGE event in all cases the tree should perform data item depending operations such as determining and refreshing the current icon or displaying and updating the item label.
Lukas
Hi Jens! In my case it was quite hard to change the data source structure. So I sticked to your other suggestion and used the ‘dirty’ way – assigned a new iconFunction to the style:
_tree.setStyle(DirectoryIcon.style.iconSkinFunction,
function(data: TreeNodeData):Class {
return iconFunction(data);
}
);
It’s not the optimal solution but works great as a global icon refresh.
Thanks for your support Jens!
Another thing – it would be nice if we could use the as3commons libraries instead of as3 libraries. It can get quite confusing to use org.as3commons.collections.framework.IDataProvider in one place and com.sibirjak.asdpc.core.dataprovider.IDataProvider in another.
Jens Struwe
The com.sibirjak.asdpc.core.dataprovider.IDataProvider is to be replaced by the as3commons one in the version 1 of this project.
Coming end of the year.
chen
Great Job, you are not only engineer, but artist also… hope to see the final version.
Ahmad Hawamdeh
Great Job, you are not only engineer, but artist also… please can u give me the FLA to see the components…best wishes….
Keith
Very nice work. One thing that seems problematic though is when the showroot property is set to false and use use expandNodeAt(0, true); The expected behavior I think would be for the root node to be at index 0, but instead the first child of the root node is considered 0. That makes it problematic to have all nodes expanded on first initialization, unless there is another way.
thx
Jens Struwe
There is a difference between the actual hierachical data source and the visible list of the tree view. While the data source might be hierarchical, the list is flat. Each item of the list can be accessed using an index. Setting
showRoot=falseconverts the data source into a flat list skipping the root node. It is then impossible to either collapse or expand the root node since the root node is not part of the flat list any longer. However, you may run a loop to expand all level 1 nodes:Keith
Still struggling with this. It seems that the value of the property numItems is 0, which makes no sense because there should be at least 2. I am assuming that this property changes based on how many in the tree hierarchy are visible? If so, then it’s value should be 2 because since the root node is hidden, the 2 nodes under that have child nodes, which are not expanded on the treeview’s creation. I do want these expanded though on the treeview’s creation.
Keith
I think the problem is in the fact that the downloaded src example is different than what is shown above. The interface in the top example uses com.sibirjak.asdpc.core.dataprovider.IDataProvider, which defines a numItems property. However, the src code does not use this property or the same interface, so how is this to be accomplished?
thx
Jens Struwe
Just made a quick check. The data of the TreeView is initialized not until the TreeView is added to the stage:
–
To expand the TreeView as you like, you should use a reverse loop over the children of your plain data source:
This works regardless whether the TreeView has been added to stage or not yet. Hope I could help.
Samir
Hello,
I have suggestions for the TreeView component based on the implementation on my last project.
1) The getter for listDataProvider should be set protected. I needed change it to protected when extending TreeView class to implement the following features for my project;
2) I’m working with an html/flash website and use the treeview as menu. A method like expandNodeAt that expands parent-wise. When the user click a node I save the node index path to expand the last node expanded/clicked treeview if the page is submited.
3) A proprerty like selectedNode : TreeNode. To get the TreeNode from selectedIndex I needed return listDataProvider.getNodeAt(selectedIndex);
4) the TreeNode should reference TreeNodeData through a property like nodeData or data.
Thank You
Edit by admin: Moved request to support forum.
Jens Struwe
Please post your feature request in the forum: https://sibirjak.tenderapp.com/discussions/
Keith
Hello,
Yes, that helped, thank you. I think some of the problem was that I was not waiting until the tree got added to stage before trying to access that property.
Keith Lee
Hi,
I started playing with the new AIR SDK & Flash Builder in CS5.5, and took my existing AS3 project and compiled it for an iPad. Oddly, the treeView is blank on that device. I modified the src code a bit so it would use embedded fonts, so I don’t think it is a missing font issue, since those same embedded fonts work else where in the program. I’ve not done any debugging yet, but was wondering if you know of anything that might cause this, since I’m wandering into unknown territory
.
Jens Struwe
Did you try device fonts?
Joe Shields
Hi,
I am still getting the onMouseDown warnings, was the core codebase ever updated to remove these warnings ?
I’m also getting a TextField.appendText() slow warning on Label.as (line 280)
tarek
Hi,
i would like to hide the icons at the left of each node and let buttons intact.
yakamoz
hi
how i align label text and icon to right ??
yakamoz
hi i start compile your sample , but dispatch this error
asdpc-0.4.1-snapshot-src\com\sibirjak\asdpc\core\managers\BindingManager.as, Line 71 1017: The definition of base class LinkedMap was not found.
how to resolve this error ?
Hyzhak
You have misprint. Instead of:
setSyle(
must be:
setStyle(
Thanks for awesome components!