Ultrashock Tutorials > Flash 8 > XML Portfolio Viewer  
 
by Jim Armstrong, 2112 FX::Singularity
Download Source Files 
 
XML Portfolio Viewer
 
 Introduction and Code Requirements
 Section 01: Layout XML  
 Section 02: Portfolio XML  
 Section 03: Architecture  
 Section 04: Preloading  
 Section 05: Error Handling  
 Section 06: pair & triple classes 
 Section 07: Observer-Observable Utility 

 Section 08: Style Manager 
 Section 09: Layout Items  
 Section 10: Custom Layout Classes  
 Section 11: Glyph Class  
 Section 12: Multi-dimensional Thumbnailer  
 Section 13: Model 
 Section 14: View 
 Section 15: Controller 
 Section 16: Suggestions for Improvement 

Layout Items

First and foremost, I will state that the current implementation of the LayoutItem class is a hack. As mentioned earlier, I don't want this project to move from a very long deconstruction to a book :) In order to reduce the total number of class files, it was expedient to lump together several areas of functionality into a single base LayoutItem class. I would not recommend this approach for larger production projects.

The 'base' layout components are graphics (MovieClip), Labels (TextField) and Buttons (MovieClip with button behavior). The type of basic component is indicated in the layout.xml file with the 'type' attribute of the <item> tag. Any component that is not one of the base types is considered custom. A custom component is associated with a class that extends LayoutItem. The class name is provided in the 'class' attribute of the <item> tag. Custom classes are discussed in the next section.

LayoutInterface

LayoutItem is a base class for layout components. The class needs to implement certain functionality in order to server as an Observer and receive style broadcasts. In order to ensure that LayoutItem and its subclasses provide the necessary functionality, LayoutItem implements a LayoutInterface, as shown below.

interface LayoutInterface
{
  // respond to style updates
  public function updateStyle(_s:StyleLayout):Void
  // an observer must have an accessible name property
  public function getName():String;
  // observer responds to notification from observed subject
  public function notify( _info:Object ):Void;
}

This interface ensures that a LayoutItem or its subclass can respond to notification from an ObservableObject and an update from a StyleLayout instance.

LayoutItem Properties

The LayoutItem class contains a number of properties common to basic layout elements and a small number of core variables,

// properties (some property changes trigger a notification)
private var __name:String;        // name of this component
private var __type:String;        // type of component
private var __x:Number;           // holding value for x-coordinate until init.
private var __y:Number;           // holding value for y-coordinate until init.
private var __xCenter:Boolean;    // true if x-coordinate is centered on Stage
private var __yCenter:Boolean;    // true if y-coordinate is centered on Stage
private var __width:Number;       // holding value for width until init.
private var __height:Number;      // holding value for height until init.
private var __linkage:String;     // linkage id for this item, if required
private var __xOffset:Number;     // x-offset, relative to observed component
private var __yOffset:Number;     // y-offset, relative to observed component
private var __align:String;       // horizontal alignment
private var __vAlign:String;      // vertical alignment
private var __label:String;       // component label or text
private var __html:Boolean;       // true if html is allowed 
private var __style:StyleLayout;  // style information for this component
// core
private var __observable:ObservableObject; // item is observable via composition
private var __component;                   // reference to viewable component
private var __init:Boolean;                // true if component has been initialized

All variables have private access as they are error-checked before assignment. The core variable set includes a reference to the ObservableObject class introduced in a previous section. This allows the LayoutItem to be observed by another LayoutItem.

The __component variable is an untyped reference to the viewable component in the Layout. For the current hack implementation, __component is a reference to a TextField or MovieClip in the base class.

The __init variable is used to flag whether or not the LayoutItem has been initialized. This is important in the setter functions for all LayoutItem properties. It is most likely that LayoutItem properties are set before the actual component is displayed on Stage. Instead of directly setting properties on __component, the property values are stored for later initialization. If the component is already created and displayed on Stage, then setting the property on __component is allowable.

Observers

The functions addObserver(), removeObserver(), clearObservers(), and notifyObservers() manage the process of having other LayoutItems observe the current instance. The first three methods exercise the corresponding method in the __observable instance.

LayoutItems can be both Observers or subjects. Whenever a property changes that affects the component's position or orientation on Stage, notifyObservers() is called to notify all registered Observers to alter their position.

Notice that setter functions that alter either position or size of the component call one of two private methods, __updatePosition() or __updateSize(),

private function __updateSize(_w:Number, _h:Number):Void
{
  if( __type != NONE )
  {
    __component._width  = _w;
    __component._height = _h;
  }
  __width  = _w;
  __height = _h;
  notifyObservers();
}
private function __updatePosition(_xC:Number, _yC:Number):Void
{
  // if the component is updated before init., it is undefined, 
  // so the only effect is to set the x- and y-coordinates for 
  // later initialization.
  if( __type != NONE )
  {
    __component._x = _xC;
    __component._y = _yC;
  }
  __x = _xC;
  __y = _yC;
  notifyObservers();
}

The notifyObservers() method is called from both __updatePosition() and __updateSize(). If the component is not yet initialized, __component is null or undefined, so the relevant property is stored for later initialization. When the component is finally placed on Stage, it is correctly positioned relative to the observed component -- provided you don't make the mistake of observing more than one component -:) In that case, only the last observation is relevant.

Responding to Notification From Other Components

As an Observer, LayoutItem must implement a notify() method to respond to broadcasts from other LayoutItems as a result of their calling notifyObservers(). The notify() method adjusts the LayoutItem's position according to alignment specifications,

public function notify(_info:Object):Void
{
  // test for circular access, i.e. make sure component is not observing itself
  if( _info.name != __name )
  {
    var newX:Number = 0;
    var newY:Number = 0;
    // use align/valign for base positioning, then adust with offsets
    if( __align == "left" )
      newX = _info.x + __xOffset;
    else if( __align == "right" )
      newX = _info.x + _info.width - __width + __xOffset;
    else if( __align == "stackright" )
      newX = _info.x + _info.width + __xOffset;
    else if( __align == "stackleft" )
      newX = _info.x - __width + __xOffset;
 
    if( __vAlign == "top" )
      newY = _info.y + __yOffset;
    else if( __vAlign == "bottom" )
      newY = _info.y + _info.height - __height + __yOffset;
    else if( __vAlign == "stackbottom" )
      newY = _info.y + _info.height + __yOffset;
    else if( __vAlign == "stacktop" )
      newY = _info.y - __height + __yOffset;
    __updatePosition( newX, newY );
  }
}

Since the __updatePosition() method automatically calls notifyObservers(), it is possible for a LayoutItem to be both an Observer and the subject. As mentioned earlier, the SYNOPSIS component observes the SCROLLER. The SYNOPSIS instance notify() method is called whenever the SCROLLER notifies its observers of a change. After adjusting its position, SYNOPSIS notifies its observers, which includes the PLAY button. The PLAY button immediately aligns with the newly positioned SYNOSIS component.

Responding To Style Notification

According to the LayoutInterface, LayoutItem must implement an updateStyle() method in order to process style notification from the StyleMgr class. The style notification may be received in advance of component initialization. In this case, a copy of the reference to the StyleInstance is stored. The internal reference is used during initialization. If the component has already been initialized, the style information is directly applied.

public function updateStyle(_s:StyleLayout):Void
{
  if( __init )
    __assignStyles(_s);
  else
    __style = _s;
}

Component Initialization

Initialization is performed in the init() method, whose signature is

public function init( _mc:MovieClip, _instance:String, _depth:Number):Void

The init() method receives a reference to the parent clip, instance name, and depth as arguments. Based on the type of LayoutItem, either a MovieClip, TextField, or MovieClip with button behaviors is created.

The layout component is initially created with visibility turned off. It is up to the calling program (the View) to turn on visibility using the show() method.

Now that we can create basic layout items or components, what about more sophisticated, custom items?

 
©2006 Ultrashock.com - All rights reserved