Flash Doctors Dose User Guide

Jonathan Doklovic

Revision History
Revision 1.0 DRAFT10/22/2006jd

Initial version of this document.

Flash Doctors Dose User Guide

Dose is a set of actionscript objects that are used to represent a foundation of GUI concepts


Table of Contents

1. What is Dose?
Description
What's It Good For?
What's it do?
2. Working With Displayables
What is a Displayable?
Asset Injection
Moving Displayables
3. Working With LayoutManagers
LayoutManager Basics
Using LinearLayoutManager
Alignment with LayoutManagers.
4. Working with Groups
TabGroups (temp for JT)

List of Examples

2.1. Creating a displayable and setting it's stage asset
2.2. Creating a displayable and setting it's stage asset by name
2.3. Creating a displayable and dynamically generating it's stage asset
2.4. Creating a displayable and dynamically generating it's stage asset with a container
2.5. Nesting displayable stage assets
2.6. Loading an asset into a displayable
2.7. Creating a displayable and attaching it's stage asset
2.8. Moving a displayable
3.1. Simple Horizontal Layout with LinearLayoutManager
3.2. Simple Horizontal Layout with LinearLayoutManager
3.3. Horizontal Alignment with LinearLayoutManager
4.1. Creating and Displaying a TabGroup

Chapter 1. What is Dose?

Description

Dose can be described as a package of objects that represent low level GUI concepts. It is used as the foundation on which complex, highly designed GUI applications can be built. Dose is *not* a component library and should not be confused with the macromedia/adobe component library or any other third-party component library.

Dose provides very simple, yet powerful interfaces that, when used together, can accomplish complex GUI scenarios. At the heart of dose are the IDisplayable and the IMouseable interfaces. (described later). Apart from the actionscript code, Dose makes use of very simple "templates" that are basically MovieClips and/or fla files with named frames.

What's It Good For?

Because dose is not a component framework, it's not meant to be used to create reusable components that can be compiled as swc files and dropped into the components palette inside of the FlashIDE. Instead dose was created to facilitate the creation of highly designed, custom user interfaces.

The easiest way to describe this is by using a simple button metaphor: in dose anything can be a button. This is because in dose, a button is simply something that can be displayed and interacted with using a mouse. This leaves the actual design of the "button" up to the designer... it could be a photo, a line, an entire animation, etc. Dose decouples the functionality from the design, leaving a designer complete freedom while providing the developer a standard way to handle functionality.

What's it do?

Nothing. (for the most-part)... Because every application is different and has different needs when it comes to functionality (even on a component level) dose only implements the bare minimum functionality it needs to work at a low level. However, dose provides methods for adding any ICommands (see ReflexUsersGuide) to objects when it makes sense. Essentially, this allows the developer to only have to concentrate on what the UI objects are actually trying to accomplish instead of the mechanism that makes them work. This will be described throughout the documentation where applicable.

Chapter 2. Working With Displayables

What is a Displayable?

By itself, dose cannot and does not create or display GUI components directly, instead it wraps movie clips and other displayable entities to provide their GUI functionality. Another way to think about this is "Asset Injection", meaning the actual assets are "injected" into dose objects which in turn can provide functionality to the assets.

This brings us to the concept of "displayables". A displayable is any dose object that can have a visible stage asset injected into it. Displayables are the basis for all visible GUI objects in dose and every displayable dose object implements the IDisplayable interface.

An AbstractDisplayable class is provided, which all displayables should extend, as well as a Displayable concrete class that can be used for most simple assets. There are a couple of other abstract and concrete displayable classes that will be described later.

Asset Injection

Injecting assets into a displayable is pretty easy and can be done multiple ways:

  • Simply set the asset MovieClip with a setter

  • Set the asset using it's instance name

  • Dynamically create a named placeholder clip and load an asset into it

  • Attach the asset using it's linkageID

Injecting the asset with a setter is the simplest way to inject an asset. To do this, you just need an asset on the stage.

Example 2.1. Creating a displayable and setting it's stage asset

var disp:IDisplayable = new Displayable();
disp.setName("myDisplayable");
disp.setStageAsset(_root.someClip);

Injecting the asset using it's instance name is just as easy. To do this you just need a named asset on the stage.

Example 2.2. Creating a displayable and setting it's stage asset by name

var disp:IDisplayable = new Displayable();
disp.setName("myDisplayable");
disp.setStageAssetByName("myInstanceName");

Injecting the asset by creating a named placeholder and loading an asset into it is a bit more tricky, but not much. First, we need to create the place holder clip. This can be done by calling getStageAsset() on any displayable that has not yet had an asset injected into it. When getStageAsset() is called, it checks to see if the displayable's asset is null, if it is, an empty MovieClip is created and named using the displayable's name property.

Example 2.3. Creating a displayable and dynamically generating it's stage asset

var disp:IDisplayable = new Displayable();
disp.setName("myDisplayable");
var myMC:MovieClip = disp.getStageAsset();

trace(myMC); 
//traces: _level0.myDisplayable

That was pretty easy, but suppose you need to nest your displayable's stage asset under another clip or a mask. This is where the setContainer() method comes in. A displayable's setContainer() method can be called before calling getStageAsset() to set the path to the generated MovieClip. The string passed to the setContainer method should not include _root or _level0 as it's assumed. Be aware that if the container path passed to setContainer does not exist at the time getStageAsset() is called, the container will default to _level0;

Example 2.4. Creating a displayable and dynamically generating it's stage asset with a container

var disp:IDisplayable = new Displayable();
disp.setName("myDisplayable");
disp.setContainer("clip1.mask");
var myMC:MovieClip = disp.getStageAsset();
          
trace(myMC); 
//traces: _level0.clip1.mask.myDisplayable

The next example shows how displayable assets can be nested.

Example 2.5. Nesting displayable stage assets

var disp1:IDisplayable = new Displayable();
disp1.setName("myDisp1");
var myMC1:MovieClip = disp.getStageAsset();

disp2:Displayable = new Displayable();
disp2.setName("myDisp2");
disp2.setContainer("myDisp1");
var myMC2:MovieClip = disp2.getStageAsset();

var disp3:IDisplayable = new Displayable();
disp3.setName("myDisp3");
disp3.setContainer("myDisp1.myDisp2");
var myMC3:MovieClip = disp3.getStageAsset();         

trace(myMC1); 
//traces: _level0.myDisp1

trace(myMC2); 
//traces: _level0.myDisp1.myDisp2
          
trace(myMC3); 
//traces: _level0.myDisp1.myDisp2.myDisp3

From here, loading the asset into the displayable is just a matter of calling loadMovie() However, we suggest using the FlashDoctors net package, or better yet, the net package with Syringe.

Example 2.6. Loading an asset into a displayable

var disp:IDisplayable = new Displayable();
disp.setName("myDisplayable");
disp.setContainer("clip1.mask");
var myMC:MovieClip = disp.getStageAsset();
myMC.loadMovie("myAsset.swf");

Injecting the asset using it's linkageID is also very easy. To do this, you just need an asset in the library with a linkageID set. When the setStageAssetByLinkage is called, it uses the container value as the parent MovieClip and uses the name value as the name for the new clip.

Example 2.7. Creating a displayable and attaching it's stage asset

var disp:IDisplayable = new Displayable();
disp.setName("myDisplayable");
disp.setStageAssetByLinkage("myLinkageID");

trace(disp.getStageAsset());
//traces: _level0.myDisplayable.myLinkageID

Moving Displayables

Now that we can get assets into displayables the only thing left is to move the displayable. This is simply done by setting the x and y properties of the displayable.

Example 2.8. Moving a displayable

var disp:IDisplayable = new Displayable();
disp.setName("myDisplayable");
disp.setStageAsset(_root.myClip);
disp.setX(10);
disp.setY(20);

When the x and y properties are set on the displayable, the stage asset is moved immediately. This is important to note because when setX() and setY() are called, they make a call to getStageAsset(). This means that if setX() or setY() is called before a stage asset is set, the displayable will auto generate the asset based on the displayable's name. Care should be taken to make sure setContainer() is called (if needed) before calling setX() or setY().

Chapter 3. Working With LayoutManagers

LayoutManager Basics

Although any displayable object in dose can be positioned simply by setting it's x and y properties, layout managers provide an easy yet powerful way to layout entire applications or sections of applications. All layout managers implement the ILayoutManager interface and should extend AbstractLayoutManager.

In general, layout managers take a List of IDisplayables, and a starting position. The starting position is set simply by calling the layout manager's setX() and setY() methods. From there the calculateLayout() method can be called which will return a Layout object which can be looped through to get the end positions of all of the IDisplayables. Although this may be useful in some cases, it's more common to just call the layoutItems() method which will calculate the layout and also position all of the IDisplayables immediately. Keep in mind that the x and y properties are relative to any containers the items may be within.

Dose provides two concrete implementations of ILayoutManager: LinearLayoutManager and StackedLayoutManager

Using LinearLayoutManager

The LinearLayoutManager class is used to layout IDisplayables either horizontally or vertically with equal spacing between each item. To set which type of layout is to be used we simply call the setType() method and pass it one of the type constants: LinearLayoutManager.HORIZONTAL or LinearLayoutManager.VERTICAL (as a shortcut for syringe users, the previous can also be passed in as strings "H" or "V"). If no type is set on the layout manager it defaults to horizontal. The amount of spacing between each item in pixels is set by calling the setSpacing() method. The LinearLayoutManager also has options for setting the horizontal and vertical alignments of the layout which will be discussed later.

Example 3.1. Simple Horizontal Layout with LinearLayoutManager

var disp1:IDisplayable = new Displayable();
disp1.setName("myDisp1");
disp1.setStageAsset(_root.myClip1);

var disp2:IDisplayable = new Displayable();
disp2.setName("myDisp2");
disp2.setStageAsset(_root.myClip2);

var disp3:IDisplayable = new Displayable();
disp3.setName("myDisp3");
disp3.setStageAsset(_root.myClip3);

var layoutMan:LinearLayoutManager = new LinearLayoutManager();
layoutMan.addItem(disp1);
layoutMan.addItem(disp2);
layoutMan.addItem(disp3);
layoutMan.setX(10);
layoutMan.setY(10);
layoutMan.setSpacing(2);
layoutMan.layoutItems();

        

Laying out items vertically is exactly the same with the exception of setting the type of layout.

Example 3.2. Simple Horizontal Layout with LinearLayoutManager

//create displayables
...

var layoutMan:LinearLayoutManager = new LinearLayoutManager();
layoutMan.setType(LinearLayoutManager.VERTICAL);
layoutMan.addItem(disp1);
layoutMan.addItem(disp2);
layoutMan.addItem(disp3);
layoutMan.setX(10);
layoutMan.setY(10);
layoutMan.setSpacing(2);
layoutMan.layoutItems();



Alignment with LayoutManagers.

As mentioned before, there are also options for setting the alignment of items. This is done through the setHalign() and setValign() methods. The possible alignment options are listed below and have different results depending on the type of the layout manager.

  • LinearLayoutManager.LEFT

  • LinearLayoutManager.RIGHT

  • LinearLayoutManager.CENTER

  • LinearLayoutManager.TOP

  • LinearLayoutManager.BOTTOM

(as a shortcut for syringe users, the above can also be passed as strings: "L","R","C","T" or "B")

The haligh and valign properties are used together to set both the build order and the baseline for the layout manager. When working with type HORIZONTAL the halign sets the builder order and the valign sets the baseline, visa-versa for type VERTICAL.

The build order dictates if the items should be layed out from the beginning or the end of the list as well as if the position set via the x/y properties should be used as the starting or ending position. For HORIZONTAL, halign LEFT assumes the position is the starting position and the items should be layed out beginning to end. RIGHT has the opposite effect. For VERTICAL, TOP and BOTTOM are used in the same way.

Example 3.3. Horizontal Alignment with LinearLayoutManager

//create layoutmanager and add displayables to it here
...
layoutMan.setType(LinearLayoutManager.HORIZONTAL);
layoutMan.setX(0);
layoutMan.setHalign(LinearLayoutManager.LEFT);
layoutMan.layoutItems();

//or to align right
layoutMan.setType(LinearLayoutManager.HORIZONTAL);
layoutMan.setX(100);
layoutMan.setHalign(LinearLayoutManager.RIGHT);
layoutMan.layoutItems();

        

Chapter 4. Working with Groups

Table of Contents

TabGroups (temp for JT)

TabGroups (temp for JT)

A TabGroup extends AbstractGroup and Implements IGroup. AbstractGroup defaults to using a LinearLayoutManager in HORIZONTAL mode, but can be overridden by calling setLayoutManager.

All groups accept IGroupable objects via addItem() or setItems(). Whenever setLayoutManager(), setItems(), or addItem() is called on the group, the items are automatically added to the group's layout manager. TabGroup exists because it automatically adds the basic mouse interaction commands to each TabButton when it is added to the group.

Every TabButton stage asset should be built following the TabButton movie template. This is simply any movie clip with the following named frames: "disabled", "over", "off", "down", "active". The frame following each of these named frames (or at the end of the state change animation) should have and action frame that includes stop(); This is due to the fact that Dose uses gotoAndPlay(stateFrame) when changing the states of a button. Also, "disabled" should always be the first named frame so that assets are defaulted to the disabled state.

Example 4.1. Creating and Displaying a TabGroup

var btn1:IDisplayable = new TabButton();
btn1.setName("btn1");
btn1.setX(-100); //set the x so the asset loads off stage
//use above docs to load in the stage asset
...
//repeat for n buttons
...

//create our tabgroup
var tg:TabGroup = new TabGroup();
//tell it where to start drawing
var lm:LinearLayoutManager = LinearLayoutManager(tg.getLayoutManager);
lm.setX(10);
lm.setY(10);
lm.setSpacing(2);
tg.addItem(IGroupable(btn1));
tg.addItem(IGroupable(btn1));
tg.addItem(IGroupable(btn1));

//tell the layoutmanager to layout the items
lm.layoutItems();

//in syringe, you can use inner beans/lists to set the tabs to the group
//the order in which tabs are added to the group are the order in which they display

/* syringe use:
<bean id="tabGroup" class="com.flashdoctors.dose.ui.group.TabGroup">
  <property name="layoutManager">
    <bean class="com.flashdoctors.dose.ui.layout.LinearLayoutManager">
      <property name="x" value="10"/>
      <property name="y" value="10"/>
      <property name="spacing" value="2"/>
    </bean>
  </property>
  <property name="items">
    <list>
      <ref bean="btn1"/>
      <ref bean="btn2"/>
      <ref bean="btn3"/>
    </list>
  </property>
</bean>
*/