diff --git a/AcmeWidgetFactory/src/org/robotlegs/demos/acmewidgetfactory/shell/model/ActiveWidgetModel.as b/AcmeWidgetFactory/src/org/robotlegs/demos/acmewidgetfactory/shell/model/ActiveWidgetModel.as index bf3c0ed..6cbb456 100644 --- a/AcmeWidgetFactory/src/org/robotlegs/demos/acmewidgetfactory/shell/model/ActiveWidgetModel.as +++ b/AcmeWidgetFactory/src/org/robotlegs/demos/acmewidgetfactory/shell/model/ActiveWidgetModel.as @@ -7,10 +7,10 @@ package org.robotlegs.demos.acmewidgetfactory.shell.model import mx.modules.ModuleManager; import org.robotlegs.demos.acmewidgetfactory.common.interfaces.IWidgetModule; - import org.robotlegs.mvcs.Model; + import org.robotlegs.mvcs.Actor; import org.robotlegs.utils.NamedObjectMap; - public class ActiveWidgetModel extends Model + public class ActiveWidgetModel extends Actor { private static const MODULE_URL:String = 'org/robotlegs/demos/acmewidgetfactory/modules/widget/WidgetModule.swf'; diff --git a/FlickrImageGallery/src/org/robotlegs/demos/imagegallery/models/GalleryModel.as b/FlickrImageGallery/src/org/robotlegs/demos/imagegallery/models/GalleryModel.as index 4797548..6d8581e 100644 --- a/FlickrImageGallery/src/org/robotlegs/demos/imagegallery/models/GalleryModel.as +++ b/FlickrImageGallery/src/org/robotlegs/demos/imagegallery/models/GalleryModel.as @@ -15,7 +15,7 @@ package org.robotlegs.demos.imagegallery.models import org.robotlegs.demos.imagegallery.models.vo.GalleryImage; import org.robotlegs.mvcs.*; - public class GalleryModel extends Model + public class GalleryModel extends Actor { private var _gallery:Gallery; diff --git a/FlickrImageGallery/src/org/robotlegs/demos/imagegallery/remote/services/FlickrImageService.as b/FlickrImageGallery/src/org/robotlegs/demos/imagegallery/remote/services/FlickrImageService.as index 0bb8fb3..9fbcc7f 100644 --- a/FlickrImageGallery/src/org/robotlegs/demos/imagegallery/remote/services/FlickrImageService.as +++ b/FlickrImageGallery/src/org/robotlegs/demos/imagegallery/remote/services/FlickrImageService.as @@ -20,9 +20,9 @@ package org.robotlegs.demos.imagegallery.remote.services import org.robotlegs.demos.imagegallery.events.GalleryEvent; import org.robotlegs.demos.imagegallery.models.vo.Gallery; import org.robotlegs.demos.imagegallery.models.vo.GalleryImage; - import org.robotlegs.mvcs.Service; + import org.robotlegs.mvcs.Actor; - public class FlickrImageService extends Service implements IGalleryImageService + public class FlickrImageService extends Actor implements IGalleryImageService { private var service:FlickrService; private var photos:Photos; diff --git a/GoogleMaps/src/org/robotlegs/demos/flashgooglemaps/model/proxies/AssetLoaderProxy.as b/GoogleMaps/src/org/robotlegs/demos/flashgooglemaps/model/proxies/AssetLoaderProxy.as index 216ad92..42f84e0 100644 --- a/GoogleMaps/src/org/robotlegs/demos/flashgooglemaps/model/proxies/AssetLoaderProxy.as +++ b/GoogleMaps/src/org/robotlegs/demos/flashgooglemaps/model/proxies/AssetLoaderProxy.as @@ -27,7 +27,7 @@ package org.robotlegs.demos.flashgooglemaps.model.proxies import flash.net.URLRequest; import org.robotlegs.demos.flashgooglemaps.model.events.AssetLoaderProxyEvent; - import org.robotlegs.mvcs.Model; + import org.robotlegs.mvcs.Actor; /** * Proxy to load the xml content. @@ -35,7 +35,7 @@ package org.robotlegs.demos.flashgooglemaps.model.proxies * @author Peter Lorent peter.lorent@gmail.com * */ - public class AssetLoaderProxy extends Model + public class AssetLoaderProxy extends Actor { //-------------------------------------------------------------------------- // diff --git a/GoogleMaps/src/org/robotlegs/demos/flashgooglemaps/model/services/GeoCodingService.as b/GoogleMaps/src/org/robotlegs/demos/flashgooglemaps/model/services/GeoCodingService.as index d787788..51cb612 100644 --- a/GoogleMaps/src/org/robotlegs/demos/flashgooglemaps/model/services/GeoCodingService.as +++ b/GoogleMaps/src/org/robotlegs/demos/flashgooglemaps/model/services/GeoCodingService.as @@ -22,12 +22,11 @@ package org.robotlegs.demos.flashgooglemaps.model.services { - import org.robotlegs.mvcs.Service; - import org.robotlegs.demos.flashgooglemaps.model.events.GeoCodingServiceEvent; - import com.google.maps.services.ClientGeocoder; import com.google.maps.services.GeocodingEvent; - import com.google.maps.LatLng; + + import org.robotlegs.demos.flashgooglemaps.model.events.GeoCodingServiceEvent; + import org.robotlegs.mvcs.Actor; /** * A Service to get us some results from the Googlemaps API. @@ -35,7 +34,7 @@ package org.robotlegs.demos.flashgooglemaps.model.services * @author Peter Lorent peter.lorent@gmail.com * */ - public class GeoCodingService extends Service + public class GeoCodingService extends Actor { //-------------------------------------------------------------------------- // diff --git a/GoogleMaps/web/FlashGoogleMaps.html b/GoogleMaps/web/FlashGoogleMaps.html index 32500f1..c28c292 100644 --- a/GoogleMaps/web/FlashGoogleMaps.html +++ b/GoogleMaps/web/FlashGoogleMaps.html @@ -12,7 +12,7 @@ // --> - + @@ -65,9 +66,11 @@ To view this page ensure that Adobe Flash Player version 10.0.0 or greater is installed.

- - Get Adobe Flash Player - + diff --git a/GoogleMaps/web/FlashGoogleMaps.swf b/GoogleMaps/web/FlashGoogleMaps.swf index de2735b..486047b 100644 Binary files a/GoogleMaps/web/FlashGoogleMaps.swf and b/GoogleMaps/web/FlashGoogleMaps.swf differ diff --git a/GoogleMaps/web/assets/img/jos.jpg b/GoogleMaps/web/assets/img/jos.jpg new file mode 100644 index 0000000..81e9791 Binary files /dev/null and b/GoogleMaps/web/assets/img/jos.jpg differ diff --git a/GoogleMaps/web/assets/img/wild.jpg b/GoogleMaps/web/assets/img/wild.jpg new file mode 100644 index 0000000..6098e33 Binary files /dev/null and b/GoogleMaps/web/assets/img/wild.jpg differ diff --git a/GoogleMaps/web/assets/xml/content.xml b/GoogleMaps/web/assets/xml/content.xml new file mode 100644 index 0000000..636572e --- /dev/null +++ b/GoogleMaps/web/assets/xml/content.xml @@ -0,0 +1,17 @@ + + + + + + + + So, let's try and explain how everything works here.

Remember, on github.com/darscan/robotlegs/tree/master you can read more about the framework.

First things first.
The project is a FlashBuilder AS3-project using SDK4.0.0 build 7219. It is set to build in /web/assets/swf/ and opens the index.html in /web if you debug the project. The index.html embeds a loader.swf and it loads the swf we compile with FlashBuilder. The View (component) classes in the code embed graphical assets (movieclips) from fla files (Flash CS4). These are set to publish in src/main/flash/assets/swf/. If you change things in the fla's, compile in the Flash IDE and debug the project in FlashBuilder to see the changes. The Googlemap uses a custom marker. Its View class embeds a .png that resides in src/main/flash/assets/bitmaps/. One thing to mention: I used the word component. No, I don't mean a full fledged AS3 Component. In the context of the framework we merely use the word component to make a distinction between the Mediator and the view component it mediates.

The basic idea is to show how the framework is used to consume content like xml and a service. And (of course) how to set and change the state using events. On the Googlemap I show some pubs in our country with corresponding entries under the 'Tips' tab in the main navigation. Clicking on one of the markers triggers an event in the View component and its Mediator handles the event by calling the (Googlemaps API) service. The Mediator receives the result from the service and changes the state of the View component via its API. To demonstrate how to 'communicate' between the main content pane and the Googlemap (these two 'components' are obviously unaware of each other) the tips will 'trigger' an event when clicked and cause the Googlemap to change its state.

Within the main content pane the main navigation is a seperate component. It merely triggers an event when one of the tabs is clicked. The event carries an id and the Mediator that 'governs' the content view component uses this id to show the correct content from the xml.

Ok, that pretty much wraps it up. Last thing to mention: this is a work in progress so I'll probably refactor some things, so check back if you want to have the latest version. And now:


Show me the best pubs >>]]>
+ + + + + Some words on how the code works.


Everything is a choice, right? I've just made some choices in the design to show how the framework does its job. For instance, in this demo I'm waiting for the Googlemap to broadcast its MapEvent.MAP_READY event before anything happens on the stage - see GoogleMapsView.handleEvent(). Only after that event fires, I'm loading the xml that contains the data for the markers, parse that data and animate the map to a position on the stage. 'onComplete' the main content pane moves to its final destination. It's only to show how to use the events from the framework to orchestrate what happens on the stage. So yes, if that MapEvent.MAP_READY doesn't fire, nothing will happen. In a real life website you would need to catch this and show some error message. Or opt for a different implementation all together for that matter.

Now, from the top.
Ok, to get things working the framework requires some basic actors. One of the - in my opinion - nifty features of RobotLegs is that it 'listens' to what happens on the display list (later more on this). So the first thing you must provide is the container that holds all Sprites and Movieclips you want to put on the stage - see FlashGoogleMaps.as which is the 'Document class' of the project. You pass this information to what is known as the Context - see FlashGoogleMapsContext.as. The Context will initialize the framework. Next, you need to provide some information about your actors. Basically you map View components to their Mediators, map Commands to events (so things will happen when you want to) and... well, let's say save some stuff you can use later on in the code ('ask for' - for instance - Proxies and/or Services using the magic called Dependency Injection). When all of that is done, you fire a ContextEvent.STARTUP and... nothing happens. Here is where it starts to get interesting. Only when you add a Sprite to the display list, that is when things start happening. The framework detects the new child on the stage, provides the correct mediator and away we go. And once you are coding in RobotLegs you will experience why this is so freaking cool. Let's summarize the basic actors in this demo:

FlashGoogleMaps.as - serves as the Document Class
FlashGoogleMapsContext.as - initializes the framework
PrepViewCommand.as - map View components to Mediators
PrepModelCommand.as - 'save' the model parts we will need
PrepControllerCommand - map some Commands to events
StartupCommand.as - add some Sprites to fire up this thing.

The Views and Mediators.
Ok, with the basic actors in place we can add our Views and do something with the Model. As said, I'm dropping a GoogleMapsView on the stage. The framework detects this action and automatically provides the GoogleMapsMediator thanks to the mapping we did. Have a look at the GoogleMapsMediator. It listens for the GoogleMapsView.GOOGLEMAP_READY event fired by the GoogleMapsView. Once that events fires, handleGoogleMapReady() gets called and that's when I load the xml-file that contains the data for the markers and all other content. To load the xml (a Model related job) we dispatch an event that is mapped to the LoadXMLCommand. The GoogleMapsMediator obviously wants to know when the xml is loaded so it registers for AssetLoaderProxyEvent.XML_CONTENT_LOADED which will be fired by AssetLoaderProxy. Once the event fires handleXMLContentLoaded() modifies GoogleMapsView via its API. And that - basically - is it!

Ok, that was way more than 'some words', but you have to agree it's easy stuff and all you need to know to start coding with RobotLegs. Yes, there is more but once you are on your way you will discover and learn the more involved aspects of the framework.
]]>
+ How about the nitty gritty?
+We have the basics covered and the purpose of this demo is to show just how easy it is to work with RobotLegs, but maybe I should explain some design choices in the code.

The Mediators.
I could have done the demo with three Mediators:

GoogleMapsMediator, ContentViewMediator, TabViewMediator, mediating the three 'major' views in the demo.

In this setup the ContentView, representing the content pane, could listen to events from its view parts (PlainTextView and TipView(s)) and let the ContentMediator handle those events. Let's look at the tips. What we need here is that a click on the tip makes the Googlemap zoom in on the location and show the lay over with some information on the selected pub. The ContentView must listen for the event from the TipView(s) and let its Mediator know about this so the framework can notify the GoogleMapsMediator of the request. Let's say this works but it clutters the code in the ContentView. In comes that nifty feature again where RobotLegs detects new children on the stage. The moment the ContentView adds TipView(s) to the display list, RobotLegs makes sure there is a Mediator (provided we did the mapping!). This makes sense right? The dynamically created TipViewMediators now handle the click event and 'directly' inform the GooglemapsMediator. And yes, if we remove a child, RobotLegs removes the associated Mediator for us.

So, what about a Mediator for the SmartInfoWindow? I'll leave that up to you if you don't mind.

The content.
There are so many ways to parse, save and distribute the (xml) content and it is beyond the scope of this demo to discuss this. I decided to use VO's for the markers on the Googlemap because this makes it much easier to work with (this is pretty much the way I would handle a result from a remoting gateway). Yes, you can also skip the VO stuff all together and just parse the tips in the GoogleView, or whatever approach you feel comfortable with. One thing to note on my VO approach: it is not really the Mediator way of doing things. You should be able to (re)use the view component as is in another project. Meaning, using its API, provide it with data and be done with it. The dependency on the VO's prevents this. Just so you know.

The events.
I can hear you thinking, 'do we need all these events'? Technically, no. You could do with a generic event that can carry optional data. Downside: it means casting stuff all over the place and that's one of the things RobotLegs is not promoting. Bottom line: it's a matter of choice.

Final words.
Found any flaws in the code? You know a better way to do things? Let me know. Join the RobotLegs AS3 Discussion Group, http://groups.google.com/group/robotlegs, and drop a message.
I hope this demo helped you to get going with RobotLegs in a Flash AS3 environment. And I wish you happy coding!
]]>
+
+
diff --git a/GoogleMaps/web/index.html b/GoogleMaps/web/index.html index 14985d8..f497c1a 100644 --- a/GoogleMaps/web/index.html +++ b/GoogleMaps/web/index.html @@ -16,11 +16,11 @@ - - + + - + @@ -34,9 +34,9 @@