Basic Tabbed-Menu / View Stack Flex App Structure

Just some quick notes on setting up a basic Flex app that encapsulates individual page content (views). This could work for a multi-tab widget or a simple microsite.

Here’re some ways to interact w/ the View Stack:

Simple ViewStack switching by id
Selecting a view in a ViewStack just by its Class

To replace the views with your own custom .mxml files, check out at least the first 7 minutes of the Cairngorm Part 2 video here. It ends up looking like this:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:view="view.*" 
    layout="vertical" >

//....
<mx:ViewStack id="yourID" width="100%" height="100%">
<view:YourPage1 />
<view:YourPage2 />
</mx:ViewStack>
//...

Note, the extra namespace at the top, “xmlns:view”, and make sure that directory actually exists in your source folder. The “view” directory is where YourPage1.mxml and YourPage2.mxml should be stored.

Advertisements

Part 2: Using custom graphics via Flex SDK in the Flash IDE

This post expands on the previous simple example with an example of a basic menu for an Actionscript-only AS3.0 project in Flash that uses a cool feature of the Flex SDK — the Embed tag. The last example was useful because the Flash IDE’s Library wasn’t used at all. This method, allows you to still use the Flex SDK’s [Embed] meta tag but lets you work with a Designer who only knows how to use .fla files and the Library. Using this technique a Developer can receive an assets SWF from a Designer and worry about the code, not about setting up graphics in the library.

Prep the files
In the Flash IDE* (CS4, for example), create an empty .fla and set TenOfSameButn as the Document Class. Make sure you have an assets SWF named “BasicBtnAssets.swf” inside a folder called /assets in your main directory, or in the same place your main .fla is located. BasicBtnAssets.swf should contain your button graphics, in this case just a generic Off state and On state set to Export for Actionscript. The Off state has a Class name of “reg” (set by going to Library > (Right/Control click the asset MovieClip ) > Properties) and the On state is named “ovr” via the library by the Designer.

Create the graphic assets container Class
Place it inside this folder structure: {your main .fla’s location}/com/timshaya/model.

package com.timshaya.model
{	
	import flash.display.Sprite;
	import flash.display.MovieClip;
	
	public class BasicBtnAssets extends Sprite
	{	
		//embed graphic assets, 
		// "../../../" since "/assets" is outside this package
		[Embed(source="../../../assets/BasicBtnAssets2.swf", symbol="reg")]
		private var MyBtns1offState:Class;
		[Embed(source="../../../assets/BasicBtnAssets2.swf", symbol="ovr")]
		private var MyBtns1onState:Class;

		//create displayable object to attach graphics to
		private var _mybtn1off:Sprite;
		private var _mybtn1on:Sprite;
		
		public function BasicBtnAssets():void 
		{
			//attach graphic asset to displayable object	
			_mybtn1off = new MyBtns1offState();
			_mybtn1on = new MyBtns1onState();
		}
		
		/*  create getter method to give other classes a way to access 
			the displayable graphic object while preserving Encapsulation */						
		public function get mybtn1off():Sprite { return this._mybtn1off; }		
		public function get mybtn1on():Sprite { return this._mybtn1on; }		
	}	
}

Use the above graphic assets Class to display a 10 button menu on stage
Place TenOfSameButn.as in the same location as your main .fla file that uses this as its Document Class.

package 
{	
	import com.timshaya.model.BasicBtnAssets;
	
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.DisplayObject;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.MouseEvent;	
	
	[SWF (width="600", height="400", backgroundColor="#9999cc", frameRate="31")]
	public class TenOfSameButn extends MovieClip
	{				
		//a reference to the custom graphics object
		private var btnAssets:BasicBtnAssets; 
		private var butnGroup1:Sprite;
		
		//buttons
		private var butn1:      Sprite; //button 1 local container
		private var butn2:      Sprite;
		private var butn3:      Sprite;
		private var butn4:      Sprite;
		private var butn5:      Sprite; 
		private var butn6:      Sprite;
		private var butn7:      Sprite;
		private var butn8:      Sprite;
		private var butn9:      Sprite; 
		private var butn10:     Sprite; 		
		private var butnsArra:  Array = [butn1,butn2,butn3,butn4,butn5,butn6,butn7,butn8,butn9,butn10];
		
		private var offSet:     Number = 20; //horizontal button spacing offset
		
		public function TenOfSameButn():void 
		{						
			buildMenu();
		}		
		
		public function buildMenu():void 
		{
			butnGroup1 = new Sprite();
			addChild(butnGroup1);			
			
			for(var itm:int = 0; itm < butnsArra.length; itm++) //make 10 buttons
			{				
				butnsArra[itm] = new Sprite();
				//butnsArra[itm] = new MovieClip();																
				//butnsArra[itm].ID = itm; 
				//adding custom properties only works 
                                //with MovieClip, because it's a Dynamic Class															
																
				//create a new BasicBtnAssets instance for each button
				btnAssets = new BasicBtnAssets(); 				
				
				//put btn1 off state inside btn1 
				butnsArra[itm].addChild(btnAssets.mybtn1off);	
	
				//put btn1 on state inside btn1
				butnsArra[itm].addChild(btnAssets.mybtn1on);	
				
				//add each button to the group container so they can be repositioned as a group
				butnGroup1.addChild(butnsArra[itm]);		
				
				butnsArra[itm].x = 2.2;
				butnsArra[itm].x = butnsArra[itm].x * itm * offSet;
				//trace("butnsArra["+itm+"].x = " + butnsArra[itm].x);	
				butnsArra[itm].y = stage.stageHeight / 2 - butnsArra[itm].height/2 - 100;
				
				//hide Mouse Over state
				butnsArra[itm].getChildAt(1).visible = false; 
				butnsArra[itm].buttonMode = true;
				
				butnsArra[itm].addEventListener(MouseEvent.MOUSE_OVER, doMouseOvr, false, 0, true);
				butnsArra[itm].addEventListener(MouseEvent.MOUSE_OUT, doMouseOut, false, 0, true);				
			}
			
			//center btns container
			butnGroup1.x = stage.stageWidth/2 - butnGroup1.width/2;			
		}
		
		public function doMouseOvr(e:MouseEvent):void 
		{				
			e.target.parent.getChildAt(1).visible = true;
		}
		
		public function doMouseOut(e:MouseEvent):void 
		{
			e.target.parent.getChildAt(1).visible = false;
		}
	}	
}

Part 1: Using custom graphics via Flex SDK in the Flash IDE

Part 2. This is one way to organize graphical assets for an Actionscript-only AS3.0 project in Flash without using the Library.

Prep the files
In the Flash IDE* (CS4, for example), create an empty .fla and set Tester1 as the Document Class. Make sure you have an image named “mybutton1.png” inside a folder called /assets in your main directory, or in the same place your main .fla is located.

Create the graphic assets container Class
Place it inside this folder structure: {your main .fla’s location}/com/timshaya/model.

package com.timshaya.model
{	
	import flash.display.DisplayObject;
	
	public class BtnAssets 
	{	
		//embed graphic assets
		// "../../../" since "/assets" is outside this package
		[Embed("../../../assets/mybutton1.png")]
		private var MyBtn1:Class;
		
		//create displayable object to attach graphics to
		private var _mybtn1:DisplayObject;
		
		public function BtnAssets():void 
		{
			//attach graphic asset to displayable object	
			_mybtn1 = new MyBtn1();
		}
		
		/*  create getter method to give other classes a way to access 
			the displayable graphic object while preserving Encapsulation** */
		public function get mybtn1():DisplayObject { return this._mybtn1; }		
				
	}	
}

Use the above graphic assets Class to display a graphic on stage
Place Tester1.as in the same location as your main .fla file that uses this as its Document Class.

package 
{	
	import com.timshaya.model.BtnAssets;
	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	
	[SWF (width="600", height="400", backgroundColor="#9999cc", frameRate="31")]
	public class Tester1 extends MovieClip
	{				
		//a reference to the custom graphics object
		private var btnAssets:BtnAssets; 

		//buttons
		private var butn1:DisplayObject;		
		
		public function Tester1():void 
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align=StageAlign.TOP_LEFT;
			
			btnAssets = new BtnAssets();
			
			//add button to stage
			butn1 = btnAssets.mybtn1;
			butn1.x = (stage.stageWidth/2) - butn1.width/2; //stage center
			butn1.y = stage.stageHeight/2 - butn1.height/2;
			addChild(butn1);			
		}		
	}	
}

Why bother? Why not just stuff all assets in the .fla via the Library? Doing it this way makes your AS3.0 code less IDE dependent. It’s easier to compile regardless of whether you’re using Flash, Flex Builder, FDT, or FlashDevelop.

* IDE means Integrated Development Environment. It’s a fancy way of saying “program” or “development tool.”

** Encapsulation is a key principle of OOP

A quick note about compiling FIVe3D examples in Flex

One of my favorite FIVe3D examples is this AS3 banner by Bartek Drozdz.

I downloaded the source code graciously provided by the author but when I tried to compile in Flex Builder 3 w/ SDK 3.4, I kept getting errors that told me Flex can’t find classes found in the “fl.motion.*” package. Since that particular package only works in the Flash IDE, I had to make some small adjustments to the FIVe3D banner code to get it to compile as a Flex Builder Actionscript application. Basically, I had to substitute all “fl.motion” package classes with their equivalents from the TweenLite library. For example, when an easing function, such as “import fl.motion.Elastic” was required by line 6 of Screenplay.as, it was quick and easy to change that to “import gs.easing.Elastic,” while making sure the relevant “gs” packages are actually at the location you’re telling the application they’re located.

In Sprite3D.as and Shape3D.as I commented out these lines and most of the banner example’s functionality remained unaffected:

/* ... */ 
import fl.motion.Color;
/* ... */ 
var color:Color = new Color();
color.brightness = brightness;
color.alphaMultiplier = alpha;
transform.colorTransform = color;
/* ... */ 

Testing a cool AS3-based video player

Martin Legris created a great little Actionscript-only AS3 Video player:

today I will explain how to play .FLV files that are hosted on a standard HTTP server, no fancy streaming. You can use pre-made components to do so, but sometimes, for whatever reason, you want to do it yourself. I wrote my first FLV playing algorithm in AS3 about 10 months ago, it has evolved since and here is the breakdown on how I make it work. It’s been used in many widgets, mostly for Music Nation.

His tutorial came in three parts, with final code located here, in Part 3.

Here’s a quick little Client class I wrote as an Actionscript Project in Flex Builder 3. If you’re using the Flash IDE, just use this as the Document Class. If you’re using FlashDevelop — you know what to do. This code can be used to test the code in Part 3:

package {

	import ca.newcommerce.media.FLVPlayer;
	import ca.newcommerce.media.MediaData;

	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.media.Video;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;

	public class FLVPlayerTest extends Sprite
	{
		private var myData:MediaData;
		private var vid:Video;
		private var myPlayr:FLVPlayer;
		private var txtBox:TextField;
		private var txtBox2:TextField;

		//in real life, populate this array from an external data source
		private var trackArray:Array = ["http://www.helpexamples.com/flash/video/clouds.flv",
             "http://www.helpexamples.com/flash/video/typing_short.flv",
             "http://www.helpexamples.com/flash/video/sheep.flv",
             "http://www.helpexamples.com/flash/video/water.flv",										       "http://www.helpexamples.com/flash/video/cuepoints.flv"];

		public function FLVPlayerTest()
		{
			inti();
			addBasicMenu();
		}

		public function inti():void
		{
			//start the player
			myData = new MediaData(trackArray[0], "some title", 300, "image.jpg", 320, 200);
			myPlayr = new FLVPlayer();
			vid = new Video(320, 200);

			myPlayr.video = vid;
			myPlayr.playMedia(myData);

			stage.addChild(vid);
		}

		public function addBasicMenu():void
		{
			//add some simple text boxes to test loading other videos
			txtBox2 = new TextField();
         	txtBox2.y = vid.height + 20;
         	txtBox2.autoSize = TextFieldAutoSize.LEFT;
         	txtBox = new TextField();
         	txtBox.autoSize = TextFieldAutoSize.LEFT;
         	txtBox.multiline = true;
         	txtBox.x = vid.x;
         	txtBox.y = txtBox2.y + 20;
         	txtBox.mouseEnabled = true;
         	stage.addChild(txtBox);
         	stage.addChild(txtBox2);

         	txtBox2.text = "Click a line below to load another movie:\n\n";

         	txtBox.appendText("line one\n");
         	txtBox.appendText("line two\n");
         	txtBox.appendText("line three\n");
         	txtBox.appendText("line four\n");
         	txtBox.appendText("line five\n");

			txtBox.addEventListener(MouseEvent.CLICK, handleClick, false, 0, true);
		}

		public function handleClick(e:MouseEvent):void
		{
			//tells us what line of the text box was clicked by the mouse
			var lineIndx:int = txtBox.getLineIndexAtPoint(e.target.mouseX, e.target.mouseY);

			trace(lineIndx);
			switch(lineIndx)
			{
				case 0:
					changeVid(trackArray[lineIndx]);
					break;
				case 1:
					changeVid(trackArray[lineIndx]);
					break;
				case 2:
					changeVid(trackArray[lineIndx]);
					break;
				case 3:
					changeVid(trackArray[lineIndx]);
					break;
				case 4:
					changeVid(trackArray[lineIndx]);
					break;
			}
		}

		public function changeVid(v:String, t:String="", l:int=120, img:String="", w:int=320, h:int=200):void
		{
			//calls the get uri() function of the MediaData class,
			//since myData is an instance of (or object of type) MediaData
			myData.uri = v;
			myData.title = t; // get title();
			myData.duration = l; // get duration();
			myData.width = w;
			myData.height = h;
			myPlayr.play(false);

		}
	}
}

I guess FLVPlayerTest(), as it’s written above, can be considered a View and a Controller in an MVC pattern. It can be a Controller, because of the handleClick() & changeVid() functions that tell the model to update itself. addBasicMenu() could be part of the Controller, since it ads a visual element whose sole purpose is to receive user input (mouse click events) and then tell the Model to update itself. Then again… it can also be part of the View, since it’s a visual component that the user sees and code associated with it can be considered to be display logic. In the MVC chapter of Advanced ActionScript 3 with Design Patterns by Joey Lott and Danny Patterson, put similar visual elements into their Controller. In their Clock example, the Controller class includes code for the button that toggles between Views and text fields that tell the Model to update itself based on user input.

If I add buttons to control play, pause, volume, those would be part of the Controller as well, if we stick with the example from Joey Lott and Danny Patterson.

Although the FLVPlayer class feels like a Controller, it’s actually the main part of the Model. If this was a middleware application, it would be the DB class, or the class that has all bulk of the app’s business logic. It would contain the CRUD methods that interact with the Database (in this case the video data source).

MediaData is part of the Model too. It encapsulates the properties of a video, like uri, image, title, duration, etc. The trackArray is part of how the View stores info from the Model, or at least, it would be, if it was coming from an external source. In real life it would be an Array of MediaData objects. I’m thinking of how in Budi Kurniawan‘s simple servlet-based MVC application a Database class (Model) grabs info from the database (external source) and instantiates objects (part of Model) that store the DB data for use by the application. In the same servlet app, the View then runs a foreach loop and populates a collection object like a List, HashMap or Vector with all the objects instantiated by the DB class.

Adding MySQL to $PATH Environment Variable on OS X

Update, 09.10.2012: This just worked for me for adding Android’s adb tool to my environment path on OS X 10.6.8. The first time I tried I got an error because I wrote “export $PATH=” instead of “export PATH=”.

Earlier this year I took some Java courses. I learned a ton from what was on the syllabus. It was exciting to see stuff like Generics in the Collections framework in JDK 1.5 and compare it to how Actionscript didn’t have that option until very recently, when the Vector class was added to AS3 for Flash Player 10.

One thing that caught me by surprise was that all software installation instructions for class materials were for Windows only (may be I was naive to expect otherwise). The professor was good but he wasn’t a Mac guy and he was super busy at his day job. A few of us OS X guys had to do extra work on our own on top of all the regular class work, just to get Eclipse, Tomcat & MySQL working on our systems. As painful as it was to spend extra days on things like “Why do I have to spend days on learning UNIX when my Java homework is due tomorrow?!!!” OR “Why do I keep getting a 404 Error for Servlets but not for JSP?! !@##$#^$%^$%^!!”… in the end, I think we ended up as slightly better developers, with a little bit more experience, because we all had to teach ourselves a little Terminal and OS X UNIX commands on the spot.

At the very least, I can always say, “Hey, at least I taught myself how to add “mysql” to the $PATH Environment Variable on OS X:

  1. launch Terminal (assuming it’s a bash shell)
  2. write ‘echo $PATH’ to see what your path is now
  3. if ‘mysql’ isn’t in there, write in the path to where you installed it via this command:
    ‘export PATH=/Users/your_user_name/your_path_to_mysql/mysql/bin:$PATH >> ~/.bash_profile’
  4. that should add it to your bash_profile
  5. write ‘echo $PATH’ again, you should see ‘mysql’ in there

Note: this is for installing MySQL as a stand alone app for use with J2EE/Java projects. If you’re just trying to do some PHP on a development machine, it’s easier to use a wysiwyg LAMP package like MAMP or XAMPP.

More on the $PATH environment variable here.

The same technique can be used to add the open source Flex SDK compiler, MXMLC, to your $PATH environment variable on OS X.

Checking out a new book for Java EE & Flex 3, published 2009

I  couldn’t find any sort of companion site url. Was I not reading carefully enough or does one not exist on purpose/due to time constraints? 

Trying out the Ch.6: Writing Java Web Applications example…  

On first try, I had a configuration problem trying to install ALL of  Spring IDE 2.2.4 plugin for Eclipse 3.4 for Java EE on OS X 10.4.11.  Here’s the error message:

2

Staying in Eclipse 3.4 I then tried to install only the Spring IDE parts specified on p.33 by doing Help > Software Updates > Available Software > Add Site  (http://springide.org/updatesite)  and the installation worked.

Note
It was quicker and easier to do this Spring MVC tutorial first, before doing Ch.6’s detailed ANT build solution. There was 1 vague area here, in the Adding Libraries section it was unclear which folders contain which .jar file. Also, the file names didn’t contain the version numbers in them. After a little digging inside /mylocalpath/spring-framework-2.5.6/, it was fine. Most were in “dist,” “lib,” or “jakarta-commons.”

Here’s a resource for going beyond the Ch.6 example: Mastering Spring MVC.