Designing a Generic Toolmanager - apache-flex

I want to handle multiple operations on a UI Component (button ,textfield, swfs,custom objects etc)
in like scaling,skewing ,color,rotations etc etc and save them too. Earlier the actions were done
using a single tool and single mxml file but now the tool is separated into different tools.
Was wondering how i can design / use something like Toolmanager class to handle actions etc?
Also the tricky part is that some objects can have more operations defined for them .
Like 'object1' has 3 operations that can be performed on it and 'object2' has 5 operations defined on it.
We are using MVC design pattern but no frameworks as such.
What are the different design patterns that can be used to do this?
Edit:
To be more precise i want implement this in AS3 OO way.
The application is similar to drawing application which supports addition of various images,text,audio,swfs etc. One added user can perform various operations of the objects..like
adding color,scaling skewing,rotation etc etc and custom effects and after that export the drawing as PNG.Likewise some effects that are applicable to text are not applicable to images
and vice versa. and some effects can be common.
Any ideas?

Probably you could have a toolbar, tools(inheriting from a common base), and some kind of property panel, these objects are accessible from a manager class which wrappes them together and makes some variables accessible for all classes.
Probably you want a selection array or vector in the manager class and a select tool to manipulate this collection
like (in the manager)
protected var _selection:Vector.<EditableBase> = new Vector.<EditableBase>();
public function get selection() { return _selection;}
and a collection about the editbase extensions and the tools avaiable for them.
every time the selection tool updates the selection collection (probably calling a method on manager from the select tool's onMouseUp method) you can update the toolbar to display the apropriate tools for the current selection
(in manager)
protected var _ToolsByType:Object (or Dictionary) = {"EditableAudio": ["toolA", "toolB", etc]};
protected var _defaultSet:Array = ["toolA", "toolB"];
and after the selection has benn manipulated (in manager also)
public function onSelectionChangedCallback():void
{
var toolsToDisplay:Array = _defaultSet;
if(_selection.length == 1)
{
//not actual syntax
var type:String = getQualifiedClassName(_selection[0]);
if(type in _ToolsByType) toolsToDisplay = _ToolsByType[type];
}
myToolBar.showSet(toolsToDisplay);
}
the ancestor for the tools should look something like this:
public class ToolBase
{
protected var _manager:ToolManager;
function ToolBase(manager:ToolManager)//and probably a bunch of other params as well
{
_manager = manager;
}
function onSelect()
{
//you can manipulate the properties panel here
}
function onDeSelect()...
function onMouseDown(mouseData:event/whateverWrapperYouHaveCreated)...
function onMouseMove...
function onMouseUp...
}
and so and so on :)
kinda straight forward.
check photoshop plugin tutorials, or google around "extending {any adobe stuff here, like flash or something}
thats javascript but the concept can be applied here as well

maybe you could use the Strategy Design Pattern by creating some extra classes in your MVC implementation
http://en.wikipedia.org/wiki/Strategy_pattern
algo, check this tool for images:
http://www.senocular.com/demo/TransformToolAS3/TransformTool.html
bye! :)

Related

AS3 Robot legs and Signals - Using Signals, Quite verbose, any alternatives?

Im using RobotLegs and Signals for my application. This is my first time using Robotlegs, and Im using Joel Hooks Signal Command Map example here
I've noticed that it seems quite verbose in contrast to events. For every Signal I have to create a new class, whereas with events I would group event types into one class.
I like how visually and instantly descriptive this is.. just browsing a signals package will reveal all app communications. Although it seems quite verbose to me.
Are other people using this, Is the way I'm using signals like this correct, or have people found a way around this verboseness?
Cheers
It's the correct way though. The major advantage of signals is you can include them in your interface definitions, but obviously you'll end up with a big pile of signals.
In general I use signals only for my view->mediator and service->command communication (1-to-1). For system wide notifications I use events (n-to-n). It makes the number of signals a bit more manageable.
But it's a matter of preference obviously.
Using a good IDE and/or a templating system alleviates a lot of the "pain" of having to create the various signals.
You do not have to make a new signal class for Command maps, its just good practice. You could just give the "dataType" class a type property - and do a switch on that. But that would be messy for commands. But note, Commands are basically for triggering application wide actions.
Not all signals trigger application wide actions.
For instance, if you are responding to a heap of events from a single View. I suggest making a Signal class for related "view events" (e.g. MyButtonSignal for MyButtonView) and give it a type property.
A typical signal of mine will look like:
package {
public class MyButtonSignal extends Signal {
public static const CLICK:String = 'myButtonClick';
public static const OVER:String = 'myButtonOver';
public function MyButtonSignal() {
super(String, Object);
}
}
}
Dispatch like so
myButtonSignal.dispatch(MyButtonSignal.CLICK, {name:'exit'});
Listen as normal:
myButtonSignal.add(doMyButtonSignal);
Handle signal like so:
protected function doMyButtonSignal(type:String, params:Object):void {
switch(type) {
case MyButtonSignal.CLICK: trace('click', params.name);
break;
case MyButtonSignal.OVER: trace('OVER', params.name);
break;
}
}
Occasionally its useful to give the data variable its own data class.
So everytime you realise "Aw shit, I need to react to another event", you simple go to the Signal and add a new static const to represent the event. Much like you (probably?) did when using Event objects.
For every Signal I have to create a new class, whereas with events I
would group event types into one class.
Instead of doing that you could just use the signal as a property… something like:
public var myCustomSignal:Signal = new Signal(String,String);
You can think of a signal as a property of your object/interface.
In Joel's example he's using signals to denote system level events and is mapping them with the robotlegs SignalMap which maps signals by type. Because they are mapped by type you need to create a unique type for each system level signal.

Unittesting a Save function using MVP pattern and RhinoMock

I am trying to get a better code coverage with my unittests, and recently I switched to using RhinoMock for my Mocking needs.
But I have got a question with how to write a specific unit-test, the Save() function.
I have an IView interface with several functions to retrieve values from the view (aspx page), examples are GetUsername(), GetPassword(), GetAddress() and GetCountry().
When the user clicks the submit button I want to have tests that tests if all these functions are actually being called. So I wrote this test:
[TestMethod]
public void MainController_Save_ShouldRetrieveLUsername()
{
//Initialize the IView and Controller
InitViewAndController();
//Trigger the Save function triggering the controller
//to collect information for storage
_controller.Save();
_view.AssertWasCalled(s => s.GetUsername(), o => o.Repeat.Once());
}
Now finally comes the question, considering the aspx contains 15 input fields that needs to be saved, is there a better way to test this behaviour that writing and maintaining 15 of these tests?
On one hand test should be simple and optimally only one Assert, but 15 of these functions feels like a waste.
Instead of testing whether these functions are called (they look more like properties instead of functions, BTW), you should check the results of the Save function. You should treat your test code more like a black box and try not to insert too much of its interior knowledge into your tests. This way your tests will be less brittle when the Save code changes.
Google for "state based testing".

How to create helper functions in a flex application

I have a flex application, and I am using a cairngorm structure -
src/com/mysite/editor/model/ contains the following two things
EditorModelLocator.as (Singleton Enforced Application Globals),
EditorGlobalConstants.as (Contains All constants), like the following
public static const SUPPORT_PHONE:String = '800-865-7496';
public static const SUPPORT_EMAIL:String = 'support#mysite.com';
I was wondering where the best place to put helper methods is. I need these to be methods I can use outside of the singleton enforced class. Would it make sense to put it in Global Constants? The only thing against that, is I always use EditorGlobalConstants the same way:
EditorGlobalConstants.SUPPORT_PHONE
An example of a 'helper function' is the following:
public var blank(value:String):Boolean {
if( value == '' || value == null ) return true;
return false;
}
I can store all of this information in EditorGlobalConstants, but I was wondering if maybe EditorHelpers.as would be better, and how I would instantiate/use that solution?
Thanks!
Andrew Thorp
Not familiar with how cairngorm tends to do things, but in AS3 functions don't have to be part of a class.
For instance, you could have a file called helperFunction.as with the contents:
package my.package {
public function helperFunction(arg1:Object, arg2:String):void {
// Do stuff
}
}
Then just import that method like you would anything else:
import my.package.helperFunction
and you can use it in your code.
Just pick a package that would make sense for the method to live in (probably in the same package that the objects it's meant to help with are defined).
If you're going to use your helper methods not only in your singleton class, it would be better to place them somewhere upper in hierarchy. You can easily find that place by yourself. Let's try:
Break up your application (in imagination/paper/whatever) into a boxes. Each class is a separate box.
Put them into structure. You just need to see, which boxes are placed inside which ones.
Mark the boxes-classes, where are you going to use these methods.
Find the top level, where are you going to use them and place your class there.
Let's see an example .. suppose you have this structure:
ToplevelApplication
|-BoxAtLevel_1
| |-BoxAtLevel_2
...
if I want my helpers used only in BoxAtLevel_2, I'd put them there:
|-BoxAtLevel_1
| |-BoxAtLevel_2
| |-Helpers
And so on .. if you have any troubles - put your structure here, and I'll help.
Also, about EditorHelpers.as .. is this an instance-level things or rather class-level ones? That's what going to set the way you'll use them.

Fastest way to get an Objects values in as3

Ok, so I swear this question should be all over the place, but its not.
I have a value object, inside are lots of getters/setters. It is not a dynamic class. And I desperately need to search an ArrayCollection filled with them. The search spans all fields, so and there are about 13 different types of VOs I'll be doing this with.
I've tried ObjectUtil.toString() and that works fine and all but it's slow as hell. There are 20 properties to return and ObjectUtil.toString() adds a bunch of junk to the output, not to mention the code is slow to begin with.
flash.utils.describeType() is even worse.
I'll be pleased to hear I'm missing something obvious.
UPDATE:
I ended up taking Juan's code along with the filter algorithm I use for searching and created ArrayCollectionX. Which means that every ArrayCollection I use now handles it's own filters. I can search through individual properties of the items in the AC, or with Juan's code it handles full collection search like a champ. There was negligible lag compared to the same solution with external filters.
If I understand your problem correctly, what you want is a list of the getters defined for certain objects. As far as I know, you'll have to use describeType for something like this (I'm pretty sure ObjectUtils uses this method under the hood).
Calling describeType a lot is going to be slow, as you note. But for only 13 types, this shouldn't be problematic, I think. Since these types are not dynamic, you know their properties are fixed, so you can retrieve this data once and cache it. You can build your cache up front or as you find new types.
Here's is a simple way to do this in code:
private var typePropertiesCache:Object = {};
private function getPropertyNames(instance:Object):Array {
var className:String = getQualifiedClassName(instance);
if(typePropertiesCache[className]) {
return typePropertiesCache[className];
}
var typeDef:XML = describeType(instance);
var props:Array = [];
for each(var prop:XML in typeDef.accessor.(#access == "readwrite" || #access == "readonly")) {
props.push(prop.#name);
}
return typePropertiesCache[className] = props;
}

clone flex component

I am trying to duplicate a flex component at run time.
For example if i have this
mx:Button label="btn" id="btn" click="handleClick(event)"/>
i should be able to call a function called DuplicateComponent() and it should return me a UI component thts exactly same as above button including the event listeners with it.
Can some one help me please??
Thanks in advance
Do a Byte Array Copy. This code segment should do it for you:
// ActionScript file
import flash.utils.ByteArray;
private function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
One note, I did not write this code myself, I'm pretty sure I got it from a post on the Flex Coder's list.
To solve that problem you should use actionscript and create the buttons dynamically.
Lets say you want the button(s) to go in a VBox called 'someVbox'
for (var i:uint = 0; i< 10; i++){
var but:Button = new Button();
but.label = 'some_id_'+i;
but.id = 'some_id_'+i;
but.addEventListener(MouseEvent.CLICK, 'handleClick');
someVbox.addChild(but);
}
I haven't tested it, but that should add 10 buttons to a vbox with a bit of luck.
You can't take a deep copy of UIComponents natively. You're best bet would be to create a new one and analyse the one you have to add a duplicate setup. To be honest this does sound like a bit of a code smell. I wonder if there may be a better solution to the problem with a bit of a rethink..
Same question as: http://www.flexforum.org/viewtopic.php?f=4&t=1421
Showing up in a google search for the same thing. So you've cut&pasted the same question a month later. No luck eh?
There is no easy way to do this that I know of. Many of a component's settings are dependent on the container/context/etc... and get instantiated during the creation process, so there's no reason to clone from that perspective.
You can clone key settings in actionscript and use those when creating new elements.
For instance, assuming you only care about properties, you might have an array ["styleName","width","height",...], and you can maybe use the array like this:
var newUI:UIComponent = new UIComponent();
for each(var s:String in propArray) {
newUI[s] = clonedUI[s];
}
If you want more bites on your question (rather than waiting a month), tell us what you are trying to achieve.
mx.utils.ObjectUtil often comes in handy, however for complex object types, it's typically good practice to implement an interface that requires a .clone() method, similar to how Events are cloned.
For example:
class MyClass implements ICanvasObject
{
...
public function clone():ICanvasObject
{
var obj:MyClass = new MyClass(parameters...);
return obj;
}
}
This gives your code more clarity and properly encapsulates concerns in the context of how the object is being used / cloned.
You are right but as per my understanding UI Components are not cloned by mx.utils.ObjectUtil.
from : http://livedocs.adobe.com/flex/201/langref/mx/utils/ObjectUtil.html#copy()
copy () method
public static function copy(value:Object):Object
Copies the specified Object and returns a reference to the copy. The copy is made using a native serialization technique. This means that custom serialization will be respected during the copy.
This method is designed for copying data objects, such as elements of a collection. It is not intended for copying a UIComponent object, such as a TextInput control. If you want to create copies of specific UIComponent objects, you can create a subclass of the component and implement a clone() method, or other method to perform the copy.
Parameters value:Object — Object that should be copied.
Returns Object — Copy of the specified Object

Resources