Archive for the ‘ActionScript’ Category

click on marker always show the last entry of data

June 14, 2008

This is a question from a co-worker of my last job. His is using gcliendGeocoder within a for-loop to dynamically get lat/lng and creating makers on Google maps. The problem is each time you click on a marker, the html text in the info window is always the one that should be for the last marker in the for-loop.

His code:

for (id = 0; id < addresses.length; id++)
{
var description = addresses[id];
var myBiz = biz[id];
geocoder.getLatLng(
description,
function(point)
{
var marker = new GMarker(point);
GEvent.addListener(marker, ‘click’,function(){marker.openInfoWindowHtml(description);});
map.addOverlay(marker);
}
);
}

The point here is “geocoder.getLatLng” is an “asynchronous” callback. That means when the “for-id-loop” reaches its end, the very first “getLatLng” may not get back yet. That’s why you always get the last description in the array. The fix is to add an additional counter inside the call back of “getLatLng”, and assign it as a dynamic property to the marker that gets returned from the callback, and then increment the counter by one at the end of the callback. When you handle the click, you always do a lookup on the marker using the id to find the right marker and the description.

var markers = [];
var closureID = 0;

for (id = 0; id < addresses.length; id++) {
var description = addresses[id];

geocoder.getLatLng(
description,
function(point) {
if(point)
{
var marker = new GMarker(point);
marker.id = closureID;
markers[closureID]=marker;
GEvent.addListener(marker, ‘click’,
function()
{
markers[marker.id].openInfoWindowHtml(addresses[marker.id]);
}
);
map.addOverlay(marker);
++closureID;
}
}
);

}

To see it in action, here is what happens “before“, and “after“:

Use swc in flex

May 5, 2008

Scenario 1: You need to compile ActionScript code as a reusable component in Flex Builder.

Solutions: Follow the steps (FB plugin v3):

Step 1. Compile swc. First you will need to create a new “Flex Library Project”. Then copy all the actionscript code into the top folder of your project file, retaining the package/namespace structure (fig. 1)

The file structure and xml manifest file in Flex Library Project

In “src” folder, you would need a xml-manifest.xml file where you declare the class and id (optional, default to the class name anyways) (fig 1). Thirdly, you would need to define your namespace for the class that’s going to be referenced in MXML (or Flash?) like so: In the AS class fine, inside the class definition, just like the way as you declare a variable, add “public namespace fc;” (substitue “fc” with whatever your choice of namespace). If you’ve enabled “build automatically” (under “Project” menu command), FB will instantaneously build the deploy files for you the time you save the AS file. The result is the complied .swc file, which you can find in the “bin” folder in your library project.

Step 2. Use swc in your Flex project. You either need to copy the swc file(s) into the library-path folders as defined in your flex-config.xml, or explicitly tell Flex to use the swc you want in your current project. To do so, go to “Project properties”->”Flex Build Path”->”Library Path”->”Add SWC”. You can simply navigate to the swc file in the Flex library project as defined in Step 1. After Flex compiled the project, you can use the component as defined in your ActionScript code. Here is an extract:

<mx:HBox>
<mx:Label text=”Search by last name: “/>
<fc:AutoComplete id=”lastNameSrchAC” dataProvider=”{listInfo}” labelField=”lastName”/>
</mx:HBox>

See also: Namespaces in Flex and Soprano

ScrollPane doesn’t clip loaded content

April 17, 2008

When a ScrollPane is used to load media (Flash 8 IDE), sometimes the loaded content didn’t get clipped (it either sits on top of the scrollpane or goes underneath it).

Cause: An absolute URL is used (such as “myScrollPane.contentPath = ‘http://www.mydomain.com/img/image.jpg’”) for the loaded content.

Solution: Change the absolute URL to relative URL (”img/image.jpg”). Of course you should be able to put the loading swf file and the loaded contents on the same domain.

Mouse hitTest (collision test) in AS 2

April 6, 2008

As a spatially challenged person (easily lost in a street/inside an office building/mall, etc.), I am always confused by the maths that is required when converting a spatial point from one coordinate space into another (localToGlobal, globalTolocal, etc. in Flash).

But hitTest for mouse cursor (collision test to see if mouse cursor collide with movieclip/subclass instances) is much more straightforward ;) You always test the mouse coordinates at the _root; this also holds true when you load the swf as an external file using MovieClip.loadMovie or MovieClipLoader.loadClip.

var bigMC:MovieClip;
var cir:MovieClip = bigMC.cir;
var rec:MovieClip = bigMC.rec;


var lsnr:Object = new Object();
lsnr.onMouseMove = function(evt:Object)
{
var tof:Boolean = cir.hitTest(_root._xmouse, _root._ymouse, true);
if(tof)trace(tof);
}
Mouse.addListener(lsnr);

In actionScript 3, the cumbersome way of using onMouseMove is gone because of the added event types such as MOUSE_OVER and MOUSE_OUT.

Full-screen mode in Flash 8

February 19, 2008

How to create true fullscreen movies with Flash

Exploring full-screen mode in Flash Player 9

Quick facts:

  1. Only supported with Flash Player 9.0.28  or above;
  2. Can be implemented in Flash 8 IDE by modifying the Stage class;
  3. Can only be initiated with  user inputs such as mouse click or keypres;
  4. An overlay dialog box will appear when the movie enters full-screen mode, instructing the user how to exit and return to normal mode.

Concurrent/Hierarchical states in State pattern and MVC pattern: Take two

September 23, 2007

Concurrent states in a state machine have behaviors that are independent of other states. For example, in a Flash video player, the “fullscreen” state is independent of “play”/”pause” states.

In a state machine, states have hierarchies. Some states that show relatedness of contexts can be grouped together; Child states are not accessible until their parent states are active. Theoretically, each set of concurrent states should have their own state manager. (In practice, if there is only two set of concurrent states, I find it just convenient to combine the two into one context object and have the base state includes interfaces that should be used by the other set of concurrent states. )

State pattern and MVC pattern revisit: Take one

September 22, 2007

Use case: You need to change the behaviors of your type code at run-time. For example, clicks on “play” button sometimes play a video clip and in other cases do nothing, depending on the context. (whether the video clip is playing or not.) The bad smell in your code usually is signaled by the presence of case-like conditional statements. It gets too complex when you need to place in many of the methods the same logical case/if-else switches to tackle the context and execute different code. The solutions can be “Replace Conditional with Polymorphism“, “Replace Type Code with Subclasses” or “Replace Type Code with State/Strategy” (Martin Fowler: Refactoring).

In GUI design, the run-time states and behaviors of a set of user interfaces are determined by a set of predefined rules. These rules are usually procedural-like and can be visually presented in flow charts. Using a statechart, we can split the logics into a group of self-sustained substate objects and thus make our program much easier to control.

In order to make it work, you need to set up a polymorphic structure:

1. A generic state interface. It contains two methods: enter() and exit(). Implement enter()/exit() in the concrete classes to perform type dependent setups and cleanup (such as hiding/exiting/fading out some components, etc.).

2. An application specific state interface. In this interface, define services that all the subclasses need to carry out, such as the following:

public function viewProfile(index:Number):Void
public function handleIndexSelect(info:Object):Void

3. An abstract/base state class that implements interfaces 1 and 2.

4. Most of times, instead of stuffing all the service methods in the base state class in step3, you will find it convenient to create a couple of concrete classes that provide common services more than one of the substates will perform and that are independent of the context, such as playVideo(index:uint):Void, pauseVideo():Void, setRepeatAll(v:Boolean):Void, handleClipComplete(evt:Object):Void, etc..

5. A state manager. State manager is the context object. It has the following major responsibilites:

a. Stores references, as well as defines accessors to all the substate objects.

b. Accessors to get and set the current state object. Like this:

public function setState(v:AbstractState):Void
{
_state.exit();
_state = v;
_state.enter();
}

c. Initializes the entry substate object (or to initialize all the substates) and set the current state to that object when itself is initialized.

6. All the concrete substate classes. The classes need to store a reference to the main timeline (or the Document class if in ActionScript 3), as well as references to each of the common service provider classes as mentioned in step3 if any. Each of the classes has the following responsibilities:

a. Implements enter() and exit(). enter() needs to assign event handlers to all the UI controls.

b. Defines and implements context sensitive behaviors. They are usually handlers of UI events.

c. At least one of the methods in step b. needs to call the state manager to switch the current substate.

MVC/UMC revisit

August 7, 2007

I was doing a simple audio clip playlist a couple weeks ago. Such a small thing got to the level at which I almost couldn’t handle it when I started to try to put some buttons to indicate and prompt users to toggle “repeat all” on and off. It works like this:

If no clip is playing and “repeat all” is off, the player displays “toggle off” icon while displaying a “play all clips” button when mouse rolls over it. If a clip is playing and “repeat all” is off, the player instead displays “turn on autoplay” when mouse-over. When “repeat all” is on, the player displays “repeat all on” icon on “mouse-up” state and “turn off autoplay” on “mouse-over” state.

I got into interwinded “if-else” conditions and was almost lost. I spent almost a whole day and still couldn’t get the buttons work together nicely. I think to myself hey if such a small thing takes me so long to figure out, what else could I possibly do? I have been doing ActionScript full-time for about 3 years now; although most of my stuff is not stellar in terms of the coding level, I’ve gained quite a bit of confidence in coding UI and animation. So I decided to give myself a little break and went to the library and Borders. After reading and thinking, I finally think I not only got the stuff done, but also showed a bit of logic in my spaghetti code. At the end I list the books/articles that I have been reading for the past couple of days. Not that I feel I have been elevated to another level, but here are just some thoughts:

Basically Control is like a hub. It knows about both View and Model and connects View and Model. It contains the logic of the UI. The responsibility of Control basically is about coordinating all the events and actions that affect both UI and Model. Many of them (but not all) are about how to react to the requests from UI and updates it; if there is anything it cannot decide by itself, it relays them to the Model. The rule of thumb here is that if an interaction won’t affect other UI components and doesn’t request anything from Model, Control will handle it directly (like most of the roll-overs) without consulting Model.

If the UI is requesting anything from Model (like asking to play another song or movie), Control would not change View directly. Instead it sends the request to Model and Model makes changes accordingly and then signals Control about the updates. Control/View receives the information about the changes and View is then updated (like dehighlighting the currently highlighted button and highlighting the button that is associated to the clip that is requested, assuming the clip starts playing.)

The change of UI doesn’t necessarily initiated by a request from UI. It could be a system event, like a song completes playing, or a change from Model, like a new song has been added to the pool of all the available songs on the server, etc.. Control should have routines to handle all these changes (such as “handleClipComplete()”, etc..)

It’s just a matter of your coding style and about the complexity of the entities you are dealing with when it comes to whether to use classes (each of which present only a segment of MVC), or whether to have one UI component per View, or just to stuff everything in one big chunk of code. It’s the thought behind it that matters.

It helps me a lot since I’ve started to learn to draw diagrams of the states (statechart) and then to figure out all the classes and operations/attributes from it. I am using paper and pall pen instead of any of the UML tools. It helps me to concentrate on the thinking.

Readings:

Declaring stage instances from Library

July 17, 2007

1. Uncheck “Publish settings->AS3->Automatically declare stage instances”;

2. Right click Sprite/MovieClip in Library. Check “Linkage”, assign”Class”and “Base class”. I think the base class is either “Sprite” or “MovieClip”;

3. Declare instance as a property of the Document class. The class must be declared as public in order not to get a compiler error. Like so:

public var bkgdrop:Backdrop;

or

public var bkgdrop:Sprite;

Links:

Class path / Document class

July 16, 2007

It took me like 10 minutes to figure out…

The class path, if under the directory “Classes” which is inside the same directory as the running .fla, should be:

./Classes

Not:

Classes

Nor:

/Classes

Document class (accessed by right-click on stage) is dot name-spaced.