Save Image As… now as a separate tag
James Ward created a clever way of adding a “Save Image As…” feature to an image in Flex.
However clever, in my case I really wanted to avoid having to subclass the Image class specifically, so I created an MXML tag which would take the Image instance as an argument instead.
The source code looks like this…
package org.hello.saveimageas
{
import flash.events.ContextMenuEvent;
import flash.net.FileReference;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.ByteArray;
import mx.controls.Image;
import mx.core.IMXMLObject;
public class SaveImageAs implements IMXMLObject
{
private var _target:Image;
private var _label:String = "Save Image As...";
public function SaveImageAs()
{
super();
}
public function initialized(document:Object, id:String):void
{
// empty for now
}
protected function saveImageAs( event:ContextMenuEvent ) : void
{
var tba:ByteArray = new ByteArray();
this.target.content.loaderInfo.bytes.readBytes(tba, 0, ( this.target.content.loaderInfo.bytes.length - 17 ) );
tba.position = 49;
var ba:ByteArray = new ByteArray();
while (tba.bytesAvailable)
{
ba.writeByte(tba.readUnsignedByte());
}
var fr:FileReference = new FileReference();
fr.save( ba, this.target.source.toString() );
}
[Bindable]
public function get target() : Image
{
return this._target;
}
public function set target( value:Image ) : void
{
this._target = value;
if( this.target != null )
{
var targetContextMenu:ContextMenu = this.target.contextMenu != null ? this.target.contextMenu : new ContextMenu();
targetContextMenu.hideBuiltInItems();
var item:ContextMenuItem = new ContextMenuItem( this.label );
targetContextMenu.customItems.push(item);
item.addEventListener( ContextMenuEvent.MENU_ITEM_SELECT, saveImageAs );
this.target.contextMenu = targetContextMenu;
}
}
[Bindable]
public function get label() : String
{
return this._label;
}
public function set label( value:String ) : void
{
this._label = value;
}
}
}
A basic usage of it could look something like this…
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" xmlns:saveimageas="org.hello.saveimageas.*">
<mx:Image id="image" source="http://www.motorscooterguide.net/Pictures/cy50jog_black.jpg" />
<fx:Declarations>
<saveimageas:SaveImageAs target="{ this.image }" />
</fx:Declarations>
</s:Application>
Be sure to check out the original implementation by James Ward… it might suite your needs better…
http://www.jamesward.com/blog/2009/07/09/flex-example-right-click-save-image-as/
Thomas Burleson has already cornered this approach – as “Flex Behavior Injection”… check it out…
http://www.gridlinked.info/flex-behavior-injection/
The above modification to James Wards’ original contribution has been added to the “unsponsored” framework from where you can obtain it via SVN…
http://code.google.com/p/unsponsored/
Google Wave… likely now not waporware, and now with an AS API
Google Wave will now suddenly not become waporware… I never thought it would, however lots or credible people have spoken about the chance that Google Wave would either never see the day of light or if then, only for a short time.
If you want to get started with utilizing the Google Wave API’s and like I am currently, mostly building systems based on ActionScript and Flex, you don’t need to start implementing your own delegate API Google’s API, a couple of guys from the Google Developer Community has created a simple ActionScript implementation already.
Check it out…
http://code.google.com/p/wave-as-client/
A couple of notes…
* it uses ExternalInterface to call the actual JavaScript implementation (so no new communication logic)
* its released on the Apache License
* its very recent and active (last commit at the time of this post was 28 hrs ago)
A fun way to open a native window in AIR with MATE
Sometimes when coding it happens that you stumble on something which just strikes you as funny (sometimes for apparently no reason whatsoever).
One such experience happened today when I was coding an AIR client with MATE and I had to open a new NativeWindow.
It should be noted that I for this implementation am experimenting with ridding myself of using Managers (no other motivation than curiosity about will come out in terms of code design and architecture).
Well, the thing that amused me was to use a PropertySetter. This is due to the fact that you have to set the “visible” property in order to actually show the window. However, you also have to pass an object of the type “NativeWindowInitOptions” to the constructor.
The code eventually can be written like this…
<?xml version="1.0" encoding="utf-8"?> <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" xmlns:local="*"> <s:Button label="Click Me" /> <fx:Declarations> <local:GlobalEventMap2 /> </fx:Declarations> </s:WindowedApplication>
<?xml version="1.0" encoding="utf-8"?>
<mate:EventMap xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" xmlns:mate="http://mate.asfusion.com/">
<fx:Declarations>
<mate:EventHandlers type="{ MouseEvent.CLICK }">
<mate:PropertySetter
generator="{ NativeWindow }"
constructorArguments="{ [ new NativeWindowInitOptions() ] }"
cache="none"
targetKey="visible"
source="{ true }" />
</mate:EventHandlers>
</fx:Declarations>
</mate:EventMap>
MATE CacheSetter.. a quick and dirty introduction
One of the newer classes in the MATE Flex Framework yet to be documented is the CacheSetter.
It’s nothing overly fancy, but it does exactly what it promises… it allows you to set the Cache from an ActionTag.
Let’s examine the code below… it’s a standard MATE EventMap with a couple of eventhandlers which offers to exit an AIR application when the User clicks anywhere on it… the applications for such a feature might be quite limited, but that’s what I could think of at 4:40 AM in Bangkok after almost 2 hours of being teleconferencing with the Flex Team sitting in California and it proves the point with the CacheSetter close to a minimal implementation.
NativeSystemEventMap.mxml
<?xml version="1.0" encoding="utf-8"?>
<mate:EventMap xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo"
xmlns:mate="http://mate.asfusion.com/">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import flash.desktop.NativeApplication;
]]>
</fx:Script>
<fx:Declarations>
<mate:EventHandlers type="{ FlexEvent.CREATION_COMPLETE }">
<mate:CacheSetter cacheKey="{ NativeApplication }" instance="{ NativeApplication.nativeApplication }" />
</mate:EventHandlers>
<mate:EventHandlers type="{ MouseEvent.MOUSE_DOWN }">
<mate:MethodInvoker generator="{ NativeApplication }" method="exit" />
</mate:EventHandlers>
</fx:Declarations>
</mate:EventMap>
For the sake of completion, I will also bring the code to the AIR application itself…
<?xml version="1.0" encoding="utf-8"?> <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" xmlns:client="org.hello.micromanager.timetracker.client.*" xmlns:local="*"> <fx:Declarations> <local:NativeSystemEventMap /> </fx:Declarations> </s:WindowedApplication>
One of the more interesting and intricate details (and eventually why this exercise is interesting), is to see that it uses the Class reference as the cacheKey and that you eventually would be able to use any class or hashable object and chain as the cacheKey. If the cacheKey is NOT set explicitly it will default to use the class type of the Generator attribute, but if you are working with MATE the Cache class is one of the classes it makes the most sense to take an extra look at…
CacheSetter (Source)
http://code.google.com/p/mate-framework/source/browse/trunk/src/com/asfusion/mate/actions/CacheSetter.as
Cache (Source)
http://code.google.com/p/mate-framework/source/browse/trunk/src/com/asfusion/mate/core/Cache.as
Cache (Documentation
http://mate.asfusion.com/api_docs/com/asfusion/mate/core/Cache.html
ActionScript API for Adobe Wave Service
While I was experimenting with the new Adobe Wave Service from Adobe… I decided to take some of the experimental code and create a reusable library.
It has a basic implementation handling authentication as well as broadcasting notifications.
I have named the project “asadobewave” which roughly stands for ActionScript Adobe Wave and I have made it available via the Google Code under the Mozilla license.
Check it out…
http://code.google.com/p/asadobewave/
It has been moved to here…
http://code.google.com/p/as3wavelib/
Introducing Axiis… Open Source Data Visualization
Up to this point there has been only four more or less serious alternatives when it came to employing advanced Data Visualization in your Flex Apps, but not with Axiis another alternative has emerged.
Up to ths point we could either…
- Use the data visualization library native to the Flex SDK.
- Use Ilog Elixir.
- Use on of the the more or less unserious smaller contributions available out there typically limited to a single visualization.
- Write it ourselves.
Axiis, the 5. option now available, is an open source data visualization framework designed for beginner and expert developers alike.
Whether you are building elegant charts for executive briefings or exploring the boundaries of advanced data visualization research, Axiis has something for you.
Axiis provides both pre-built visualization components as well as abstract layout patterns and rendering classes that allow you to create your own unique visualizations.
Axiis is built upon the Degrafa graphics framework and Adobe Flex 3…
Check it out…
http://www.axiis.org/
…thx to the always well informed Paw Suddergaard for initially pointing me to this great contribution to the preferred library of open source projects…
Introducing HydraMVC…
HydraMVC is one of the most recent newcomers to the scene of Application Frameworks and Architecture Blocks for Flex Applications.
Its definitely something I’m going to check out in parallel to my love affair with the Mate Flex Framework.

HydraMVC is the result of a total rewrite of the PureMVC API exclusively for Flex, allowing Flex developers to take advantage of the PureMVC paradigm while leveraging native Flex features.
In addition to using Events vs. an independent Observer pattern, HydraMVC also streamlines implementation, encapsulating much of the initialization code that needed to be written when implementing PureMVC.
HydraMVC was written out of a love / hate relationship with PureMVC; it’s not our intent to say it’s “better” than PureMVC, because the mission of the frameworks are entirely different. PureMVC intends to be language-agnostic, where HydraMVC is a compromise by design.
While HydraMVC is an MVC framework, the demos also imply a strategy for package structure, although the implementation of HydraMVC will work regardless of whatever package structure convention you use. The goal was to create a structure that scales well for large applications, but it also allows you to quickly develop small applications in a proper MVC.
FC / FB Workflow Optimizer… sources available
I have made the sources available for the Workflow Optimizer… its a crude implementation but it does the job.
It uses Flex, AIR, as3preferenceslib, as3corelib and the Mate Flex Framework.
Don’t hesitate to comment on the ideas or concepts.. but don’t comment the code: it’s not written with any other priority than functionality…
Check it out…
http://code.google.com/p/workflowoptimizer/
Flash Catalyst / Flash Builder Workflow Optimizer
Workflow Optimizer is a small and lightweight tool which helps Flash Designers and Flash Developers to work around some of the temporary limitations with Flash Catalyst.
The application allows you to automatically extract the contents of FXP / FXPL files and put them into a configurable directory and can hence replace some of the tedious export / import actions from Flash Catalyst to Flash Builder.
The application is written in Flash Builder 4 with Flex 4 and AIR, it uses the as3preferenceslib for persisting the directory and file information and it uses Mate Flex Framework as the application controller.
Next step is to add support for running as a service by adding some Merapi classes and examine even better ways to help optimize the FC / FB workflow.
You can download and install the latest version from the Adobe AIR Marketplace here…
http://www.adobe.com/cfusion/marketplace/index.cfm?event=marketplace.offering&offeringid=13424
Sources are available at Google Code…
http://code.google.com/p/workflowoptimizer/
You can download the binary from here…
http://petermolgaard.com/projects/workflowoptimizer/WorkflowOptimizer.air.zip
Sources will soon follow…
Mate… Lightweight Schedule Extension
Some time ago I was in need of something to be run at regular intervals.
Among the many implementations I already had in my framework, I thought that including either my Workflow package (An ActionScript port of the Windows Workflow Foundation 3) or my processing package (eventually just a scheduling application block which allows processes to be managed Windows Service style.
I wanted something much more lightweight, so I decided to implement a Schedule Handler.
It extends the AbstractHandlers class, so all I had to do was initiate a timer and then run the sequence when the timer elapsed… more lightweight then that is hard to imagine.
package org.hellogroup.mate.actionLists
{
import com.asfusion.mate.actionLists.AbstractHandlers;
import com.asfusion.mate.actionLists.Scope;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Schedule extends AbstractHandlers
{
private var timer:Timer = null;
public function Schedule()
{
super();
this.timer = new Timer( 1000 );
this.timer.addEventListener( TimerEvent.TIMER, this.handleTimer );
}
[Bindable]
public function get delay() : Number
{
return timer.delay;
}
public function set delay( value:Number ) : void
{
this.timer.delay = value;
}
override public function initialized( document:Object, id:String ) : void
{
super.initialized( document, id );
this.timer.start();
}
private function handleTimer( event:TimerEvent ) : void
{
this.runSequence( new Scope( event, true, this.map ), this.actions );
}
}
}
The class is included in the downloads in my previous post…
http://blog.petermolgaard.com/2009/05/30/mate-stopanddispatchhandlers-extension/










3 comments