Tag Archive for 'custom components'

The BetterTitleWindow Component: A better way to customize title bars

It's pretty common to need to put a button or some other component into the title bar of a Panel or TitleWindow component (I'm going to refer to both of these components as Panel components since they are nearly the same). The Flex Panel components don't provide any support for this, but it can be done by subclassing, overriding the createChildren method, and adding code to insert components into the titleBar UIComponent. (This technique is explained here and many other places.)

But it seems silly to have to create a new subclass for each different button or other component that you need to add to a panel. And this basic technique doesn't allow you to make any modifications to the title bar on the fly. It recently occurred to me that it would be really handy if title bars were handled just like the ControlBar component--as a container tag that you can put inside your Panel and then everything inside of it will automatically be placed in the proper location at the top of the Panel.

So... I created the BetterTitleWindow component which does exactly that. Here's some mxml illustrating its usage:

It's pretty simple. Just put the TitleBar tag inside the BetterTitleWindow and add any components you need inside the TitleBar. TitleBar is nothing more than an HBox, so as you can see in the example, you can set all of the usual HBox padding and alignment styles for controlling its layout. The TitleBar instance is then accessible through the titleBarContainer property of BetterTitleWindow, so you can add more components or change styles or anything else at runtime. Here's a small sample app that demonstrates this capability:

You can also download the project from our svn repository.

Comment

The TreeBrowser Component: Mac OS X – style column view for Flex

I've always been a big fan of the column view in the Mac OS X Finder (and earlier on NeXT OS). It's a clear, intuitive way to navigate through hierarchical data, particularly when that data is nested many levels deep. For a while I've been wanting to create a generic Flex component to display data column-style, but I've never managed to set aside the time to do it... until now!

The TreeBrowser component can be used anywhere the standard Tree component can. Like Tree, it supports displaying data from xml and basic nested object stuctures by default, and you can set a custom data descriptor to display any other kind of complex data (more info on data descriptors can be found here). By default it uses the same folder and document icons as Tree, and style settings can be used to set custom icon classes. It also has iconFunction and iconField properties for setting icons on an object-by-object basis. Each column in the component is a standard Flex List, and the style of the columns can be set to customize their appearance.

The TreeBrowser can also optionally display a "details" pane that shows information about the currently selected leaf node of the tree. If enabled, the details pane defaults to a simple two column DataGrid displaying the name and value of each property of the selected object. A custom detailRenderer can be set to show information tailored to a particular kind of object or usage of the TreeBrowser.

Here's a source-enabled example showing usage of the TreeBrowser to navigate XML data. This example also uses the excellent flexmdi framework to demonstrate how TreeBrowser components behave when resized. The three buttons at the top will open windows with or without the details pane, or with a custom detailRenderer.

You can also download the project from our svn repository.

TreeBrowser API Documentation can be found here.

And be sure to let us know if you find any interesting uses for this component...

18 Comments

ActionScript 3 value object generator

It seems every time I start a new project there is always a period of time before the server side and the client side logic begin working in sync. In this post I will present a little tool I created for our last project. The task of this tool is to convert value objects or transfer object (VOs/TOs) from XML into ActionScript. I found it really useful in getting the project off the ground as it allowed the ui team to start creating the interface and using actual tos before the server side was ready to go. Applying the service locator pattern to the service layer allows one to easily switch from XML service implementation to the real services.

In the rest of post I refer to the objects being parsed as TOs or transfer objects. The distinction between a transfer object and a value object is that the latter might contain not only data but also perform some logic as well. Transfer objects simply facilitate the moving of data between the backend and the frontend. They do not perform any logic at all. Now let's start parsing some TOs.

To get the parser going we need to follow several simple steps. First, create an XML file containing the TOs' mock data. Second, setup the parser with the correct directory structure and files. Last, invoke the parser. Here I just use a simple test program to invoke the parser. In a real project you would want to create a separate XML implementation for your services and call the parser from each service.

Before getting started with the parser we need to create a XML file. For our example I'll use 3 classes a UserTO class, a AddressTO class and a RoleTO class. Here is the users.xml file that is to be parsed.

A few things to note about the syntax of the XML file. Each class is contained in a <Class> tag. The type attribute specifies the type of the object. A tag without the type attribute is considered to be a String. The ref tag specifies that the details of the class are located in another file.

After the XML file we need to create TO classes to instantiate and populate with data. These are UserTO.as, AddressTO and RoleTO.as. Since they contain just getters and setters I have omitted the code but you can download the source code from 9mmedia's svn.

So we have our XML ready and our TO objects ready to get populated with data. The last step remaining is to setup the parser. We do this in the XmlToParserConfig.as file. Here is how it's done:

Make sure that the toPackage property is pointing to the correct folder where the TOs are stored and that xmlDirectory is pointing to the folder with the xml files. Also note that all classes you define have to be included in the XmlToParserConfig.createInstances() method. All files need to be referenced at least once so that they are included in the swf. The XmlToParserConfig is passed to the constructor of the XmlToParser as you can see below.

The last step remaining is to run the parser.

Once the file finishes parsing onParseComplete is executed and the users collection is populated with 2 UserTO objects.

You can find the source code in the 9mmedia public svn repository located here.

Certainly there are other ways to accomplish the task of getting the frontend up and running. I have found that using the XmlToParser is an easy way to get a project off the ground quickly without a functioning backend. The greatest part about it being that the switch from mock to real data can be made at anytime in the service locator. Depending on the particular implementation one could set each service individually to use real or mock data.

Comments

Reusable Components using PureMVC

So a while ago we promised to discuss the capabilities of PureMVC mediators and proxies in creating reusable components. But this week an update to the framework makes it easier than ever to use dynamic naming conventions.

Our main beef with the mediators in the last post was that it was inconvenient to name them dynamically as we had to come up with a workaround similar to what was implemented in the proxies.
For any of you not familiar, proxies and mediators are retrieved by name, making it necessary to have unique names for each mediator. The Proxy class lets you supply a unique name:

The Mediator class previously lacked this same naming solution so we had to come up with our own similar way of assigning it:

But now has been updated to include a name as a parameter in the constructor, rendering our solution unneeded. So how does this affect our reusable components you say? Well, we have realized that creating and displaying multiple instances of the same component on screen at the same time requires a little finesse.

First of all, we had to take advantage of using the dynamic names for both mediators and proxies for our component. We based their names on the uid of the viewComponent.
So for example, we often have viewComponents whose uid is something along the lines of Canvas10.ModuleLoader33.Module85, therefore our mediator would be named
Canvas10.ModuleLoader33.Module85Mediator and our proxy would be named Canvas10.ModuleLoader33.Module85Proxy.
This leads to being able to retrieve the mediator and proxy from anywhere that has access to the viewComponent by simply using the following:

Once the mediator and proxy were both established for the component, we thought all was smooth sailing. Until we started listening to notifications and realized that every copy of the component received them no matter which one requested the action.
In other words, component1, component2, and component3 are all of type OurCustomComponent. Component1 calls a method in the proxy and listens for a notification back that it is finished loading data.
Component1 receives the notification, but so do component2 and component3 that also have the notification listed in listNotificationInterests. So how to tell the difference when receiving notifications?

Simple, we used the type property on each notification. We set the type to the mediatorName that was passed from the mediator to the proxy.

Then the proxy made calls to the service to save data and when it finished, it returned the mediatorName as the type in the notification.

Then when the mediator gets the notification back in handleNotification, we check to see if the type matches the name of the mediator. If it does, the notification is meant to be received by this instance of the mediator, if not it is discarded.

Comments

Drag And Drop Markers Made Easy

While the basics of creating drag-and-drop functionality in Flex are easily implemented through the DragManager, there are some important details that aren't handled for you, especially if you are using custom components (as opposed to using the built-in list-based components). For example, it's often useful to display a visual indicator of where the object being dragged will be inserted when released. Here at 9mmedia we've needed to do this on several occasions for things like visual editing tools. To facilitate this, we created a simple container component called DragMarkerBox that provides the marker functionality for any objects that are dragged inside of it.

Working Example:
http://www.9mmedia.com/examples/dragmarkerexample
Get the code:
http://code.9mmedia.com/svn/public/DragMarkerExample

The basic usage of the component is extremely simple; since it extends the Box container class, you use in the same way you would an HBox or VBox. One slight catch is that the container needs to have a backgroundColor specified, otherwise too many mouse events get fired when dragging over the items in the DragMarkerBox and the marker will flicker and appear jittery.

	<dragmarkerbox:DragMarkerVBox id="leftMarkerBox" backgroundColor="#ffffff">
		<DragItem itemLabel="1"/>
		<DragItem itemLabel="2"/>
		<DragItem itemLabel="3"/>
		<DragItem itemLabel="4"/>
		<DragItem itemLabel="5"/>
	</dragmarkerbox:DragMarkerVBox>

Note that the DragMarkerbox container doesn't automatically make the objects it contains draggable; it's up to the objects themselves to call DragManager.doDrag and begin the drag operation. Once dragging has started, however, DragMarkerBox will track the mouse position in relation to the objects being dragged over and display a marker either before or after the object currently under the mouse. When the item is dropped, DragMarkerBox will dispatch a DragMarkerEvent containing the DragSource and the position where the drop occurred.

There is a default marker component included, but you can customize the appearance of the marker by specifying your own markerFactory.

If you want to restrict the objects that can be dropped inside of the DragMarkerBox, you can specify an acceptFunction that will be used to evaluate whether a dragged object should be accepted as a valid drag action. If the object is not accepted, the drag marker will not display, and no DragMarkerEvent will be dispatched on mouse release. The acceptFunction should be defined as a function that takes one argument (the object being dragged) and returns a boolean value.

That's pretty much all there is to using the component. It's simple, but can be used in some powerful ways. You can nest as many levels of these containers as you want, and mix horizontal and vertical orientations.

Comments