Essential ActionScript 2.0

 <  Day Day Up  >  

7.4 Autosizing the Image Viewer

Well, that was so easy we may as well have a little more fun. Now that our ImageViewerDeluxe class supports resizing, let's add the ability to automatically resize the viewer to fit the size of any loaded image.

To set the size of the viewer when an image loads, we'll override the ImageViewer class's onLoadInit( ) method. From the ImageViewerDeluxe version of the method, we'll check the size of the loaded image and then use our handy new setSize( ) method to resize the viewer to those dimensions. We'll also use super( ) to invoke the overridden version of onLoadInit( ) so that the original behavior of the method is preserved. Here is the absolute quick-and-dirtiest way to add the new autosize feature:

public function onLoadInit (target:MovieClip):Void { super.onLoadInit(target); setSize(container_mc.image_mc._width, container_mc.image_mc._height); }

Admittedly, that code works, but it's inflexible . For starters, every ImageViewerDeluxe instance created will resize itself when it loads an image. That should be optional, not mandatory. Furthermore, as we saw when we implemented setSize( ) , it often pays to break up functionality into discrete methods , each of which can be accessed selectively by users of the class. Let's reexamine the autosize feature to see how it can be broken up.

First, we want the autosize feature to be optional, so we need a new Boolean property, showFullImage , which indicates whether the viewer should autosize ( true ) or not ( false ). The showFullImage property should be private , and should be set and retrieved via accessor methods: getShowFullImage( ) and setShowFullImage( ) .

Next, it's likely that an ImageViewerDeluxe user would want to use our autosize feature even after an image loads. For example, an interface might provide a button to reveal the entire image. Given that we're building autosize functionality already, it's sensible to offer this feature in a separate method: scaleViewerToImage( ) .

Finally, consider what the scaleViewerToImage( ) method does: it checks the width and height of the image in the viewer and sets the viewer's size to those dimensions. Checking the width and height of the image in the viewer is useful in and of itself. For example, if the viewer is used as part of a dynamic interface that automatically adjusts itself to the viewer's size, the creator of that interface will need some way to retrieve the viewer's dimensions. Hence, we should create public methods that return the width and height of the image in the viewer: getImageWidth( ) and getImageHeight( ) .

Let's see how this all plays out in code.

First, here's our showFullImage property definition. The property defaults to false (don't autosize).

private var showFullImage:Boolean = false;

Next, here are the accessor methods for showFullImage :

public function setShowFullImage(show:Boolean):Void { showFullImage = show; } public function getShowFullImage( ):Boolean { return showFullImage; }

The getImageWidth( ) and getImageHeight( ) methods are equally simple. They simply return the _width and _height of the image_mc movie clip. Recall that container_mc is an instance property defined by the ImageViewer class and that image_mc is a movie clip ”nested within container_mc ”that contains the current loaded image.

public function getImageWidth ( ):Number { return container_mc.image_mc._width; } public function getImageHeight ( ):Number { return container_mc.image_mc._height; }

Finally, here's the scaleViewerToImage( ) method. It uses getImageWidth( ) and getImageHeight( ) to determine the new size of the viewer.

public function scaleViewerToImage ( ):Void { setSize(getImageWidth( ), getImageHeight( )); }

Now we can return to our onLoadInit( ) method, where the viewer does its autosizing. Recall what the quick-and-dirty version looked like:

public function onLoadInit (target:MovieClip):Void { super.onLoadInit(target); setSize(container_mc.image_mc._width, container_mc.image_mc._height); }

Here's the revised version, which autosizes only if the viewer's autosize feature is turned on (i.e., if showFullImage is true ):

public function onLoadInit (target:MovieClip):Void { super.onLoadInit(target); if (showFullImage) { scaleViewerToImage( ); } }

Notice how compact and readable the method is now that the autosize functionality is separated into distinct methods. The autosize feature is now optional, and we've exposed new methods to retrieve the image dimensions and arbitrarily resize the viewer to fit the image it's displaying. Great stuff!

It's easy to get carried away with adding new features. In most real-world cases, features should be added only to satisfy some specific requirement. The wisdom of the Extreme Programming methodology applies here: never add functionality early.

More functionality means more code complexity, which translates into more development and maintenance time. In our autosize example, we posed scenarios that made extra functionality a requirement. If the real-world case had no such requirement, breaking our autosize feature up into separate methods would not have been wise.

Example 7-3 shows the final code for the ImageViewerDeluxe class. Update your code in ImageViewerDeluxe.as to match the example (changes from Example 7-2 shown in bold).

Example 7-3. The ImageViewerDeluxe class, final version

/** * An ImageViewer that can be repositioned and resized after it is created */ class ImageViewerDeluxe extends ImageViewer { // Flag indicating whether the viewer should be // scaled to match the size of the image. private var showFullImage:Boolean = false; public function ImageViewerDeluxe (target:MovieClip, depth:Number, x:Number, y:Number, w:Number, h:Number, borderThickness:Number, borderColor:Number) { super(target, depth, x, y, w, h, borderThickness, borderColor); } /** * Sets the position of the viewer. * * @param x The new horizontal position of the viewer. * @param y The new vertical position of the viewer. */ public function setPosition (x:Number, y:Number):Void { container_mc._x = x; container_mc._y = y; } /** * Sets the size of the viewer (i.e., adjusts the * border and mask size). * * @param w The new width of the viewer, in pixels. * @param h The new height of the viewer, in pixels. */ public function setSize (w:Number, h:Number):Void { createImageClipMask(w, h); createBorder(w, h); container_mc.image_mc.setMask(container_mc.mask_mc); } /** * Returns the width of the clip that contains the image. */ public function getImageWidth ( ):Number { return container_mc.image_mc._width; } /** * Returns the height of the clip that contains the image. */ public function getImageHeight ( ):Number { return container_mc.image_mc._height; } /** * Set flag indicating whether the entire image should be * displayed or the image should be cropped to fit the viewer. * * @param show A flag indicating whether the viewer should be * scaled to match the size of the image. */ public function setShowFullImage(show:Boolean):Void { showFullImage = show; } /** * Returns flag indicating whether the entire image should be * displayed or the image should be cropped to fit the viewer. */ public function getShowFullImage( ):Boolean { return showFullImage; } /** * Adjusts the size of the viewer so that the entire * image is visible. */ public function scaleViewerToImage ( ):Void { setSize(getImageWidth( ), getImageHeight( )); } /** * MovieClipLoader handler. Triggered by imageLoader when loading is done. * Overrides ImageViewer.onLoadInit( ) , adding autosizing feature. */ public function onLoadInit (target:MovieClip):Void { super.onLoadInit(target); if (showFullImage) { scaleViewerToImage( ); } } }

 <  Day Day Up  >  

Категории