<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>masputih &#187; ActionScript 3</title>
	<atom:link href="http://masputih.com/category/as3/feed" rel="self" type="application/rss+xml" />
	<link>http://masputih.com</link>
	<description>Coder for Hire</description>
	<lastBuildDate>Mon, 24 May 2010 08:48:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Creating Drag-and-Drop for AS3 Isolib</title>
		<link>http://masputih.com/2010/05/creating-drag-and-drop-for-as3-isolib</link>
		<comments>http://masputih.com/2010/05/creating-drag-and-drop-for-as3-isolib#comments</comments>
		<pubDate>Mon, 24 May 2010 08:18:40 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>

		<guid isPermaLink="false">http://masputih.com/2010/05/creating-drag-and-drop-for-as3-isolib</guid>
		<description><![CDATA[Some folks had asked about drag-and-drop mechanism in as3isolib discussion group. While there’s no such feature built-in in the library, it’s not hard to write it yourself. So here’s a super simple class that provides that mechanism, called DragManager. I borrowed the idea from Flex’s DragManager. Note that this class is really a simple one [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Some folks had asked about drag-and-drop mechanism in <a title="AS3 Isometric Engine" href="http://code.google.com/p/as3isolib/">as3isolib</a> <a title="discussion group" href="http://tech.groups.yahoo.com/group/as3isolib/">discussion group</a>. While there’s no such feature built-in in the library, it’s not hard to write it yourself.</p>
<p>So here’s a super simple class that provides that mechanism, called DragManager. I borrowed the idea from Flex’s DragManager. Note that this class is really a simple one and it doesn’t respect “grid” so you’ll have to modify it if you want to use it in a grid-based isometric space.  Trust me, it’s not too hard <img src='http://masputih.com/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  </p>
<div id="attachment_738" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/wordpress/wp-content/uploads/2010/05/dd.swf"><img src="http://masputih.com/wordpress/wp-content/uploads/2010/05/isodd-300x223.jpg" alt="" title="DragManagerDemo" width="300" height="223" class="size-medium wp-image-738" /></a>
	<p class="wp-caption-text">Click to see the demo</p>
</div>
<p><span id="more-736"></span></p>
<p>And here’s the class:</p>
<pre class="brush:as3">
package masputih.isometric.utils
{
	import as3isolib.core.IsoDisplayObject;
	import as3isolib.display.IsoView;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;

	/**
	 * ...
	 * @author Anggie Bratadinata
	 */
	public class DragManager
	{

		private var _proxy:Sprite;
		private var _view:IsoView;
		private var _obj:IsoDisplayObject;

		public function drag(obj:IsoDisplayObject, view:IsoView):void
		{

			_view = view;
			_obj = obj;

			var bmp:Bitmap = new Bitmap(_obj.getRenderData().bitmapData)
			bmp.x = -_obj.length;
			bmp.y = -_obj.height;

			_proxy = new Sprite();
			_proxy.alpha = .5;
			_proxy.addChild(bmp);
			_proxy.addEventListener(Event.ENTER_FRAME, onProxyEnterFrame);
			_view.addChild(_proxy);

			_view.stage.addEventListener(MouseEvent.MOUSE_UP, drop);
		}

		private function onProxyEnterFrame(e:Event):void
		{
			if (_proxy != null)
			{
				_proxy.x = _view.mouseX;
				_proxy.y = _view.mouseY;
			}

		}

		private function drop(e:Event = null):void
		{
			var p:Point = new Point(_proxy.x, _proxy.y);
			p = _view.localToIso(p);

			_obj.moveTo(p.x, p.y, 0);

			//clean up
			_view.removeChild(_proxy);
			_view.stage.removeEventListener(MouseEvent.MOUSE_UP, drop);
			_proxy.removeEventListener(Event.ENTER_FRAME, onProxyEnterFrame);
			_proxy = null

		}

		public function get obj():IsoDisplayObject { return _obj; }

		/**********************************************
		 * SINGLETON CTOR
		 **********************************************/

		private static var _instance:DragManager;
		public function DragManager(enf:SingletonEnforcer)
		{

		}
		public static function getInstance():DragManager{
			if(_instance == null) _instance = new DragManager(new SingletonEnforcer());
			return _instance;
		}

	}

}

class SingletonEnforcer{};
</pre>
<h3>Sample Usage</h3>
<pre class="brush:as3">
package
{

	import as3isolib.core.IsoDisplayObject;
	import as3isolib.display.IsoView;
	import as3isolib.display.primitive.IsoBox;
	import as3isolib.display.primitive.IsoRectangle;
	import as3isolib.display.scene.IsoGrid;
	import as3isolib.display.scene.IsoScene;
	import as3isolib.graphics.SolidColorFill;
	import eDpLib.events.ProxyEvent;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import masputih.isometric.utils.DragManager;

	/**
	 * Main class
	 * @author
	 */
	public class DDTest extends Sprite
	{

		public var view:IsoView;
		public var scene:IsoScene;
		public var grid:IsoGrid;

		public function DDTest()
		{
			addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		}

		private function onAddedToStage(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);

			view = new IsoView();
			view.setSize(600, 400);
			view.showBorder = true;

			addChild(view);

			scene = new IsoScene();
			view.addScene(scene);

			grid = new IsoGrid();
			grid.cellSize = 400;
			grid.setGridSize(1, 1);

			scene.addChild(grid);

			view.pan(0, 200);

			var obj1:IsoBox = new IsoBox();
			obj1.setSize(20, 20, 20);
			obj1.moveTo(100, 100, 0);
			obj1.fill = new SolidColorFill(0xFFFF80, 1);
			obj1.container.mouseChildren = false;
			obj1.addEventListener(MouseEvent.MOUSE_DOWN, onIsoObjMouseDown);

			var obj2:IsoRectangle = new IsoRectangle();
			obj2.setSize(20, 20,0);
			obj2.moveTo(200, 100, 0);
			obj2.fill = new SolidColorFill(0x0080FF, 1);
			obj2.container.mouseChildren = false;
			obj2.addEventListener(MouseEvent.MOUSE_DOWN, onIsoObjMouseDown);

			var obj3:IsoBox = new IsoBox();
			obj3.setSize(20, 40,30);
			obj3.moveTo(200, 200, 0);
			obj3.fill = new SolidColorFill(0x800040, 1);
			obj3.container.mouseChildren = false;
			obj3.addEventListener(MouseEvent.MOUSE_DOWN, onIsoObjMouseDown);

			scene.addChild(obj1);
			scene.addChild(obj2);
			scene.addChild(obj3);

			stage.addEventListener(Event.ENTER_FRAME, render);
		}

		private function onIsoObjMouseDown(e:ProxyEvent):void
		{
			DragManager.getInstance().drag(IsoDisplayObject(e.target), view);
		}

		private function render(e:Event):void
		{
			view.render(true);
		}

	}

}</pre>
<p>Hope you like it!</p>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2010/05/creating-drag-and-drop-for-as3-isolib/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Array Paginator Class</title>
		<link>http://masputih.com/2010/03/array-paginator-class</link>
		<comments>http://masputih.com/2010/03/array-paginator-class#comments</comments>
		<pubDate>Thu, 25 Mar 2010 13:17:23 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[Freebies]]></category>
		<category><![CDATA[actionscript]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=729</guid>
		<description><![CDATA[Here’s a class to paginate an Array with convenient functions like pageUp(), pageDown(), peek(), etc. package { /** * * @author Anggie Bratadinata */ public class ArrayPaginator { private var _target:Array; private var _pageSize:int = 0; private var _totalPage:int = 0; private var _pageIndex:int = 0; private var _currentPage:Array; private var _targetLength:int; private var _pagedArray:Array; [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Here’s a class to paginate an Array with convenient functions like <code>pageUp()</code>, <code>pageDown()</code>, <code>peek()</code>, etc.</p>
<p><span id="more-729"></span></p>
<pre class="brush:as3" >
package
{

	/**
	 *
	 * @author Anggie Bratadinata
	 */
	public class ArrayPaginator
	{
		private var _target:Array;
		private var _pageSize:int = 0;
		private var _totalPage:int = 0;

		private var _pageIndex:int = 0;
		private var _currentPage:Array;
		private var _targetLength:int;
		private var _pagedArray:Array;

		public function ArrayPaginator()
		{

		}

		/**
		 * Build a paginated array using a copy of the target array and return the first page.
		 * Later modifications to the target array will not be reflected unless this function is revoked.
		 *
		 * @param	target				The array to be paginated
		 * @param	pageSize			The number of items in each page
		 * @param 	forceFullContent	Force all pages to contain equal number of items
		 * @param	pageFiller			Object to fill a page that has less number of items than the intended page size. Ignored if forceFullContent is false.
		 * @return
		 */
		public function paginate(target:Array, pageSize:int = 1, forceFullContent:Boolean = false, pageFiller:* = null):Array
		{

			if (pageSize < 1) {
				throw new ArgumentError("pageSize can't be less than 1");
				return;
			}

			_target = target.concat();
			_targetLength = _target.length;
			_pageSize = pageSize;

			_totalPage = Math.ceil(_targetLength / _pageSize);

			if (forceFullContent)
			{
				var fillCount:int = (_totalPage * _pageSize) - _targetLength;

				if (fillCount > 0)
				{
					for (var j:int = 0; j < fillCount; j++)
					{
						_target.push(pageFiller);
					}

					_targetLength = _target.length;
				}
			}

			_pagedArray = [];

			for (var i:int = 0; i < _targetLength; i = i + _pageSize )
			{
				var sub:Array = _target.slice(i, i + _pageSize);
				_pagedArray.push(sub);
			}

			return firstPage;

		}

		/**
		 * Go to a page and get its content.
		 *
		 * @param	pageNum		Page number from 1 to total page.
		 * @return 	Array Page content
		 */
		public function getPage(pageNum:int):Array
		{
			var idx:int = pageNum - 1;
			var a:Array = _pagedArray[idx];

			if (a != null)
			{
				_pageIndex = idx;
				_currentPage = a;
			}

			return a;
		}

		/**
		 * Go to the next page and get its content.
		 * @return Array
		 */
		public function pageUp():Array
		{
			if (currentPageNum == _totalPage)
			{
				return currentPage;
			}

			return getPage(currentPageNum + 1);
		};

		/**
		 * Go to the previous page and get its content.
		 * @return Array
		 */
		public function pageDown():Array
		{
			if (currentPageNum == 1)
			{
				return currentPage;
			}

			return getPage(currentPageNum - 1);
		};

		/**
		 * Get the content of the last page without moving the page pointer.
		 * @return Array
		 */
		public function peekLast():Array
		{
			return peekPage(_totalPage);
		}

		/**
		 * Get the content of the first page without moving the page pointer.
		 * @return Array
		 */
		public function peekFirst():Array
		{
			return peekPage(1);
		}

		/**
		 * Get the content of the next page without moving the page pointer.
		 * @return Array
		 */
		public function peekUp():Array
		{
			return peekPage(currentPageNum + 1);
		}

		/**
		 * Get the content of the previous page without moving the page pointer.
		 * @return Array
		 */
		public function peekDown():Array
		{
			return peekPage(currentPageNum - 1);
		}

		/**
		 * Get the content of a page without moving the page pointer.
		 * @param 	pageNum  Page number from 1 to total page
		 * @return Array
		 */
		public function peekPage(pageNum:int):Array
		{
			var p:Array = _pagedArray[pageNum - 1];
			return p;
		}

		/**
		 * Get all pages.
		 * @return Array
		 */
		public function get pages():Array
		{
			return _pagedArray;
		}

		/**
		 * Go to the last page and get the content
		 * @return Array The page content
		 */
		public function get lastPage():Array
		{
			return getPage(_totalPage);
		};

		/**
		 * Go to the first page and get the content
		 * @return Array The page content
		 */
		public function get firstPage():Array
		{
			return getPage(1);
		};

		/**
		 * Get the current page number
		 */
		public function get currentPageNum():int
		{
			return _pageIndex + 1;
		}

		/**
		 * Get the total number of pages.
		 */
		public function get totalPage():int
		{
			return _totalPage;
		}

		/**
		 * Get the content of the current page.
		 * @return Array
		 */
		public function get currentPage():Array
		{
			return _currentPage;
		}

		/**
		 * True if the current page is the last page
		 */
		public function get isLast():Boolean
		{
			return (currentPageNum == _totalPage);
		}

		/**
		 * True if the current page is the first page
		 */
		public function get isFirst():Boolean
		{
			return (currentPageNum == 1);
		}
	}

}
</pre>
<h4>Sample Usage</h4>
<pre class="brush:as3">
private function onAddedToStage(e:Event):void
{
	removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);

	target = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
	paginator = new ArrayPaginator();
	trace("first page " + paginator.paginate(target, 4));
	trace("num of pages " + paginator.totalPage);

	timer = new Timer(3000);
	timer.addEventListener(TimerEvent.TIMER, onTimer);
	timer.start();
}

public var isUp:Boolean = true;

private function onTimer(e:TimerEvent):void
{
	if (paginator.isFirst) {
		isUp = true;
	} else	if(paginator.isLast) {
		isUp = false;
	}

	if (isUp) {
		paginator.pageUp() ;
	}else {
		paginator.pageDown();
	}
	trace('/-------/');
	trace("page " + paginator.currentPageNum + " : " + paginator.currentPage.join(','));
	trace("next page " + paginator.peekUp());
	trace("prev page " + paginator.peekDown());
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2010/03/array-paginator-class/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scattered Gallery</title>
		<link>http://masputih.com/2009/12/scattered-gallery</link>
		<comments>http://masputih.com/2009/12/scattered-gallery#comments</comments>
		<pubDate>Mon, 14 Dec 2009 14:21:48 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[Freebies]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=660</guid>
		<description><![CDATA[A free flash gallery with randomly distributed pictures. Written in pure AS3. Compiled with Flex SDK. Uses an XML to specify image URLs and caption text Click on an empty space to randomly redistribute the pictures. Click on a picture to see it in its real size. Click on it again to scale it down. [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>A free flash gallery with randomly distributed pictures. Written in pure AS3. Compiled with Flex SDK.</p>
<ul>
<li>Uses an XML to specify image URLs and caption text</li>
<li>Click on an empty space to randomly redistribute the pictures.</li>
<li>Click on a picture to see it in its real size. Click on it again to scale it down.</li>
<li>Pictures are draggable.</li>
</ul>
<p><span id="more-660"></span><br />
The main code is free to use for any purpose. No warranty. Feel free to ask if you have any questions.</p>
<p>Note that this application uses 3rd-party libraries (TweenLite and MonsterDebugger). Please consult their licenses as well.</p>
<div id="attachment_661" class="wp-caption aligncenter" style="width: 355px">
	<a href="http://labs.masputih.com/scattered-gallery/" rel="shadowbox"><img src="http://masputih.com/wordpress/wp-content/uploads/2009/12/scattered-gallery.jpg" alt="Click to view the demo" title="Scattered Gallery" width="355" height="328" class="size-full wp-image-661" /></a>
	<p class="wp-caption-text">Click to view the demo</p>
</div>
<blockquote>
<h4>Download</h4>
<a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=scattered-gallery.zip" title="Downloaded 199 times">→ Scattered Gallery</a></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/12/scattered-gallery/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tracking Aplikasi Flash dengan Google Analytics</title>
		<link>http://masputih.com/2009/11/tracking-aplikasi-flash-dengan-google-analytics</link>
		<comments>http://masputih.com/2009/11/tracking-aplikasi-flash-dengan-google-analytics#comments</comments>
		<pubDate>Sat, 28 Nov 2009 04:25:24 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[actionscript]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=558</guid>
		<description><![CDATA[GA for Flash adalah library AS3 yang bisa kita gunakan untuk mengumpulkan data untuk Google Analytics. Library ini sangat gampang dipakai. Kita tinggal membuat objek Tracker dan mengeksekusi tracker.trackPageView(/data/yang/ingin/di/kirim/ke/ga). Berikut ini contoh GA report yang menampilkan hasil tracking mp3 yang dimainkan oleh sebuah aplikasi mp3 player. Contoh code nya: private function init(e:Event):void { removeChild(preloader); if [...]]]></description>
			<content:encoded><![CDATA[<p></p><p><a href="http://code.google.com/p/gaforflash/">GA for Flash</a> adalah library AS3 yang bisa kita gunakan untuk mengumpulkan data untuk Google Analytics. Library ini sangat gampang dipakai. Kita tinggal membuat objek Tracker dan mengeksekusi <code>tracker.trackPageView(/data/yang/ingin/di/kirim/ke/ga)</code>.</p>
<p>Berikut ini contoh GA report yang menampilkan hasil tracking mp3 yang dimainkan oleh sebuah aplikasi mp3 player.</p>
<p><a href="http://masputih.com/uploads/2009/11/ga-report.jpg" rel="shadowbox"><img src="http://masputih.com/uploads/2009/11/ga-report-300x274.jpg" alt="ga-report" title="ga-report" width="300" height="274" class="aligncenter size-medium wp-image-559" /></a></p>
<p><span id="more-558"></span></p>
<p>Contoh code nya:</p>
<pre class="brush:as3">
private function init(e:Event):void
{
	removeChild(preloader);

	if (ExternalInterface.available) {
		tracker = new GATracker( this, "window.pageTracker", "Bridge", true );
	}

	mp3Player.addEventListener("songComplete", onSongComplete);
}

private function onSongComplete(e:Event):void
{

	var song:Object = mp3Player.song;
	try {
		tracker.trackPageview('/'+song.artist + '/' + song.album + '/' + song.name);
	}catch (e:Error) { };
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/11/tracking-aplikasi-flash-dengan-google-analytics/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bekerja dengan FlashDevelop, Flex SDK, dan Flash</title>
		<link>http://masputih.com/2009/07/flashdevelop-flex-sdk-flash</link>
		<comments>http://masputih.com/2009/07/flashdevelop-flex-sdk-flash#comments</comments>
		<pubDate>Wed, 15 Jul 2009 06:59:25 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[practice]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=482</guid>
		<description><![CDATA[Dalam artikel kali ini saya jelaskan cara bekerja dengan FlashDevelop, Flex SDK, dan Flash CS3/4. Flex SDK saya pakai untuk kompilasi proyek karena jauh lebih cepat daripada compiler bawaan Flash IDE. Di sini, Flash IDE saya gunakan untuk membuat library berisi objek visual, atau biasa disebut asset library. SWF yg saya buat dengan Flash IDE [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Dalam artikel kali ini saya jelaskan cara bekerja dengan FlashDevelop, Flex SDK, dan Flash CS3/4. Flex SDK saya pakai untuk kompilasi proyek karena jauh lebih cepat daripada <em>compiler</em> bawaan Flash IDE.</p>
<p>Di sini, Flash IDE saya gunakan untuk membuat <em>library</em> berisi objek visual, atau biasa disebut <em>asset library</em>. SWF yg saya buat dengan Flash IDE hanya berisi sedikit kode atau malah nggak ada kode sama sekali. Kode program utama saya buat dengan FlashDevelop dan saya kompilasi dengan Flex <em>compiler</em>.</p>
<p>Ada 2 cara untuk menggabungkan <em>asset library</em> dengan program utama yaitu:</p>
<p><span id="more-482"></span></p>
<ol>
<li>Dengan teknik <em>embedding</em> dimana SWF yang berisi aset dikompilasi jadi satu dengan program utama</li>
<li><em>Runtime asset</em> dimana SWF yang berisi aset dibuat terpisah dari program utama dan nanti dimuat pada saat program dijalankan.</li>
</ol>
<p>Kalo Anda ingin nyoba sendiri, pastikan dulu instalasi FlashDevelop sudah benar &amp; <em>path</em> Flex SDK sudah diset melalui menu Tools-&gt;Program Settings-&gt;AS3 Context.</p>
<p>Berikut ini direktori project yang saya buat di FlashDevelop.</p>
<p><a href="http://masputih.com/uploads/2009/07/proj-folder.jpg"><img src="http://masputih.com/uploads/2009/07/proj-folder.jpg" alt="proj-folder.jpg" title="proj-folder.jpg" width="281" height="228" class="aligncenter size-full wp-image-479" /></a></p>
<h3>Embedding</h3>
<p>Di dalam direktori /embedded/ saya buat sebuah file .fla yang berisi asset yang akan saya gunakan.</p>
<p>Ada dua MovieClip di dalamnya, masing-masing punya dynamic textfield dengan nama instance labelTxt. Keduanya juga saya beri linkage name sesuai dengan nama symbolnya.</p>
<p><a href="http://masputih.com/uploads/2009/07/symbols-1.jpg"><img src="http://masputih.com/uploads/2009/07/symbols-1.jpg" alt="symbols-1.jpg" title="symbols-1.jpg" width="353" height="244" class="aligncenter size-full wp-image-480" /></a></p>
<p>Setelah saya publish file embed-library.fla, FlashDevelop bisa mengenali <em>linkage</em> kedua symbol tersebut.</p>
<p><a href="http://masputih.com/uploads/2009/07/linkage.jpg"><img src="http://masputih.com/uploads/2009/07/linkage.jpg" alt="linkage.jpg" title="linkage.jpg" width="459" height="214" class="aligncenter size-full wp-image-481" /></a></p>
<p>Kemudian saya buat class <code>BlueSquare</code> dengan <code>labelTxt</code> bertipe <code>flash.text.TextField</code>, sama persis dengan instance yang saya buat di Flash. </p>
<p>Saya letakkan cursor di atas baris <code>public class ...</code> , lalu saya klik kanan simbol <code>Blue</code> di project folder dan klik <em>Insert into document</em>. Hasilnya seperti berikut:</p>
<div id="attachment_488" class="wp-caption aligncenter" style="width: 528px">
	<a href="http://masputih.com/2009/07/flashdevelop-flex-sdk-flash/embed-symbol" rel="attachment wp-att-488"><img src="http://masputih.com/uploads/2009/07/embed-symbol.jpg" alt="Insert into Document" title="embed-symbol" width="528" height="471" class="size-full wp-image-488" /></a>
	<p class="wp-caption-text">Insert into Document</p>
</div>
<p>Kemudian saya buat juga class <code>GreenSquare</code> dengan langkah-langkah sama seperti di atas, tapi yang di–<em>embed</em> adalah simbol <code>Green</code>. </p>
<p>Saya buat instance kedua class tersebut di Main.as.</p>
<pre class="brush:as3">
package
{
	import flash.display.Sprite;
	import flash.events.Event;

	public class Main extends Sprite{

		public function Main():void{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point

			var blue:BlueSquare = new BlueSquare();
			blue.labelTxt.text = "I'm blue";
			addChild(blue);

			var green:GreenSquare = new GreenSquare();
			green.x = blue.width + 10;
			green.labelTxt.text = "I'm green";
			addChild(green);

		}
	}
}
</pre>
<p>Hasilnya:</p>
<div id="attachment_497" class="wp-caption aligncenter" style="width: 369px">
	<a href="http://masputih.com/2009/07/flashdevelop-flex-sdk-flash/embed-output" rel="attachment wp-att-497"><img src="http://masputih.com/uploads/2009/07/embed-output.jpg" alt="Test Movie di FD" title="Hasil Test Movie " width="369" height="141" class="size-full wp-image-497" /></a>
	<p class="wp-caption-text">Test Movie di FD</p>
</div>
<h3>Runtime Asset</h3>
<p>Saya buat file xtlibrary.fla di dalam folder /src/ di FD. SWF hasil kompilasi file ini berisi aset yang akan saya muat pada saat runtime. </p>
<p>Di dalam file ini ada dua simbol mirip dengan file embed-library.fla, tapi berwarna merah dan hitam. Masing-masing simbol saya hubungkan dengan class di dalam folder /flashlib/ — sering disebut <em>Bound Class</em>. Karena kedua class ini berhubungan dengan simbol di .fla, maka saya nggak perlu menggunakan <em>tag</em> <code>[Embed ...]</code> seperti contoh sebelumnya. </p>
<p>Berikut ini seting linkage dari kedua simbol tersebut.</p>
<div id="attachment_502" class="wp-caption aligncenter" style="width: 331px">
	<a href="http://masputih.com/2009/07/flashdevelop-flex-sdk-flash/flashlib-export" rel="attachment wp-att-502"><img src="http://masputih.com/uploads/2009/07/flashlib-export.jpg" alt="Export Setting" title="flashlib-export" width="331" height="260" class="size-full wp-image-502" /></a>
	<p class="wp-caption-text">Export Setting</p>
</div>
<div id="attachment_503" class="wp-caption aligncenter" style="width: 500px">
	<a href="http://masputih.com/2009/07/flashdevelop-flex-sdk-flash/flashlib-linkage" rel="attachment wp-att-503"><img src="http://masputih.com/uploads/2009/07/flashlib-linkage.jpg" alt="Linkage dan Bound Class" title="flashlib-linkage" width="500" height="178" class="size-full wp-image-503" /></a>
	<p class="wp-caption-text">Linkage dan Bound Class</p>
</div>
<p>Supaya simbol tersebut bisa dikenali oleh SWF utama, saya harus meletakkan keduanya di stage dan memberinya nama instance seperti ini:</p>
<div id="attachment_506" class="wp-caption aligncenter" style="width: 457px">
	<a href="http://masputih.com/2009/07/flashdevelop-flex-sdk-flash/flashlib-instance-name" rel="attachment wp-att-506"><img src="http://masputih.com/uploads/2009/07/flashlib-instance-name.jpg" alt="Stage Instance" title="flashlib-instance-name" width="457" height="143" class="size-full wp-image-506" /></a>
	<p class="wp-caption-text">Stage Instance</p>
</div>
<p>File xtlibrary.fla saya publish ke dalam folder di mana SWF utama dari project ini ( fd.swf ) berada yaitu di folder /bin/. Hasilnya seperti gambar berikut:</p>
<div id="attachment_505" class="wp-caption aligncenter" style="width: 247px">
	<a href="http://masputih.com/2009/07/flashdevelop-flex-sdk-flash/xtlibarary-publish" rel="attachment wp-att-505"><img src="http://masputih.com/uploads/2009/07/xtlibarary-publish.jpg" alt="Library SWF" title="xtlibarary-publish" width="247" height="384" class="size-full wp-image-505" /></a>
	<p class="wp-caption-text">Library SWF</p>
</div>
<p>Saya tambahkan beberapa baris kode ke dalam Main class untuk memuat file xtlibrary.swf dan mengakses simbol di atas serta membuat objek Black &amp; Red lalu menampilkannya ( mulai baris 36 ).</p>
<pre class="brush:as3">
package
{
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	import flashlib.BlackSquare;
	import flashlib.RedSquare;

	public class Main extends Sprite{

		public function Main():void{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point

			var blue:BlueSquare = new BlueSquare();
			blue.labelTxt.text = "I'm blue";
			addChild(blue);

			var green:GreenSquare = new GreenSquare();
			green.x = blue.width + 10;
			green.labelTxt.text = "I'm green";
			addChild(green);

			var ctx:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);

			var ldr:Loader = new Loader();
			ldr.contentLoaderInfo.addEventListener(Event.INIT, onLoadInit);
			ldr.load(new URLRequest("xtlibrary.swf"), ctx);

		}

		private function onLoadInit(e:Event):void {

			var assetLib:MovieClip = LoaderInfo(e.target).content as MovieClip;

			var redClassName:String = getQualifiedClassName(assetLib['red']);
			var redClassRef:* = getDefinitionByName(redClassName);

			var red:RedSquare = new redClassRef() as RedSquare;
			red.labelTxt.text = "I'm red";
			red.y = 100;
			addChild(red);

			var blackClassName:String = getQualifiedClassName(assetLib['black']);
			var blackClassRef:* = getDefinitionByName(blackClassName);

			var black:BlackSquare = new blackClassRef() as BlackSquare;
			black.labelTxt.text = "I'm black";
			black.y = 100;
			black.x = red.width + 10;
			addChild(black);
		}
	}
}
</pre>
<p>Di dalam kode di atas, saya mengakses instance kedua simbol melalui nama stage instance mereka seperti ini :</p>
<pre class="codeblock"><code>assetLib['red']
assetLib['black']
</code></pre>
<p>Hasil test movie :</p>
<div id="attachment_507" class="wp-caption aligncenter" style="width: 369px">
	<a href="http://masputih.com/2009/07/flashdevelop-flex-sdk-flash/xt-output" rel="attachment wp-att-507"><img src="http://masputih.com/uploads/2009/07/xt-output.jpg" alt="Test Movie dgn library eksternal" title="xt-output" width="369" height="141" class="size-full wp-image-507" /></a>
	<p class="wp-caption-text">Test Movie dgn library eksternal</p>
</div>
<p>Oke, gitu cara saya kerja kalo saya perlu pakai aset yang dibuat dengan Flash.<br />
Semoga bermanfaat. Contoh projectnya bisa diunduh di bawah ini :</p>
<div class="box dl_box"><a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=fd.rar" title="Downloaded 158 times">→ FD-library.rar</a></div>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/07/flashdevelop-flex-sdk-flash/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Auto-scroll Text Area</title>
		<link>http://masputih.com/2009/06/auto-scroll-text-area</link>
		<comments>http://masputih.com/2009/06/auto-scroll-text-area#comments</comments>
		<pubDate>Tue, 02 Jun 2009 10:20:18 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[component]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=469</guid>
		<description><![CDATA[Berikut ini contoh kode untuk membuat scrollbar komponen fl.controls.TextArea otomatis bergerak ke bawah kalo ada penambahan teks sehingga baris-baris terbaru selalu kelihatan. package { import fl.controls.Button; import fl.controls.TextArea; import fl.controls.TextInput; import fl.events.ComponentEvent; import flash.display.MovieClip; import flash.events.Event; import flash.events.MouseEvent; public class Main extends MovieClip { public var console:TextArea; public var input:TextInput public function Main() { console.text [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Berikut ini contoh kode untuk membuat <em>scrollbar</em> komponen <code>fl.controls.TextArea</code> otomatis bergerak ke bawah kalo ada penambahan teks sehingga baris-baris terbaru selalu kelihatan.</p>
<p><a href="http://labs.masputih.com/autoscroll_ta/index.html" rel="shadowbox"><img src="http://masputih.com/uploads/2009/06/autoscroll1.jpg" alt="autoscroll" title="autoscroll" width="420" height="333" class="aligncenter size-full wp-image-475" /></a></p>
<p><span id="more-469"></span></p>
<pre class="brush:as3">
package  {

	import fl.controls.Button;
	import fl.controls.TextArea;
	import fl.controls.TextInput;
	import fl.events.ComponentEvent;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;

	public class Main extends MovieClip {

		public var console:TextArea;
		public var input:TextInput

		public function Main() {

			console.text = "A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\n";

			console.addEventListener(Event.RENDER, updateScrollPosition);

			input.addEventListener(ComponentEvent.ENTER, addText);

		}

		private function updateScrollPosition(e:Event):void {
			console.verticalScrollPosition = console.maxVerticalScrollPosition;
		}

		private function addText(e:Event):void {
			if (input.length > 0 ) {
				console.appendText(input.text + "\n");
			}
		}

	}

}
</pre>
<div class="box dl_box">
Sourcecode : <a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=autoscrolltextarea.rar" title="Downloaded 380 times">→ AutoScrollTextArea.rar</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/06/auto-scroll-text-area/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Factory Pattern</title>
		<link>http://masputih.com/2009/05/factory-pattern</link>
		<comments>http://masputih.com/2009/05/factory-pattern#comments</comments>
		<pubDate>Wed, 06 May 2009 10:53:00 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[pattern]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=354</guid>
		<description><![CDATA[Factory Pattern adalah pattern yang digunakan untuk memisahkan (decouple) proses pembuatan/instansiasi sebuah objek (produk) dari objek lain (klien) yang menggunakannya. Tujuannya supaya perubahan pada product class nggak menyebabkan kita harus mengubah kode pada client. Paling nggak akibat dari perubahan itu bisa diminimalisir. Dan juga supaya si factory bisa digunakan oleh banyak class. Factory adalah objek [...]]]></description>
			<content:encoded><![CDATA[<p></p><p><em>Factory Pattern</em> adalah pattern yang digunakan untuk memisahkan (<em>decouple</em>) proses pembuatan/instansiasi sebuah objek (produk) dari objek lain (klien) yang menggunakannya. Tujuannya supaya perubahan pada <em>product class</em> nggak menyebabkan kita harus mengubah kode pada <em>client</em>. Paling nggak akibat dari perubahan itu bisa diminimalisir. Dan juga supaya si <em>factory</em> bisa digunakan oleh banyak class.</p>
<p><em>Factory</em> adalah objek yang berfungsi membuat objek lain (produk). Class ini menyembunyikan proses pembuatan produk dari klien sehingga klien nggak perlu tahu proses pembuatannya, bahkan klien juga nggak perlu tahu nama class dari produk yang dia minta.</p>
<p>Mungkin kita sering menulis function seperti ini: </p>
<pre class="codeblock">
<code>
var coffee:AbstractCoffee = createCoffee("xxx");
function createCoffee(type:String):Coffee{
        if(type == "xxx" ) return new XXXCoffee();
        if(type == "yyy" ) return new YYYCoffee();
        if(type == "zzz" ) return new ZZZCoffee();
        return null;
}</code>
</pre>
<p>Cukup bagus untuk proyek kecil. Tapi coba bayangin kalo kita punya 20 class yang harus bisa bikin kopi dan semuanya harus bisa ditukar-tukar saat <em>run-time</em> plus si produk kemungkinan besar bakal berubah. Repot. Di sini gunanya Factory Pattern.</p>
<p><span id="more-354"></span></p>
<p>Factory Pattern memungkinkan instansiasi sebuah produk didelegasikan ke subclass (<em>concrete factory</em>) dari <em>base-class</em> yang bersifat generik (abstrak) . Keuntungannya adalah si klien hanya perlu tau generik classnya, jadi <em>concrete factory</em> bisa ditukar-tukar secara dinamis (polymorfis) tergantung produk apa yang dibutuhkan dan klien nggak perlu tau detil pembuatan produk.</p>
<div id="attachment_353" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/factory-pattern/factory-methodjpg" rel="attachment wp-att-353"><img src="http://masputih.com/uploads/2009/05/factory-method-300x32.jpg" alt="Diagram Dasar Factory" title="factory-method.jpg" width="300" height="32" class="size-medium wp-image-353" /></a>
	<p class="wp-caption-text">Diagram Dasar Factory</p>
</div>
<p>Ada 2 varian factory pattern yaitu :</p>
<ol>
<li>Factory Method</li>
<li>Abstract Factory</li>
</ol>
<h3>Factory Method (FM)</h3>
<blockquote><p>Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses. (wikipedia)</p>
<p>Factory Method is similar to Abstract Factory but without the emphasis on families. (sourcemaking.com)</p>
</blockquote>
<div id="attachment_360" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/factory-pattern/factorymethod-class-diagram" rel="attachment wp-att-360"><img src="http://masputih.com/uploads/2009/05/factorymethod-class-diagram-300x221.jpg" alt="Factory Method" title="factorymethod-class-diagram" width="300" height="221" class="size-medium wp-image-360" /></a>
	<p class="wp-caption-text">Factory Method</p>
</div>
<p>Dalam <em>Factory Method</em>, setiap <em>concrete factory</em> bertugas membuat satu produk. Jadi ada pemetaaan 1–1 antara <em>factory</em> dan produk yang dibuatnya. Klien menggunakan <em>abstract factory</em> untuk membuat objek tapi jenis objek itu ditentukan oleh <em>concrete factory</em> yang dipilih.</p>
<p>Contoh:</p>
<pre class="brush:as3">
public class Main extends Sprite{

	public var factory:AbstractFactory;
	public var product:AbstractProduct;

	public function Main():void{

		factory = new ABCFactory();
		product = factory.createProduct();

		factory = new DEFFactory();
		product = factory.createProduct();

		factory = new XYZFactory();
		product = factory.createProduct();

	}
}

//abstract factory
public class AbstractFactory {

	public function AbstractFactory() {}

	public function createProduct():AbstractProduct {
		throw new IllegalOperationError("Abstract method. Must be implemented in subclass");
		return null;
	}

}

//abstract product
public class AbstractProduct {
	public function AbstractProduct() {}
}

//concrete factories
public class ABCFactory extends AbstractFactory {
	override public function createProduct():AbstractProduct {
		return new ProductABC();
	}
}
public class DEFFactory extends AbstractFactory {
	override public function createProduct():AbstractProduct {
		return new ProductDEF();
	}
}

//concrete products
public class ProductABC extends AbstractProduct{
	public function ProductABC() {
		trace("ProductABC created");
	}
}

public class ProductDEF extends AbstractProduct {
	public function ProductDEF() {
		trace("ProductDEF created");
	}
}
</pre>
<p>Output:</p>
<pre class="codeblock"><code>
ProductABC created
ProductDEF created

</code></pre>
<p>Dalam contoh di atas, kalo class ProductABC berubah, misalnya konstruktornya harus kita beri parameter “id”, kita nggak perlu utak-atik class Main. Cukup kita modifikasi ABCFactory. Contohnya gini :</p>
<pre class="brush:as3">
public class ProductABC extends AbstractProduct{
	public function ProductABC(id:String) {
		trace("ProductABC created with id " + id);
	}
}

public class ABCFactory extends AbstractFactory {
	override public function createProduct():AbstractProduct {
		var id:String = String(Math.round(Math.random() * 10));
		return new ProductABC(id);
	}
}
</pre>
<pre class="codeblock"><code>
ProductABC created with id 8
ProductDEF created

</code></pre>
<h3>Abstract Factory (AF)</h3>
<blockquote><p>The intent in employing the pattern is to insulate the creation of objects from their usage. This allows for new derived types to be introduced with no change to the code that uses the base class. (wikipedia)</p>
<p>Abstract Factory emphasizes a family of product objects. (sourcemaking.com)</p>
</blockquote>
<div id="attachment_361" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/uploads/2009/05/abstract-factory-class-diagram.jpg" rel="shadowbox"><img src="http://masputih.com/uploads/2009/05/abstract-factory-class-diagram-300x203.jpg" alt="Abstract Factory" title="abstract-factory-class-diagram" width="300" height="203" class="size-medium wp-image-361" /></a>
	<p class="wp-caption-text">Abstract Factory</p>
</div>
<p>Perbedaan utama antara Abstract Factory dengan Factory Method adalah dalam pemetaan antara <em>factory</em> dengan produk. Dalam AF, satu factory bisa membuat banyak produk yang sekelompok.</p>
<p>Biar lebih gampang dipahami, saya buat aplikasi sederhana berikut ini.</p>
<h3>Demo : Warung Factory</h3>
<div class="wp-caption aligncenter" style="width: 295px">
	<a href="http://labs.masputih.com/patterns/abstractfactory/index.html" rel="shadowbox"><img alt="Click to see the demo" src="http://labs.masputih.com/patterns/abstractfactory/screenshot.jpg" title="Warung Factory" width="295" height="244" /></a>
	<p class="wp-caption-text">Click to see the demo</p>
</div>
<div id="attachment_384" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/factory-pattern/warung" rel="attachment wp-att-384"><img src="http://masputih.com/uploads/2009/05/warung-300x224.jpg" alt="Class Diagram" title="warung" width="300" height="224" class="size-medium wp-image-384" /></a>
	<p class="wp-caption-text">Class Diagram</p>
</div>
<div class="box dl_box">Project files : <a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=abstractfactory.rar" title="Downloaded 468 times">→ AbstractFactory.rar</a></div>
<h4>Factory</h4>
<pre class="brush:as3">package factory {

	import product.AbstractProduct;
	import flash.errors.IllegalOperationError;

	public class AbstractFactory {

		public function AbstractFactory(name:String) {
			trace("Pesan makanan/minuman di " + name);
		}

		public function createProduct(type:String):AbstractProduct {
			throw new IllegalOperationError("Abstract method. Must be implemented in subclass.");
		}

		public function getProducts():Array {
			throw new IllegalOperationError("Abstract method. Must be implemented in subclass.");
		}

	}

}
</pre>
<p>Berikut ini turunannya, yaitu concrete factory yang akan membuat produk berdasarkan pilihan menu.</p>
<pre class="brush:as3">
//WarungBuTini.as
package factory {
	import product.AbstractProduct;
	import product.NasiRawon;
	import product.KopiSusu;
	import product.SodaGembira;

	public class WarungBuTini extends AbstractFactory{

		public static const NAME:String = "Warung Bu Tini";

		public function WarungBuTini() {
			super(NAME);
		}

		override public function createProduct(type:String):AbstractProduct {

			if (type == SodaGembira.NAME) return new SodaGembira(NAME,"4500");
			if (type == NasiRawon.NAME) return new NasiRawon(NAME, "8000");
			if (type == KopiSusu.NAME) return new KopiSusu(NAME, "6000");

			throw Error("Invalid product type");
			return null;
		}

		override public function getProducts():Array {
			return [SodaGembira.NAME,NasiRawon.NAME,KopiSusu.NAME];
		}

	}

}

//DepotAgung.as
package factory {
	import product.AbstractProduct;
	import product.NasiGoreng;
	import product.PangsitMie;
	import product.SodaGembira;

	public class DepotAgung extends AbstractFactory{

		public static const NAME:String = "Depot Agung";

		public function DepotAgung() {
			super(NAME);
		}

		override public function createProduct(type:String):AbstractProduct {
			if (type == NasiGoreng.NAME) return new NasiGoreng(NAME, "5500");
			if (type == PangsitMie.NAME) return new PangsitMie(NAME, "4000");
			if (type == SodaGembira.NAME) return new SodaGembira(NAME, "3000");

			throw Error("Invalid product type");
			return null;
		}

		override public function getProducts():Array {
			return [NasiGoreng.NAME,PangsitMie.NAME,SodaGembira.NAME];
		}

	}

}
</pre>
<h4>Product</h4>
<pre class="brush:as3">package product {
	import flash.display.Sprite;
	import flash.text.TextField;

	public class AbstractProduct extends Sprite{

		//timeline objects
		public var productName:TextField;
		public var price:TextField;
		public var factoryName:TextField;

		public function AbstractProduct(productName:String,price:String,factoryName:String) {
			this.productName.text = productName;
			this.price.text = "Rp " + price;
			this.factoryName.text = factoryName;
			trace("Beli " + productName + " di " + factoryName);
		}

		public function pay():void{
			trace("Bayar " + price.text + " ke " + factoryName.text);
		}

	}

}
</pre>
<p>Concrete Factory akan membuat objek dari concrete product dan mengirimkannya ke klien ( <code>Main</code> )<br />
Berikut ini <em>concrete product </em>nya</p>
<pre class="brush:as3">
//NasiGoreng.as
package product {

	[Embed(source='../assets/assets.swf', symbol='NasGor')]
	public class NasiGoreng extends AbstractProduct {

		public static const NAME:String = "Nasi Goreng";

		public function NasiGoreng(factoryName:String,price:String = "7000") {
			super(NAME,price,factoryName)
		}

	}

}

//SodaGembira.as
package product {

	[Embed(source='../assets/assets.swf', symbol='Sogem')]
	public class SodaGembira extends AbstractProduct {

		public static const NAME:String = "Soda Gembira";

		public function SodaGembira(factoryName:String,price:String = "5000") {
			super(NAME, price, factoryName);
		}

	}

}
</pre>
<h4>Main class</h4>
<pre class="brush:as3">package
{
	import factory.AbstractFactory;
	import factory.DepotAgung;
	import factory.WarungBuTini;
	import factory.WarungPakJaja;
	import product.AbstractProduct;
	import fl.controls.ComboBox;
	import fl.controls.List;
	import flash.display.Sprite;
	import flash.events.Event;

	public class Main extends Sprite{

		public function Main():void{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		private var _productPic:Sprite;
		private var _selector:FactorySelector;

		//main class hanya pakai base/abstract class, bukan concrete class
		private var _factory:AbstractFactory;
		private var _product:AbstractProduct;

		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);

			//_factory &#038; _products _selector
			_selector = new FactorySelector();
			addChild(_selector);

			_selector.factories.addEventListener(Event.CHANGE, selectFactory);
			_selector.productList.addEventListener(Event.CHANGE, onProductChange);

			_selector.factoryData = [WarungBuTini.NAME, DepotAgung.NAME];

			//product picture holder
			_productPic = new Sprite();
			_productPic.x = 10;
			_productPic.y = _selector.height + 20;
			addChild(_productPic);

		}

//----------------------------------------------------------- FACTORY SELECTION

		private function selectFactory(e:Event = null):void {

			switch(_selector.factories.selectedLabel) {
				case WarungBuTini.NAME:
					_factory = new WarungBuTini();
				break;
				case DepotAgung.NAME:
					_factory = new DepotAgung();
				break;
			}

			_selector.productData = _factory.getProducts();
		}

//----------------------------------------------------------- PRODUCT SELECTION

		private function onProductChange(e:Event):void {
			var type:String = _selector.productList.itemToLabel(_selector.productList.selectedItem);
			_product = _factory.createProduct(type);
			_product.pay();

			setPicture(_product);
		}

//----------------------------------------------------------- DISPLAY PRODUCT IMAGE		

		private function setPicture(product:AbstractProduct):void {

			var i:int = _productPic.numChildren;
			while (i--) {
				_productPic.removeChildAt(i);
			}

			_productPic.addChild(product);
		}
	}
}
</pre>
<h4>Tambah Factory &amp; Produk Baru</h4>
<p>Kalo kita ingin buat factory baru, langkah-langkahnya adalah :</p>
<ol>
<li>Buat sub-class dari AbstractFactory</li>
<li>Sub-class itu harus punya konstanta bernama <code>NAME</code> yang dipakai untuk menampilkan nama factory di dalam combobox</li>
<li>Override <code>createProduct()</code> dan <code>getProducts()</code></li>
<li>Tambahkan ke daftar factory
<pre class="codeblock"><code>_selector.factoryData = [...,..., FactoryBaru.NAME];</code></pre>
</li>
<li>Instansiasi factory di dalam  <code>selectFactory()</code>
<pre class="codeblock"><code>switch(_selector.factories.selectedLabel) {
	....
	case FactoryBaru.NAME:
		_factory = new FactoryBaru();
	break;
}
</code></pre>
</li>
</ol>
<p>Untuk bikin produk baru:</p>
<ol>
<li>Buat subclass dari <code>AbstractProduct </code>dengan <em>parameterized constructor</em> dan konstanta <code>NAME</code>
<pre class="codeblock"><code>
public static const NAME:String = "Produk Baru";
public function ProdukBaru(factoryName:String,price:String = "7000") {
	super(NAME,price,factoryName)
}

</code></pre>
</li>
<li>Daftarkan nama produk di dalam factory pembuatnya, lihat <code>getProducts()</code>
<pre class="codeblock"><code>override public function getProducts():Array {
	return [...,...,ProdukBaru.NAME];
}
</code></pre>
</li>
<li>Instansiasi produk di dalam <code>createProduct()</code>
<pre class="codeblock"><code>override public function createProduct(type:String):AbstractProduct {
	...
	if (type == ProdukBaru.NAME) return new ProdukBaru(NAME,"1200");
	...
}</code></pre>
</li>
</ol>
<p>Contoh:</p>
<p>Produk baru : Kopi Susu</p>
<pre class="brush:as3">
[Embed(source='../assets/assets.swf', symbol='Tarik')]
public class KopiSusu extends AbstractProduct {

	public static const NAME:String = "Kopi Susu";

//----------------------------------------------------------- INIT

	public function KopiSusu(factoryName:String,price:String = "3500") {
		super(NAME, price, factoryName);

	}

}
</pre>
<p>Factory baru : Warung Pak Jaja. Salah satu dagangannya adalah Kopi Susu.</p>
<pre class="brush:as3">
public class WarungPakJaja extends AbstractFactory {

	public static const NAME:String = "Warung Pak Jaja";

//----------------------------------------------------------- INIT

	public function WarungPakJaja() {
		super(NAME);
	}

	override public function createProduct(type:String):AbstractProduct {

		if (type == KopiSusu.NAME) return new KopiSusu(NAME,"1200");
		if (type == SodaGembira.NAME) return new SodaGembira(NAME, "3000");
		if (type == NasiGoreng.NAME) return new NasiGoreng(NAME, "7500");

		throw Error("Invalid product type");
		return null;
	}

	override public function getProducts():Array {
		return [KopiSusu.NAME,SodaGembira.NAME,NasiGoreng.NAME];
	}

}
</pre>
<p>Tambahkan Warung Pak Jaja ke dalam Main class :</p>
<pre class="brush:as3">
private function init(e:Event = null):void {
	removeEventListener(Event.ADDED_TO_STAGE, init);

	//_factory &#038; _products _selector
	_selector = new FactorySelector();
	addChild(_selector);

	_selector.factories.addEventListener(Event.CHANGE, selectFactory);
	_selector.productList.addEventListener(Event.CHANGE, onProductChange);

	_selector.factoryData = [WarungBuTini.NAME, WarungPakJaja.NAME, DepotAgung.NAME];

	//product picture holder
	_productPic = new Sprite();
	_productPic.x = 10;
	_productPic.y = _selector.height + 20;
	addChild(_productPic);

}

//----------------------------------------------------------- FACTORY SELECTION

private function selectFactory(e:Event = null):void {

	switch(_selector.factories.selectedLabel) {
		case WarungPakJaja.NAME:
			_factory = new WarungPakJaja();
		break;
		case WarungBuTini.NAME:
			_factory = new WarungBuTini();
		break;
		case DepotAgung.NAME:
			_factory = new DepotAgung();
		break;
	}

	_selector.productData = _factory.getProducts();
}
</pre>
<p>Di output panel :</p>
<pre class="codeblock"><code>
Pesan makanan/minuman di Warung Bu Tini
Beli Kopi Susu di Warung Bu Tini
Bayar Rp 6000 ke Warung Bu Tini
Pesan makanan/minuman di Depot Agung
Beli Pangsit Mie di Depot Agung
Bayar Rp 4000 ke Depot Agung
Pesan makanan/minuman di Warung Pak Jaja
Beli Soda Gembira di Warung Pak Jaja
Bayar Rp 3000 ke Warung Pak Jaja
Beli Kopi Susu di Warung Pak Jaja
Bayar Rp 1200 ke Warung Pak Jaja

</code></pre>
<p>Di dalam arsip project file di atas, saya ada banyak produk yang bisa Anda pakai untuk utak atik.</p>
<p>Oke, sekian artikel tentang Factory Method &amp; Abstract Factory. Mudah-mudahan bermanfaat. Kalo nggak ngerti silakan tanya.</p>
<h3>Links</h3>
<ul>
<li>Project file : <a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=abstractfactory.rar" title="Downloaded 468 times">→ AbstractFactory.rar</a></li>
<li><a href="http://www.sourcemaking.com">sourcemaking.com</li>
<li><a href="http://www.as3dp.com">www.as3dp.com</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/05/factory-pattern/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook AS3 API : The Basics</title>
		<link>http://masputih.com/2009/05/facebook-as3-api-the-basics</link>
		<comments>http://masputih.com/2009/05/facebook-as3-api-the-basics#comments</comments>
		<pubDate>Sat, 02 May 2009 17:18:01 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[actionscript]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=266</guid>
		<description><![CDATA[Repost artikel yg sudah pernah saya tulis di blog yang lama Dalam tutorial ini saya akan tunjukkan cara pembuatan aplikasi Flash/Flex untuk Facebook dengan menggunakan Facebook AS3 API yang resmi di-support oleh Facebook &#38; Adobe. Facebook AS3 API adalah library yang memungkinkan kita membuat aplikasi Flash/Flex yang bisa mengakses data dari Facebook tanpa memerlukan skrip [...]]]></description>
			<content:encoded><![CDATA[<p></p><blockquote><p>Repost artikel yg sudah pernah saya tulis di <a href="http://old.masputih.com">blog yang lama</a></p></blockquote>
<p>Dalam tutorial ini saya akan tunjukkan cara pembuatan aplikasi Flash/Flex untuk Facebook dengan menggunakan Facebook AS3 API yang resmi di-support oleh Facebook &amp; Adobe.</p>
<p><a href="http://code.google.com/p/facebook-actionscript-api/">Facebook AS3 API</a> adalah library yang memungkinkan kita membuat aplikasi Flash/Flex yang bisa mengakses data dari Facebook tanpa memerlukan skrip di sisi server. Kalo kita mengeset aplikasi kita sebagai aplikasi “Desktop”, kita bisa langsung menjalankan aplikasi di komputer kita. Jadi nggak perlu upload ke server. Selama proses development, umumnya kita banyak berkutat di sisi desktop , nanti kalo aplikasi sudah siap untuk testing baru kita upload ke server.</p>
<p><span id="more-266"></span></p>
<h3>Set Up</h3>
<p>Langkah pertama yang kita lakukan adalah mengunjungi Facebook Developer Home untuk mengeset aplikasi yang akan kita buat. Buka situs tersebut lalu klik tombol Set Up New Application.</p>
<p>Pada form “Essential Information”, kita isikan nama aplikasi yang akan kita buat. Klik “Agree”, lalu “Save Changes”. </p>
<div id="attachment_267" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/76" rel="attachment wp-att-267"><img src="http://masputih.com/uploads/2009/05/76-300x167.jpg" alt="Create Application" title="Create Application" width="300" height="167" class="size-medium wp-image-267" /></a>
	<p class="wp-caption-text">Create Application</p>
</div>
<p>Di halaman “Basic Settings”, catat API Key dan Secret Key.</p>
<div id="attachment_268" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/77" rel="attachment wp-att-268"><img src="http://masputih.com/uploads/2009/05/77-300x127.jpg" alt="Secret &amp; API Keys" title="Secret &amp; API Keys" width="300" height="127" class="size-medium wp-image-268" /></a>
	<p class="wp-caption-text">Secret &amp; API Keys</p>
</div>
<p>Selanjutnya, kita klik menu “Advanced”. Di sini untuk “Application Type” kita pilih Desktop karena sementara kita hanya menjalankan aplikasi secara lokal dan kalo kita ingin aplikasi kita bisa dicoba oleh orang lain, non-aktifkan juga modus Sandbox. Klik Save Changes. </p>
<div id="attachment_269" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/78" rel="attachment wp-att-269"><img src="http://masputih.com/uploads/2009/05/78-300x127.jpg" alt="Application Type" title="Application Type" width="300" height="127" class="size-medium wp-image-269" /></a>
	<p class="wp-caption-text">Application Type</p>
</div>
<p>Terakhir, kita unduh Facebook AS3 API di Googlecode . Kita bisa mengunduh dalam bentuk .zip atau .swc, namun .zip lebih baik karena kita bisa melihat sourcecode-nya. Kita unduh juga dokumentasinya. Kalo Anda punya SVN client, saya sarankan Anda melakukan SVN check-out supaya mudah untuk mengikuti update terbaru.</p>
<h3>AS3 Project</h3>
<p>Kita buat AS3 project di FlexBuilder atau FlashDevelop ( saya menggunakan FlashDevelop ). Jangan lupa tambahkan Facebook AS3 API ke dalam library path atau kopi direktori <code>source/actionscript/com</code> ke dalam source folder.</p>
<h4>Download Project</h4>
<div class="box dl_box"><a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=helloas3.rar" title="Downloaded 576 times">→ HelloAS3.rar</a></div>
<p>Dalam project ini, kita menggunakan komponen TextArea dan Button dari Flash CS4 untuk menghemat ukuran file. framework.swc kita kopi dari Flex SDK supaya kita bisa menggunakan class ObjectUtil untuk menampilkan objek dalam format yang lengkap (nama instance dan propertinya) supaya debugging lebih gampang. Tambahkan kedua .swc ke dalam project library ( di FlashDevelop : klik kanan swc → Add To Library ).</p>
<blockquote><p>Saya tidak memasukkan framework.swc ke dalam project file di atas, jadi silakan Anda kopi sendiri dari Flex SDK.</p></blockquote>
<div id="attachment_278" class="wp-caption aligncenter" style="width: 264px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/79" rel="attachment wp-att-278"><img src="http://masputih.com/uploads/2009/05/79.jpg" alt="Tambahkan Flex SWC" title="Tambahkan Flex SWC" width="264" height="162" class="size-full wp-image-278" /></a>
	<p class="wp-caption-text">Tambahkan Flex SWC</p>
</div>
<div id="attachment_279" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/80" rel="attachment wp-att-279"><img src="http://masputih.com/uploads/2009/05/80-300x228.jpg" alt="Direktori Project" title="Direktori Project" width="300" height="228" class="size-medium wp-image-279" /></a>
	<p class="wp-caption-text">Direktori Project</p>
</div>
<p>Kalo Anda ingin mengikuti tutorial ini step-by-step, silakan buka file <code>MainDesktopStart.as</code> dan set file ini sebagai <em>Document Class</em>. Caranya, klik kanan lalu klik “Always Compile” dari context menu seperti gambar di bawah ini. </p>
<div id="attachment_286" class="wp-caption aligncenter" style="width: 295px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/81" rel="attachment wp-att-286"><img src="http://masputih.com/uploads/2009/05/81.jpg" alt="Setting Main Class" title="Always Compile" width="295" height="226" class="size-full wp-image-286" /></a>
	<p class="wp-caption-text">Setting Main Class</p>
</div>
<h3>API &amp; Secret Keys</h3>
<p>Pertama kita set API Key &amp; Secret Key yang kita dapat dari Facebook. Buka file Constants.as, isikan kedua key tersebut.</p>
<pre class="brush:as3">
public static const API_KEY:String = "YOURAPIKEY";
public static const SECRET_KEY:String = "YOURSECRETKEY";
</pre>
<h3>Instansiasi Facebook &amp; Login</h3>
<p>Buka file MainDesktopStart.as.  Lihat <code>initFacebook()</code> . Di dalam function ini kita lakukan instansiasi objek <code>FacebookSessionUtil</code> dan event handling untuk <code>FacebookEvent.WAITING_FOR_LOGIN</code>  dan <code>FacebookEvent.CONNECT</code>. Karena sebelum aplikasi kita bisa mengakses data user di Facebook, user yang menggunakannya harus memberi persetujuan ( otorisasi ) untuk mengakses data, kita panggil juga <code>login()</code> milik class <code>FacebookSessionUtil</code>. </p>
<pre class="brush:as3">
private function initFacebookSession():void {

	_session = new FacebookSessionUtil(Constants.API_KEY, Constants.SECRET_KEY, this.root.loaderInfo);
	_session.addEventListener(FacebookEvent.WAITING_FOR_LOGIN, onWaitingForLogin);
	_session.addEventListener(FacebookEvent.CONNECT, onFacebookConnect);

	_session.login();

}
</pre>
<p>Sekarang kita lakukan Test Movie. </p>
<div id="attachment_287" class="wp-caption aligncenter" style="width: 286px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/92" rel="attachment wp-att-287"><img src="http://masputih.com/uploads/2009/05/92-286x300.jpg" alt="Test Movie 1" title="Test Movie 1" width="286" height="300" class="size-medium wp-image-287" /></a>
	<p class="wp-caption-text">Test Movie 1</p>
</div>
<p>Pada saat eksekusi <code>_session.login()</code>,  <code>_session</code> menyiarkan <code>FacebookEvent.WAITING_FOR_LOGIN</code> yang di-handle oleh <code>onWaitingForLogin()</code> dan browser akan menampilkan popup window seperti gambar di bawah ini setelah Anda login ke Facebook. Ini tandanya aplikasi kita sudah mendapat otorisasi.</p>
<p>Kalo nggak, pastikan API &amp; Secret Key yang Anda masukkan sudah benar dan jangan lupa, kalo Anda punya PopUp Blocker, matikan dulu. </p>
<div id="attachment_290" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/82" rel="attachment wp-att-290"><img src="http://masputih.com/uploads/2009/05/82-300x140.jpg" alt="Logged In" title="Logged In" width="300" height="140" class="size-medium wp-image-290" /></a>
	<p class="wp-caption-text">Logged In</p>
</div>
<p>Sekarang ini, kalo aplikasi Anda dijalankan oleh orang lain atau Anda login ke account lain, bukan account yang Anda gunakan untuk mendaftarkan aplikasi ini, maka Facebook akan menampilkan dialog meminta otorisasi seperti ini, sebelum pemberitahuan seperti gambar di atas:</p>
<div id="attachment_291" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/83" rel="attachment wp-att-291"><img src="http://masputih.com/uploads/2009/05/83-300x102.jpg" alt="Allow Access Dialog" title="Allow Access ?" width="300" height="102" class="size-medium wp-image-291" /></a>
	<p class="wp-caption-text">Allow Access Dialog</p>
</div>
<p>Berikutnya, kita memberi tahu aplikasi bahwa kita sudah login dan aplikasi sudah mendapat otorisasi dengan mengklik tombol “OK” di pojok kanan bawah aplikasi kita.</p>
<p>Kita tambahkan kode untuk validasi login di <code>onLoginBtnClick()</code> sehingga pada saat kita klik OK, <code>_session </code>akan melakukan validasi &amp; koneksi ke Facebook.  <code>validateLogin()</code> berguna untuk memastikan bahwa aplikasi sudah mendapat otorisasi, jadi kalo Anda mengklik OK sebelum Facebook bilang <cite>You may now close this window …</cite>, maka <code>_session.login()</code> otomatis akan dieksekusi lagi. Sebaliknya, kalo aplikasi sudah mendapat otorisasi, maka aplikasi akan melakukan koneksi ke Facebook dan saat aplikasi menerima respons balik dari Facebook, _session akan menyiarkan <code>FacebookEvent.CONNECT</code> yang di-handle oleh <code>onFacebookConnect()</code>.</p>
<pre class="brush:as3">
private function onLoginBtnClick(e:Event):void {
	_console.appendText("\n\n---\nValidating...");

	//validate login and connect to FB
	_session.validateLogin();

}
</pre>
<p>Di dalam <code>onFacebookConnect()</code> kita pastikan bahwa respon yang diterima dari Facebook tidak mengandung pesan kesalahan dengan cara menguji properti <code>success</code> dari <code>FacebookEvent</code>. Jika ada kesalahan, properti ini akan bernilai <code>false</code>. Jika tidak, maka properti ini bernilai <code>true</code>, kita akan mendapat session key, dan kita eksekusi <code>getUserInfo()</code>.</p>
<p>Kita tambahkan beberapa baris kode seperti berikut :</p>
<pre class="brush:as3">
private function onFacebookConnect(e:FacebookEvent):void {

	//if connection fails, reinitiate login
	if (!e.success) {

		_console.appendText("\n\n---\nCannot connect to Facebook!");
		_console.appendText("\n\n---\n" + ObjectUtil.toString(e.error));				

		_session.login()

		return;
	}

	_console.appendText("\n\n---\nYou are now connected to Facebook!");
	_console.appendText("\nYour session key : " + _session.facebook.session_key);

	//hide login btn
	_loginBtn.visible = false;

	getUserInfo();

}
</pre>
<h3>Getting User Data</h3>
<p>Kita lihat function <code>getUserInfo()</code>. Kita akan gunakan function ini untuk mengambil data user yang menggunakan aplikasi ini. Kita tambahkan beberapa baris ke dalam <code>getUserInfo(</code>) seperti ini:</p>
<pre class="brush:as3">
private function getUserInfo():void {
	_console.appendText("\n\n---\nGetting your info");

	var fields:Array = [GetInfoFieldValues.NAME, GetInfoFieldValues.BIRTHDAY];
	var call:FacebookCall = _session.facebook.post(new GetInfo([_session.facebook.uid], fields ));
	call.addEventListener(FacebookEvent.COMPLETE, onComplete_getUserInfo);

}
</pre>
<p>Variabel fields berisi data apa saja yang ingin kita ambil dari data user yang bersangkutan. Di sini kita cukup ambil dua buah data yaitu “name” dan “birthday”. Kita bisa memasukkan <code>String</code> ke dalam variabel fields seperti ini :</p>
<pre class="codeblock"><code>
var fields:Array = ["name","birthday"];

</code></pre>
<p>Tapi lebih baik jika kita menggunakan konstanta yang ada di class GetInfoFieldValues untuk menghindari salah tulis.</p>
<p>Variabel call adalah objek bertipe <code>FacebookCall</code>  yang merepresentasikan eksekusi Facebook API. Karena kita ingin mengambil data user, maka kita buat objek <code>GetInfo</code>, dan kita beri argumen berupa properti <code>_session.facebook.uid</code> yang berisi id dari user yang menggunakan aplikasi ini dan variabel <code>fields</code> di atas.</p>
<p>Pada saat respons dari Facebook diterima, objek call akan menyiarkan <code>FacebookEvent.COMPLETE </code>yang di-handle oleh <code>onComplete_getUserInfo()</code>  yang akan menampilkan nama &amp; tanggal lahir user di Console dan kemudian mengeksekusi <code>getFriendsInfo()</code>. Untuk itu kita tambahkan kode ke dalam function tersebut seperti di bawah ini:</p>
<pre class="brush:as3">
private function onComplete_getUserInfo(e:FacebookEvent):void {

	if (!e.success) {
		_console.appendText("\n\n---\nERROR : " + ObjectUtil.toString(e.error));
		return;
	}

	var user:FacebookUser = GetInfoData(e.data).userCollection.getItemAt(0) as FacebookUser;
	_console.appendText("\n\n---\nHello " + user.name + "!");
	_console.appendText(" You were born on " + user.birthday);

	getFriendIDs(_session.facebook.uid);

}
</pre>
<p>Variabel <code>user</code> merepresentasikan useryang sedang menggunakan aplikasi ini. Tipe datanya adalah <code>FacebookUser</code>. Di sini kita perlu melakukan <em>type-casting</em> terhadap data yang dikirim bersama <code>FacebookEvent</code> menjadi <code>GetInfoData</code> yang memiliki properti <code>userCollection</code>. Karena kita hanya meminta data satu orang user, maka user ini berada di posisi index 0  dari <code>userCollection</code>.</p>
<p>Karena <code>userCollection.getItemAt(0)</code> memberikan data bertipe <code>Object</code> maka kita lakukan <em>type-casting</em> ke tipe data <code>FacebookUser</code>. Baris-baris berikutnya menampilkan data user. Baris terakhir mengeksekusi <code>getFriendIDs()</code>.</p>
<h3>Getting Friends IDs</h3>
<p><code>getFriendIDs() </code>berfungsi untuk meminta daftar semua friends . Jadi di sini, seperti di <code>getUserInfo()</code>, kita buat variabel call yang bertipe <code>FacebookCall</code>. Berbeda dengan <code>getUserInfo()</code>, kita membuat objek <code>GetFriends</code> bukan <code>GetInfo</code>. Kita juga mengeset <code>onComplete_getFriendIDs()</code> sebagai listener untuk <code>FacebookEvent.COMPLETE</code>.</p>
<p>Kita tambahkan kode ke <code>getFriendIDs()</code> seperti berikut:</p>
<pre class="brush:as3">
private function getFriendIDs(uid:String):void {

	var call:FacebookCall = _session.facebook.post(new GetFriends(null, uid ));
	call.addEventListener(FacebookEvent.COMPLETE, onComplete_getFriendIDs);

}
</pre>
<p>Kita lanjutkan ke <code>onComplete_getFriendIDs()</code>.</p>
<p>Di sini data yang diterima bersama <code>FacebookEvent.COMPLETE</code> bertipe <code>GetFriendsData</code>. Jadi, pertama kita buat variabel lokal bernama data yang bertipe <code>GetFriendsData</code> dan mengisinya dengan <em>event data</em> yang sudah di-type-cast menjadi <code>GetFriendsData</code>.  Empat baris berikutnya, menampilkan banyaknya friends  yang bisa kita ketahui dari panjang properti friends.</p>
<p>Baris-baris berikutnya menampilkan semua ID friends, dengan memanfaatkan properti rawResult yang merupakan data bertipe <code>XML</code>. Di sini kita menggunakan sintaks <em>E4X</em> untuk mengakses semua node di dalam <code>XML</code> tersebut.</p>
<p>Baris terakhir, menggabungkan node value yang disimpan di dalam <code>Array</code> menjadi sebuah <code>String</code> dan menampilkannya.</p>
<pre class="brush:as3">
private function onComplete_getFriendIDs(e:FacebookEvent):void {

	if (!e.success) {
		_console.appendText("\n\n---\nERROR : " + ObjectUtil.toString(e.error));
		return;
	}

	var data:GetFriendsData = GetFriendsData(e.data);
	if (data.friends.length > 0) {
		_console.appendText(". You have " + data.friends.length + " friends.");
	}else {
		_console.appendText(". You have no friends.");
		return;
	}

	var xml:XML = new XML(data.rawResult);
	var ids:Array = [];

	for each( var x:XML in xml.*) {
		ids.push(x);
	}

	_console.appendText("Their IDs are : \n"+ ids.join(' , ') +"\n");
}
</pre>
<p>Sekarang kita coba jalankan aplikasi. Kalo semuanya benar, Anda akan lihat aplikasi berjalan seperti gambar di bawah ini. Kalo tidak, silakan cocokkan kode yang Anda tulis dengan<code> MainDesktop.as</code>.</p>
<div id="attachment_294" class="wp-caption aligncenter" style="width: 263px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/84" rel="attachment wp-att-294"><img src="http://masputih.com/uploads/2009/05/84-263x300.jpg" alt="Test Movie 2" title="Test Movie 2" width="263" height="300" class="size-medium wp-image-294" /></a>
	<p class="wp-caption-text">Test Movie 2</p>
</div>
<h3>Going Online</h3>
<p>Pertama saya sarankan Anda bikin satu account Facebook lagi, khusus untuk  simulasi penggunaan aplikasi oleh orang lain. Account ini sangat berguna khususnya waktu kita menguji proses otorisasi &amp; verifikasi karena developer account Anda secara otomatis mengotorisasi aplikasi yang Anda buat sendiri.</p>
<p>Supaya aplikasi kita bisa digunakan/dimuat ke dalam Facebook Canvas, kita perlu sedikit memodifikasi kode. Sebenarnya nggak banyak yang harus diubah, tapi lumayan bikin pusing karena dokumentasi yang nggak lengkap &amp; contoh-contoh aplikasi yang masih menggunakan API versi lama ( versi 2 ).</p>
<p>Ada beberapa cara untuk memuat aplikasi yang kita buat ke dalam Facebook Canvas. Informasi lengkapnya bisa Anda baca sendiri di  Facebook Architecture Overview.  Di sini, kita pilih cara yang paling gampang, dengan menggunakan salah satu tag FBML yaitu <code>fb:swf</code>.</p>
<p>Kita upload dulu file SWF aplikasi yg kita buat ke server. Terus kita buat file “index.php” yg isinya seperti ini:</p>
<pre class="brush:as3">
<fb:swf id="hello"
	swfsrc="http://facebook.masputih.com/hello-as3/HelloAS3.swf"
	swfbgcolor='FFFFFF'
	width="400" height="400"/>
</pre>
<p>Berikut ini struktur direktori di host saya. </p>
<div id="attachment_299" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/85" rel="attachment wp-att-299"><img src="http://masputih.com/uploads/2009/05/85-300x103.jpg" alt="Server Directory" title="FTP " width="300" height="103" class="size-medium wp-image-299" /></a>
	<p class="wp-caption-text">Server Directory</p>
</div>
<p>Kembali ke Application Settings di Facebook. Kita ubah tipe aplikasi menjadi “Web” lalu kita buka menu Canvas  dan kita masukkan juga URL dari file index.php yang sudah kita buat. Terakhir kita pastikan bahwa Render Method adalah FBML, bukan iFrame.</p>
<div id="attachment_302" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/86" rel="attachment wp-att-302"><img src="http://masputih.com/uploads/2009/05/86-300x128.jpg" alt="Application Type : Web" title="Application Type : Web" width="300" height="128" class="size-medium wp-image-302" /></a>
	<p class="wp-caption-text">Application Type : Web</p>
</div>
<div id="attachment_303" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/87" rel="attachment wp-att-303"><img src="http://masputih.com/uploads/2009/05/87-300x187.jpg" alt="Canvas &amp; Render Method" title="Canvas &amp; Render Method" width="300" height="187" class="size-medium wp-image-303" /></a>
	<p class="wp-caption-text">Canvas &amp; Render Method</p>
</div>
<h3>Verifikasi Session</h3>
<p>Pada saat sebuah SWF dimuat ke dalam canvas melalui fb:swf, Facebook akan menginjeksi flashvars. Yang dapat kita gunakan untuk memverifikasi apakah aplikasi sudah mendapat otorisasi untuk mengakses data adalah <code>fb_sig_session_key</code>. Gambar berikut ini menunjukkan isi flashvars yang diinjek oleh Facebook.</p>
<div id="attachment_304" class="wp-caption aligncenter" style="width: 283px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/88" rel="attachment wp-att-304"><img src="http://masputih.com/uploads/2009/05/88-283x300.jpg" alt="Session Key" title="Session Key" width="283" height="300" class="size-medium wp-image-304" /></a>
	<p class="wp-caption-text">Session Key</p>
</div>
<p>Buka file <code>MainWeb.as</code>, perbedaan dengan <code>MainDesktop.as</code>  hanya pada <code>checkSession()</code> yang berfungsi untuk mengecek keberadaan <em>session key</em>. </p>
<p>Kalo <em>session key</em> tidak ditemukan atau bernilai <code>null</code>, berarti user belum pernah menggunakan aplikasi ini sebelumnya, jadi di sini kita perlu memanggil<code> _session.login()</code>. Sebaliknya, kalo session key ditemukan, kita panggil <code>_session.verifySession()</code> yang kemudian akan melakukan koneksi dengan Facebook.</p>
<pre class="brush:as3">
private var _flashvars:Object;
private function initFacebookSession():void {

	_flashvars = this.root.loaderInfo.parameters;

	_console.appendText("\n\n---\Flashvars : " + ObjectUtil.toString(_flashvars));

	_session = new FacebookSessionUtil(Constants.API_KEY, Constants.SECRET_KEY, this.root.loaderInfo);
	_session.addEventListener(FacebookEvent.WAITING_FOR_LOGIN, onWaitingForLogin);
	_session.addEventListener(FacebookEvent.CONNECT, onFacebookConnect);

	checkSession();

}

/**
 * check the flashvars
 * if there's no session key, initiate a login process
 */
private function checkSession():void {

	_console.appendText("\n\n---\nChecking session key...");

	if (_flashvars.fb_sig_session_key != null) {
		_session.verifySession();
	}else {
		_session.login();
	}
}
</pre>
<p>Silakan akses aplikasi Anda melalui URL : http://apps.facebook.com/nama-aplikasi-anda/. Kalo semua sudah benar, Anda bisa melihatnya dimuat ke dalam Facebook Canvas. Teman Anda juga bisa menggunakan aplikasi ini.</p>
<p>Sebagai perbandingan, silakan coba aplikasi yang saya buat di sini : <a href="http://apps.facebook.com/hello-as/">http://apps.facebook.com/hello-as/</a></p>
<div id="attachment_305" class="wp-caption aligncenter" style="width: 232px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/89" rel="attachment wp-att-305"><img src="http://masputih.com/uploads/2009/05/89-232x300.jpg" alt="Facebook Application Test" title="Facebook Application Test" width="232" height="300" class="size-medium wp-image-305" /></a>
	<p class="wp-caption-text">Facebook Application Test</p>
</div>
<div id="attachment_308" class="wp-caption aligncenter" style="width: 205px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/90" rel="attachment wp-att-308"><img src="http://masputih.com/uploads/2009/05/90-205x300.jpg" alt="Application List" title="Application List" width="205" height="300" class="size-medium wp-image-308" /></a>
	<p class="wp-caption-text">Application List</p>
</div>
<p>Ok, mudah-mudahan tutorial ini bisa membantu Anda memahami Facebook ActionScript API.</p>
<p>Pada bagian berikutnya dari artikel ini, saya akan menjelaskan bagaimana saya membuat aplikasi Flex untuk Facebook yaitu :<a href="http://apps.facebook.com/fx-friendbrowser/"> Fx Friend Browser</a>.</p>
<p>Stay tuned! <img src='http://masputih.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<div id="attachment_311" class="wp-caption aligncenter" style="width: 300px">
	<a href="http://masputih.com/2009/05/facebook-as3-api-the-basics/attachment/93" rel="attachment wp-att-311"><img src="http://masputih.com/uploads/2009/05/93-300x223.jpg" alt="Fx Friend Browser" title="Fx Friend Browser" width="300" height="223" class="size-medium wp-image-311" /></a>
	<p class="wp-caption-text">Fx Friend Browser</p>
</div>
<h3>Links</h3>
<ul>
<li>Project file : <a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=helloas3.rar" title="Downloaded 576 times">→ HelloAS3.rar</a></li>
<li><a href="http://www.adobe.com/devnet/facebook/">Adobe Developer Connection : Facebook</li>
<li><a href="http://code.google.com/p/facebook-actionscript-api/" title="http://code.google.com/p/facebook-actionscript-api/">Facebook ActionScript API</a></li>
<li><a href="http://www.facebook.com/developers/">Facebook Developer Home</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/05/facebook-as3-api-the-basics/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Bagaimana Menulis Kode yang Bagus</title>
		<link>http://masputih.com/2009/05/bagaimana-menulis-kode-yang-bagus</link>
		<comments>http://masputih.com/2009/05/bagaimana-menulis-kode-yang-bagus#comments</comments>
		<pubDate>Sat, 02 May 2009 13:30:25 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[practice]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=187</guid>
		<description><![CDATA[Selama saya berkarir sebagai developer Flash dari taun 2004-an, sudah ribuan baris kode dari puluhan aplikasi Flash yang saya baca. Banyak yang bagus dan gampang dipahami, banyak juga yang njelimet &#38; ruwet mirip pangsit mie. Banyak kasus saya temui waktu saya menginterview pelamar di Trippertlabs dimana pelamar yang portfolionya luar biasa bagus, ternyata kalo nulis [...]]]></description>
			<content:encoded><![CDATA[<p></p><p>Selama saya berkarir sebagai developer Flash dari taun 2004-an, sudah ribuan baris kode dari puluhan aplikasi Flash yang saya baca. Banyak yang bagus dan gampang dipahami, banyak juga yang <em>njelimet</em> &amp; <em>ruwet</em> mirip pangsit mie. Banyak kasus saya temui waktu saya menginterview pelamar di Trippertlabs  dimana pelamar yang portfolionya luar biasa bagus, ternyata kalo nulis kode luar biasa jelek ( kebetulan posisi saya adalah Senior Developer jadi saya selalu kebagian giliran pertama untuk “menyiksa” pelamar <img src='http://masputih.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ). </p>
<p>Untuk keperluan internal Trippertlabs, saya pernah mempublikasikan tulisan berjudul <cite>Coding Guidelines for Flash &amp; Flex Developers</cite>. Saya pikir ada baiknya kalo artikel itu saya tulis lagi di sini. </p>
<p>Mulai dari yang paling dasar yaitu indentasi.</p>
<p><span id="more-187"></span></p>
<h3>Indentasi</h3>
<p>Indentasi berperan penting dalam presentasi kode. Ada beberapa style yang digunakan yaitu:</p>
<ol style="list-style-type:lower-latin;">
<li>K &amp; R Brace Style
<pre class="codeblock"><code>
function doSomething():void{
    var max:int = 10;
    for(var i:int = 0;i&lt;max;i++){
        ...
    }
}
</code></pre>
</li>
<li>Extended Brace Style
<pre class="codeblock"><code>
function doSomething():void
{
	var max:int = 10;
	for (var i:int = 0; i &lt; max; i++)
	{
		...
	}
}
</code></pre>
</li>
<li>Indented Brace/Whitesmith Style
<pre class="codeblock"><code>
function doSomething():void
           {
                var max:int = 10;
                for (var i:int = 0; i &lt; max; i++)
                    {
                      ...
                    }
           }
</code></pre>
</li>
<li>Other Brace Style
<pre class="codeblock"><code>
function giveNightmare():void
{

var max:int = 10;
for (var i:int = 0; i < max; i++)
    {
        ...
    }
}
</code></pre>
</li>
</ol>
<p>Anda bisa pilih (a) atau (b) biarpun (b) lebih baik karena sesuai dengan konvensi umum di kalangan developer flash/flex &amp; digunakan oleh Adobe. © dan (d) sebaiknya dijauhi kecuali kalo Anda ingin nulis kode yang bisa bikin orang begadang &amp; sakit kepala. </p>
<p>Style manapun yang Anda pilih, (a) atau (b), Anda harus konsisten. Jangan ganti-ganti gaya. Kalo Anda bekerja dalam satu tim, ikuti konvensi yang disepakati bersama &amp; semua anggota tim harus menggunakan style yang sama.</p>
<h3>Penamaan</h3>
<p>Penamaan yang amburadul biasanya dilakukan oleh koder baru yang masih cupu. Ini bisa dipahami karena pengalaman mereka masih sedikit atau mungkin nggak punya sama sekali. Dalam buku <cite>Code Craft : The Practice of Writing Excellent Code</cite> disebutkan aturan-aturan dalam penamaan, dua di antaranya yaitu :</p>
<blockquote>
<p>Write your code to be read by humans. Easily. The compiler will be able to cope.</p>
<p>Favor clarity over brevity.</p>
</blockquote>
<h4>Variabel &amp; Function</h4>
<p>Waktu membuat variabel &amp; function, pilih nama yang deskriptif. Sering saya lihat nama yang nggak jelas maksudnya apa kecuali kita baca comment &amp; dalam beberapa kasus, lebih mirip password. </p>
<p>Contohnya gini:</p>
<pre class="codeblock"><code>
//current index
var i:int;
//text before
var txt0:String;
//final text
var txt:String;

function fib():void{
    ...
}

</code>
</pre>
<p>Kode di atas lebih baik kalo ditulis dengan lebih jelas, misalnya :</p>
<pre class="codeblock"><code>
//current index
var curIdx:int;
//initial text
var initTxt:String;
//final text
var finalTxt:String;

function fibonacci():void{
    ...
}
</code>
</pre>
<p>Khusus untuk nama variabel yang hanya terdiri dari satu huruf, Anda boleh menggunakannya untuk variabel yang bersifat lokal. Contohnya :</p>
<pre class="codeblock"><code>
function multiplyByFive(a:Number):Number{
    return a * 5;
}
</code></pre>
<p>Jangan menggunakannya untuk instance variable. Contoh :</p>
<pre class="codeblock"><code>
var a:Number = 3;

function multiplyByFive():Number{
    return a * 5;
}
</code></pre>
<h4>Kapitalisasi</h4>
<p>Ada 4 macam skema penamaan variabel, function, dan class yang umum digunakan yaitu:</p>
<ol style="list-style-type:lower-latin;">
<li>Camel Case, contoh : <code>someVar</code>, <code>bookTitle</code></li>
<li>Proper Case, contoh : <code>ApplicationModel</code>, <code>MainView</code></li>
<li>Uppercase, contoh : <code>ENTER_FRAME</code>, <code>CLICK</code>
<li>Underscore, contoh : <code>book_title</code>, <code>button_mc</code></li>
</ol>
<p>Konvensi umum AS3 adalah menggunakan (a) untuk nama variabel dan function, (b) untuk nama class, dan © untuk konstanta. (d) banyak digunakan oleh developer yang menulis kode AS2, tapi praktek ini lebih banyak disebabkan oleh script editor bodoh bawaan Flash IDE yang nggak bisa menampilkan <em>code hinting</em> kecuali kalo nama variabel ditambah dengan singkatan tipe data tertentu, misalnya : <code>myClip_mc</code>. Praktek semacam ini udah ditinggalkan oleh developer AS3, apalagi sekarang sudah banyak code/text editor yang jauh lebih pintar daripada editor punya Flash IDE, misalnya FlashDevelop.</p>
<h3>Komentar</h3>
<p>Komentar adalah bagian kode yang sering diabaikan. Banyak developer yang sama sekali nggak nulis komentar biarpun kodenya rumit, ada yang nulis komentar terlalu panjang, ada juga yang nulis komentar sedikit tapi di bagian yang sebenarnya nggak butuh komentar. Contoh komentar yang nggak perlu :</p>
<pre class="codeblock"><code>
//increment i
i++

//assign a to temp
temp = a

//call fibonacci
fibonacci()

</code></pre>
<h4>Self-documenting Code</h4>
<p>Untuk menulis komentar yang pas, nggak terlalu banyak/panjang, juga nggak terlalu sedikit ada baiknya kalo kita mulai dari menulis kode yang bisa menjelaskan dirinya sendiri tanpa kita perlu memberi komentar. Di buku <cite>Code Craft</cite>, teknik ini disebut <em>self-documenting code</em>, caranya adalah, kembali ke penamaan, menggunakan nama yang deskriptif. Contoh :</p>
<pre class="codeblock"><code>
function onClickUploadButton(e:MouseEvent):void{ ... }

function loadVideoXML():void{ ... }

function onEnterFrame(e:Event):void { .. }

function loaderCompleteListener(e:Event):void{...}

function handleFault(e:FaultEvent):void{ ... }

function loadImage(e:Event = null):void { .. }

</code></pre>
<p>Baris terakhir dari contoh di atas adalah kasus spesial dimana sebuah <em>function</em> yang berperan sebagai <em>event handler</em>, bisa juga dieksekusi secara manual jadi kalo kita tambahkan “on” atau “Listener” malah membingungkan. Tiga baris di atasnya adalah skema penamaan event handler yang umum dipakai oleh developer Flash/Flex.</p>
<p>Setelah kita menulis <em>self-documenting code</em> selanjutnya kita cari <em>function</em> mana saja yang perlu kita masukkan ke dalam dokumentasi dan kita tambahkan komentar di sana.  </p>
<h3>Pencabangan</h3>
<p>Pencabangan juga termasuk salah satu bagian kode yang sering bermasalah. Sebenarnya nggak ada aturan baku tentang pencabangan, tapi di sini saya sarankan jika Anda menggunakan <code>if-else</code> berkurung ( <em>nested </em>) batasi kedalamanya sampai maksimal 3 level. Kalo lebih dari itu, pikirkan cara lain misalnya mengganti <code>if-else </code>dengan <code>switch-case</code>. Saya sendiri nggak begitu suka <code>if-else</code> yang lebih dari 2 level. Memang kelihatannya sepele, tapi kalo kode yang kita buat cukup rumit, kemungkinan besar kita bakal mumet kalo kita kembali utak atik kode lama setelah proyek selesai.</p>
<h3>Class Jagoan</h3>
<p>Developer yang baru menemukan jalan yang benar setelah tersesat di dunia prosedural ( timeline ) cenderung membuat kelas yang kadang disebut “Super Class” ( nggak ada hubungannya dengan <em>super class</em> di dalam hirarki OOP ). Super Class di sini adalah class yang bisa melakukan semua tugas, mulai inisialisasi, menangani user input, akses database, upload data, dan lain-lain. Class serba bisa. Di sini si developer sebetulnya tetap menulis kode secara prosedural biarpun bentuknya class. Baunya sih OOP, tapi rasanya tetap prosedural.</p>
<p>Untuk proyek kecil, sah-sah saja, nggak masalah. Tapi untuk proyek yang kompleks, praktek ini sebaiknya dihindari dan lebih baik kita buat class yang sesuai dengan konteks permasalahan yang dihadapi. Misalnya, untuk upload data, buat class yang berfungsi untuk upload data saja, nggak perlu menangani user input. Kalo upload dilakukan berdasar user input, buat dua class, satu untuk menghandel user input dan urusan upload, delegasikan ke class lain. <em>Separation of concerns is a good thing.</em></p>
<p>Oke, sekian tulisan saya. Mudah-mudahan bermanfaat.</p>
<h3>Referensi</h3>
<div style="text-align:center">
<iframe src="http://rcm.amazon.com/e/cm?t=masputih0b-20&#038;o=1&#038;p=8&#038;l=as1&#038;asins=1593271190&#038;md=10FE9736YVPPT7A0FBG2&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;m=amazon&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr&#038;nou=1" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</div>
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/05/bagaimana-menulis-kode-yang-bagus/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MVC Sederhana untuk Pemula</title>
		<link>http://masputih.com/2009/05/mvc-sederhana-untuk-pemula</link>
		<comments>http://masputih.com/2009/05/mvc-sederhana-untuk-pemula#comments</comments>
		<pubDate>Fri, 01 May 2009 08:30:57 +0000</pubDate>
		<dc:creator>Anggie Bratadinata</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Repost]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[pattern]]></category>

		<guid isPermaLink="false">http://masputih.com/?p=119</guid>
		<description><![CDATA[Repost artikel yg sudah pernah saya posting di blog yang lama. Kali ini saya jelaskan tentang cara membuat “struktur” MVC sederhana untuk menulis kode yang maintainable dengan memecah kode menjadi beberapa bagian berdasarkan fungsinya ( separation of concerns ). Saya anggap Anda sudah cukup mengetahui dasar OOP dan mempraktekkannya, jadi saya nggak perlu menjelaskan lagi [...]]]></description>
			<content:encoded><![CDATA[<p></p><blockquote><p>Repost artikel yg sudah pernah saya posting di <a href="http://old.masputih.com">blog yang lama</a>. </p></blockquote>
<p>Kali ini saya jelaskan tentang cara membuat “struktur” MVC sederhana untuk menulis kode yang maintainable dengan memecah kode menjadi beberapa bagian berdasarkan fungsinya ( <em>separation of concerns</em> ).</p>
<p>Saya anggap Anda sudah cukup mengetahui dasar OOP dan mempraktekkannya, jadi saya nggak perlu menjelaskan lagi apa itu <em>class</em>, <em>instance</em>, <em>static</em>, <em>getter/setter</em>, dsb. Saya juga nggak menjelaskan apa itu <em>custom events</em> dan bagaimana cara membuat &amp; menggunakannya karena sudah pernah saya jelaskan dalam artikel yang lain. Selain itu, Anda juga harus mengerti cara mendefinisikan &amp; membuat <em>custom class</em> untuk objek di <em>library</em>.</p>
<p><span id="more-119"></span></p>
<p>Di sini saya membuat aplikasi sederhana berupa sebuah kotak yang posisinya bisa dikontrol oleh 4 tombol seperti berikut:</p>
<div class="swfcontainer" style="text-align:center">
<div class="swf" style="margin:10px;border:1px solid #ccc;">
[kml_flashembed fversion=“9.0.124″ movie=“http://masputih.com/files/SimpleMVC.swf” targetclass=“flashmovie” publishmethod=“static” width=“320” height=“400”]</p>
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>
<p>[/kml_flashembed]
</p></div>
</div>
<h3>Design Patterns</h3>
<p><em>Design patterns</em> (DP) adalah sekumpulan solusi generik untuk masalah-masalah yang umum ditemui oleh para <em>developer</em> dalam membuat aplikasi. <em>Pattern</em> berarti pola, artinya DP bukan berupa kode, tetapi berupa panduan yang implementasinya terserah <em>developer</em> yang menggunakannya.</p>
<p>Info yang lebih lengkap bisa Anda baca di <a href="http://id.wikipedia.org/wiki/Pola_desain">wikipedia</a>.</p>
<h3>Model-View-Controller</h3>
<p>MVC adalah <em>meta-pattern</em> , artinya <span class="caps">MVC</span> bukan merupakan <em>pattern</em> yang berdiri sendiri tapi merupakan kumpulan dari beberapa <em>pattern</em> &amp; dalam buku <em>Head First Design Patterns</em> , MVC dimasukkan dalam kelompok <em>compound-pattern</em>.</p>
<p>Pada prinsipnya, implementasi MVC membagi kode ke dalam 3 bagian yaitu:</p>
<ul>
<li>Model sebagai sumber data</li>
<li>View sebagai representasi data dan <em>user interface</em></li>
<li>Controller yang berfungsi sebagai “otak” atau <em>business logic</em> yang memproses <em>user input</em> dan meng–<em>update</em> Model dan View ( kalau diperlukan ).</li>
</ul>
<h4>Apa keuntungan <span class="caps">MVC </span>?</h4>
<p>Sekilas MVC kelihatannya merepotkan karena kita harus menulis kode lebih banyak tapi keuntungannya adalah kode kita lebih <em>maintainable</em> karena kita bisa mengubah salah satu bagian tanpa harus mengubah bagian yang lain. Sebagai contoh, misalnya kita membuat aplikasi A yang memproses data berformat XML namun kemudian kita diharuskan menggunakan data berformat JSON. Dalam kasus seperti ini, kita cukup mengubah Model tanpa harus mengubah bagian yang lain.</p>
<p>MVC juga mempermudah <em>debugging</em> karena kita bisa memperkirakan bagian mana yang bermasalah tanpa harus membongkar seluruh kode yang sudah kita buat.</p>
<p>Jadi secara umum, keuntungan MVC jauh lebih besar daripada kerepotan yang ditimbulkannya. Di samping itu, kalo Anda nggak mau repot menulis berbaris-baris kode, mungkin menjadi <em>programmer</em> bukan profesi yang cocok buat Anda &amp; sebaiknya Anda <a href="http://www.google.co.id/search?q=lowongan+kerja">cari</a> pekerjaan <a href="http://bikinduit.com/">lain</a>. <img src='http://masputih.com/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Struktur dasar</h3>
<p> 	Di dalam direktori projek, saya buat 4 buah sub-direktori/<em>package</em> seperti gambar di bawah ini.</p>
<div class="wp-caption aligncenter" style="width: 188px">
	<img alt="Direktori Project di FlashDevelop" src="http://old.masputih.com/images/75.jpg" title="Struktur Direktori" width="188" height="207" />
	<p class="wp-caption-text">Direktori Project di FlashDevelop</p>
</div>
<p>Berikut ini diagram dari aplikasi yang saya buat.</p>
<div class="wp-caption aligncenter" style="width: 497px">
	<img alt="Class Diagram" src="http://masputih.com/images/74.jpg" title="Class Diagram" width="497" height="515" />
	<p class="wp-caption-text">Class Diagram</p>
</div>
<h3>View &amp; ViewEvent</h3>
<p>	Package <code>view</code> berisi class yang berhubungan dengan library symbol yaitu <code>MainView</code> dan <code>ArrowButton</code>. <code>MainView</code> bertugas menyiarkan <code>ViewEvent</code> jika salah satu tombol navigasi diklik. <em>Event</em> ini ditangkap oleh <code>Controller</code> yang kemudian meng-update <code>Model</code>. Selain itu <code>MainView</code> juga menampilkan posisi kotak kuning.</p>
<p>Kenapa saya membuat <code>ViewEvent</code> dan nggak membuat <code>Controller</code> yang langsung mendengarkan <code>MouseEvent.CLICK</code> yang disiarkan oleh tombol kontrol ? Karena saya ingin meminimalkan coupling antara <code>MainView</code> dan <code>Controller</code> sehingga jika saya perlu mengubah <code>View</code>, selama event yang disiarkannya tetap bertipe <code>ViewEvent</code>, saya nggak perlu mengubah <code>Controller</code>.</p>
<p>[js]<br />
package simplemvc.view {</p>
<p>	import flash.display.MovieClip;<br />
	import flash.events.Event;<br />
	import flash.events.MouseEvent;<br />
	import flash.geom.Point;<br />
	import flash.text.TextField;<br />
	import simplemvc.events.ViewEvent;<br />
	import simplemvc.model.Model;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class MainView extends MovieClip {</p>
<p>		//timeline objects<br />
		public var hero:MovieClip;<br />
		public var board:MovieClip;<br />
		public var leftBtn:ArrowButton;<br />
		public var rightBtn:ArrowButton;<br />
		public var upBtn:ArrowButton;<br />
		public var downBtn:ArrowButton;<br />
		public var positionTxt:TextField;</p>
<p>		private var _model:Model = Model.getInstance();</p>
<p>//———————————————————– INIT</p>
<p>		public function MainView() {</p>
<p>			initButtonListener();</p>
<p>			_model.addEventListener(Event.CHANGE, modelListener);</p>
<p>		}</p>
<p>		private function initButtonListener():void {<br />
			var i:int = 0;<br />
			while (i &lt; numChildren) {<br />
				if (this.getChildAt(i) is ArrowButton) {<br />
					this.getChildAt(i).addEventListener(MouseEvent.CLICK, buttonListener);<br />
				}<br />
				i++;<br />
			}</p>
<p>		}</p>
<p>		private function buttonListener(e:MouseEvent):void {</p>
<p>			switch(e.currentTarget) {<br />
				case leftBtn:<br />
					dispatchEvent(new ViewEvent(ViewEvent.MOVE_LEFT));<br />
				break;<br />
				case rightBtn:<br />
					dispatchEvent(new ViewEvent(ViewEvent.MOVE_RIGHT));<br />
				break;<br />
				case upBtn:<br />
					dispatchEvent(new ViewEvent(ViewEvent.MOVE_UP));<br />
				break;<br />
				case downBtn:<br />
					dispatchEvent(new ViewEvent(ViewEvent.MOVE_DOWN));<br />
				break;<br />
			}<br />
		}</p>
<p>		private function modelListener(e:Event):void {</p>
<p>			hero.x = _model.heroPos.x;<br />
			hero.y = _model.heroPos.y;</p>
<p>			positionTxt.text = _model.heroPos.toString();</p>
<p>		}</p>
<p>	}</p>
<p>}</p>
<p>[/js]</p>
<p>[js]<br />
package simplemvc.events {<br />
	import flash.events.Event;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class ViewEvent extends Event {</p>
<p>		public static const MOVE_LEFT:String = “moveLeft”;<br />
		public static const MOVE_RIGHT:String = “moveRight”;<br />
		public static const MOVE_UP:String = “moveUp”;<br />
		public static const MOVE_DOWN:String = “moveDown”;</p>
<p>		public function ViewEvent(type:String) {<br />
			super(type, true);<br />
		} </p>
<p>		override public function clone():Event {<br />
			return new ViewEvent(type);<br />
		} </p>
<p>		override public function toString():String {<br />
			return formatToString(“ViewEvent”, “type”, “bubbles”, “cancelable”, “eventPhase”);<br />
		}</p>
<p>	}</p>
<p>}</p>
<p>[/js]</p>
<h3>Model</h3>
<p><code>Model</code> adalah bagian dimana data berada. Untuk data yang bersifat global, kita bisa mengimplementasikan <em>Singleton pattern</em>. <em>Singleton class</em> hanya bisa diinstansiasi satu kali selama aplikasi berjalan. Umumnya, referensi ke instance dari Singleton diakses dengan memanggil <em>static method</em><code> getInstance()</code>.</p>
<p>Kalo kita bekerja bersama developer lain, kita bisa mencegah mereka menginstansiasi/membuat objek Singleton dengan menggunakan <em>inner class</em> yaitu class yang didefinisikan diluar <em>package</em> tetapi masih di dalam file yang sama.</p>
<p>Model saya gunakan untuk menyimpan data berupa posisi kotak kuning. Pada saat data berubah, <code>Model</code> akan men-dispatch <code>Event.CHANGE</code> yang didengarkan oleh <code>MainView</code> yang kemudian meng-update posisi kotak kuning.</p>
<p>[js]<br />
package simplemvc.model {</p>
<p>	import flash.events.Event;<br />
	import flash.events.EventDispatcher;<br />
	import flash.geom.Point;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class Model extends EventDispatcher {</p>
<p>		public var heroHeight:Number = 0;<br />
		public var heroWidth:Number = 0;<br />
//———————————————————– HERO VELOCITY</p>
<p>		public var vx:Number = 10;<br />
		public var vy:Number = 10;</p>
<p>//———————————————————– HERO POSITION</p>
<p>		private var _heroPos:Point = new Point();</p>
<p>		public function get heroPos():Point { return _heroPos; }</p>
<p>		public function set heroPos(value:Point):void {</p>
<p>			if (value.x &gt;= heroBounds.xMin &amp;&amp; value.x &lt;= heroBounds.xMax &amp;&amp;<br />
				value.y &gt;= heroBounds.yMin &amp;&amp; value.y &lt;= heroBounds.yMax ) {</p>
<p>				_heroPos = value;<br />
				dispatchEvent(new Event(Event.CHANGE));</p>
<p>			}<br />
		}</p>
<p>		public function moveDown():void {<br />
			heroPos = new Point(heroPos.x, heroPos.y + vy);<br />
		}</p>
<p>		public function moveUp():void {<br />
			heroPos = new Point(heroPos.x, heroPos.y — vy);<br />
		}</p>
<p>		public function moveLeft():void {<br />
			heroPos = new Point(heroPos.x — vx, heroPos.y);<br />
		}</p>
<p>		public function moveRight():void {<br />
			heroPos = new Point(heroPos.x + vx, heroPos.y );<br />
		}</p>
<p>//———————————————————– HERO BOUNDS</p>
<p>		private var _heroBounds:Object = {};</p>
<p>		public function get heroBounds():Object { return _heroBounds; }</p>
<p>		public function set heroBounds(value:Object):void {<br />
			//trace(value);<br />
			_heroBounds.xMin = value.x;<br />
			_heroBounds.xMax = value.x + value.width — heroWidth;<br />
			_heroBounds.yMin = value.y;<br />
			_heroBounds.yMax = value.y + value.height — heroHeight;</p>
<p>		}</p>
<p>//———————————————————– INIT<br />
		private static var _instance:Model;<br />
		public function Model(enf:SingletonEnforcer) {}<br />
		public static function getInstance():Model {<br />
			if (_instance == null) _instance = new Model(new SingletonEnforcer());<br />
			return _instance;<br />
		}</p>
<p>	}</p>
<p>}<br />
//INNER CLASS<br />
class SingletonEnforcer { };</p>
<p>[/js]</p>
<h3>Controller</h3>
<p><code>Controller</code> mendengarkan <code>ViewEvent</code> yang disiarkan oleh <code>MainView</code> dan meng-update <code>Model</code> berdasarkan event tersebut.</p>
<p>[js]<br />
package simplemvc.controller {<br />
	import flash.events.Event;<br />
	import flash.geom.Point;<br />
	import simplemvc.model.Model;<br />
	import simplemvc.view.*;<br />
	import simplemvc.events.*;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class Controller {</p>
<p>		private var _model:Model = Model.getInstance();<br />
		private var _view:MainView;</p>
<p>//———————————————————– INIT</p>
<p>		public function Controller(view:MainView) {</p>
<p>			_view = view;</p>
<p>			_model.heroHeight = _view.hero.height;<br />
			_model.heroWidth = _view.hero.width;<br />
			_model.heroBounds = _view.board.getBounds(_view);</p>
<p>			_view.addEventListener(ViewEvent.MOVE_DOWN, viewListener);<br />
			_view.addEventListener(ViewEvent.MOVE_UP, viewListener);<br />
			_view.addEventListener(ViewEvent.MOVE_LEFT, viewListener);<br />
			_view.addEventListener(ViewEvent.MOVE_RIGHT, viewListener);</p>
<p>		}</p>
<p>		public function startUp():void {<br />
			_model.heroPos = new Point(0, 0);<br />
		}</p>
<p>		private function viewListener(e:ViewEvent):void {</p>
<p>			switch(e.type) {<br />
				case ViewEvent.MOVE_DOWN:<br />
					_model.moveDown();<br />
				break;<br />
				case ViewEvent.MOVE_LEFT:<br />
					_model.moveLeft();<br />
				break;<br />
				case ViewEvent.MOVE_RIGHT:<br />
					_model.moveRight();<br />
				break;<br />
				case ViewEvent.MOVE_UP:<br />
					_model.moveUp();<br />
				break;<br />
			}<br />
		}</p>
<p>	}</p>
<p>}</p>
<p>[/js]</p>
<h3>Document/Main Class</h3>
<p>[js]<br />
package  {</p>
<p>	import flash.display.MovieClip;<br />
	import simplemvc.controller.Controller;<br />
	import simplemvc.view.MainView;</p>
<p>	/**<br />
	 * …<br />
	 * @author Anggie Bratadinata<br />
	 */<br />
	public class Main extends MovieClip {</p>
<p>		public var mainView:MainView;<br />
		public var controller:Controller;</p>
<p>		public function Main() {<br />
			controller = new Controller(mainView);<br />
			controller.startUp();<br />
		}</p>
<p>	}</p>
<p>}</p>
<p>[/js]</p>
<p>Seperti Anda lihat, menulis kode dengan struktur MVC nggak terlalu sulit, hanya sedikit ngerepotin. <img src='http://masputih.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Download</h3>
<a href="http://masputih.com/wordpress/wp-content/plugins/download-monitor/download.php?id=simple-mvc-src.zip" title="Downloaded 229 times" ><img src="http://masputih.com/images/disk.png" width="16" height="16"/> simple-mvc-src.zip</a> 
]]></content:encoded>
			<wfw:commentRss>http://masputih.com/2009/05/mvc-sederhana-untuk-pemula/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
