<?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>Mattes Groeger</title>
	<atom:link href="http://blog.mattes-groeger.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mattes-groeger.de</link>
	<description>Flash, Flex, Air Development Blog</description>
	<lastBuildDate>Sun, 29 Jan 2012 16:12:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Flash Timeline Actions</title>
		<link>http://blog.mattes-groeger.de/actionscript/flash-timeline-actions/</link>
		<comments>http://blog.mattes-groeger.de/actionscript/flash-timeline-actions/#comments</comments>
		<pubDate>Sun, 29 Jan 2012 16:12:04 +0000</pubDate>
		<dc:creator>Mattes</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[fla]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[pattern]]></category>
		<category><![CDATA[swc]]></category>
		<category><![CDATA[timeline]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://blog.mattes-groeger.de/?p=416</guid>
		<description><![CDATA[Introduction A proper designer-developer workflow is essential, especially in bigger teams. By separating logic and view (e.g. via MVC Design Pattern) we try to avoid dependencies between artists and programmers. Less coupling increases the speed of development and design. Sometimes it is hard to avoid this coupling, especially if it comes to optimization. Let&#8217;s imagine an artist [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>A proper designer-developer workflow is essential, especially in bigger teams. By separating logic and view (e.g. via <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">MVC Design Pattern</a>) we try to avoid dependencies between artists and programmers. Less coupling increases the speed of development and design.</p>
<p>Sometimes it is hard to avoid this coupling, especially if it comes to optimization. Let&#8217;s imagine an artist who wants to have sound within his timeline animation. He could just embed the sound and put it in the appropriate timeline frame. But if he then wants to use the same sound in another FLA it gets complicated. We don&#8217;t want the same sound to be loaded twice.</p>
<p>This post describes a pattern for triggering more sophisticated logic from the Flash timeline so artists can easily make use of it. For easier understanding I will stick to the sound example. But keep in mind that this pattern can be applied to other problems as well. I will give an example at the end of this post.</p>
<p>Please also note that this post focuses on timeline related actions. If you want to trigger sounds based on mouse clicks or just playing background sounds, you are perfectly fine doing this purely by code.</p>
<h4>Alternative Approaches</h4>
<p>Before discussing the actual solution in detail, I would like to briefly mention two alternatives and their particular drawbacks.</p>
<p>I already mentioned one solution: Embedding sounds within their respective <em>FLA</em> files. But using the same sound in other <em>FLAs</em> would cause it to be loaded multiple times. The browser can&#8217;t cache them either because they are embedded in different <em>SWF</em> files.</p>
<p>Another solution would be to trigger sounds programmatically by using frame labels. This means that your code would have to observe the timeline for execution of certain labels. You have to use some kind of configuration that tells the code which sound to play on which MovieClip and label. Parsing every MovieClip wouldn&#8217;t be a good idea in terms of performance.</p>
<p>Both alternatives have a drawback either for artists or programmers. Wouldn&#8217;t it be cool if we could trigger our logic from the timeline instead of heaving the logic observing it? Thats where &#8216;Timeline Actions&#8217; enter the stage.</p>
<h3>Timeline Actions</h3>
<p>This illustration shows the relevant parts that I&#8217;ll explain in the following sections.</p>
<p style="text-align: center;"><img class="size-full wp-image-440  aligncenter" title="Timeline Actions Overview" src="http://blog.mattes-groeger.de/wp-content/uploads/2012/01/Graph.png" alt="" width="471" height="347" /></p>
<h4>The basic concept</h4>
<p>In the above image you can see two example asset files (red) which will be maintained by the artists. The sound logic (blue) is a separate <em>SWF</em> or part of the application maintained by the programmers. It&#8217;s responsible for loading, caching and playing the sounds. The goal is, that artists can trigger any sound by putting the following frame script into the timeline:</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">playSound<span style="color: #000000;">&#40;</span><span style="color: #990000;">&quot;mySound&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span></div></td></tr></tbody></table></div>
<p><strong>Note</strong>: Because the <tt>playSound()</tt> is a top-level function it requires no import statement.</p>
<p>The sound logic should receive the string <tt>"mySound"</tt> and select the appropriate MP3 for playback. But how do you communicate from the assets (red) to the sound logic (blue)? It&#8217;s not a good idea to compile the sound logic into each asset. Thats why the first step is, to put just the communication logic into a very small library called &#8220;<em>timeline-sound.swc</em>&#8221; (green).</p>
<p>This library contains the <tt>playSound()</tt> function as well as a static <tt>SoundDelegate</tt> class. The <tt>SoundDelegate</tt> is the connection between <tt>playSound()</tt> and sound logic. The next section &#8220;Technical implementation&#8221; will give you more insight into the <em>SWC</em> contents.</p>
<div id="attachment_469" class="wp-caption aligncenter" style="width: 558px"><a href="http://blog.mattes-groeger.de/wp-content/uploads/2012/01/actionscript-settings.png"><img class="size-full wp-image-469" title="Advanced ActionScript 3.0 Settings" src="http://blog.mattes-groeger.de/wp-content/uploads/2012/01/actionscript-settings.png" alt="" width="548" height="167" /></a><p class="wp-caption-text">Advanced ActionScript 3.0 Settings</p></div>
<p>You can reference the <em>timeline-sound.swc</em> in each <em>FLA</em> now. Therefore open your <em>FLA</em> and navigate to <em>File -&gt; ActionScript Settings&#8230;</em> Here go to the second tab &#8220;<em>Library path</em>&#8221; and select the &#8220;<em>Browse to SWC file</em>&#8221; button (1). After choosing the <em>timeline-sound.swc</em> it shows up in the panel underneath (2). Now you can use the <tt>playSound()</tt> function as frame script without getting a compiler error. At the same time your sound logic keeps separate.</p>
<h4>Technical implementation</h4>
<p>This section will explain how top-level function, delegate and sound logic get wired together. Therefore lets see what the contents of the <em>timeline-sound.swc</em> are. You can <a href="https://github.com/MattesGroeger/as3-timeline-sound" target="_blank">browse and download the source code from GitHub</a> or just read on.</p>
<div id="attachment_466" class="wp-caption aligncenter" style="width: 217px"><img class="size-full wp-image-466" title="Contents of 'timeline-sound.swc'" src="http://blog.mattes-groeger.de/wp-content/uploads/2012/01/timeline-sound-contents.png" alt="" width="207" height="140" /><p class="wp-caption-text">Contents of &#39;timeline-sound.swc&#39;</p></div>
<p style="text-align: left;">The <strong><tt>SoundDelegate</tt></strong> contains only static methods. Therefore it can be reached from anywhere in the application (including the top-level function <tt>playSound()</tt>). It&#8217;s implementation is rather simple. It basically just holds a reference to another instance that it delegates to (line 18). Again, for encapsulation reasons this is implemented as an interface <tt>ISoundAdapter</tt> (line 3).</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #9900cc; font-weight: bold;">class</span> SoundDelegate<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">private</span> static <span style="color: #6699cc; font-weight: bold;">var</span> adapter<span style="color: #000066; font-weight: bold;">:</span>ISoundAdapter<span style="color: #000066; font-weight: bold;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> static <span style="color: #339966; font-weight: bold;">function</span> <span style="color: #004993;">init</span><span style="color: #000000;">&#40;</span>adapter<span style="color: #000066; font-weight: bold;">:</span>ISoundAdapter = <span style="color: #0033ff; font-weight: bold;">null</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">:</span><span style="color: #0033ff; font-weight: bold;">void</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SoundDelegate<span style="color: #000066; font-weight: bold;">.</span>adapter = <span style="color: #000000;">&#40;</span>adapter <span style="color: #000066; font-weight: bold;">!</span>= <span style="color: #0033ff; font-weight: bold;">null</span><span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">?</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; adapter <span style="color: #000066; font-weight: bold;">:</span> <span style="color: #0033ff; font-weight: bold;">new</span> NullSoundAdapter<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> static <span style="color: #339966; font-weight: bold;">function</span> <span style="color: #0033ff; font-weight: bold;">get</span> initialized<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">:</span><a href="http://www.google.com/search?q=boolean%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:boolean.html"><span style="color: #004993;">Boolean</span></a><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">return</span> adapter <span style="color: #000066; font-weight: bold;">!</span>= <span style="color: #0033ff; font-weight: bold;">null</span><span style="color: #000066; font-weight: bold;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> static <span style="color: #339966; font-weight: bold;">function</span> playSound<span style="color: #000000;">&#40;</span>key<span style="color: #000066; font-weight: bold;">:</span><a href="http://www.google.com/search?q=string%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:string.html"><span style="color: #004993;">String</span></a><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">:</span><span style="color: #0033ff; font-weight: bold;">void</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; adapter<span style="color: #000066; font-weight: bold;">.</span>playSound<span style="color: #000000;">&#40;</span>key<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>You can also see an <tt>init()</tt> function (line 5) which is used to set the proper <strong><tt>ISoundAdapter</tt></strong> implementation. The <tt>ISoundAdapter</tt> defines just one method:</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0033ff; font-weight: bold;">public</span> interface ISoundAdapter<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #339966; font-weight: bold;">function</span> playSound<span style="color: #000000;">&#40;</span>key<span style="color: #000066; font-weight: bold;">:</span><a href="http://www.google.com/search?q=string%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:string.html"><span style="color: #004993;">String</span></a><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">:</span><span style="color: #0033ff; font-weight: bold;">void</span><span style="color: #000066; font-weight: bold;">;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>In line 8 of the <tt>SoundDelegate</tt> listing you will also notice that a <tt>NullSoundAdapter</tt> is assigned in case no instance gets passed to this method. This null-implementation silently ignores every call to <tt>playSound()</tt>. And this is how the <strong><tt>playSound()</tt></strong> top-level function looks like:</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #339966; font-weight: bold;">function</span> playSound<span style="color: #000000;">&#40;</span>title<span style="color: #000066; font-weight: bold;">:</span><a href="http://www.google.com/search?q=string%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:string.html"><span style="color: #004993;">String</span></a><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">:</span><span style="color: #0033ff; font-weight: bold;">void</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #000066; font-weight: bold;">!</span>SoundDelegate<span style="color: #000066; font-weight: bold;">.</span>initialized<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SoundDelegate<span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">init</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
&nbsp; &nbsp; SoundDelegate<span style="color: #000066; font-weight: bold;">.</span>playSound<span style="color: #000000;">&#40;</span>title<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>The function makes sure that the <tt>SoundDelegate</tt> class gets initialized. Because it will create the <tt>NullSoundAdapter</tt> by default, it is not very useful yet. Thats where the actual sound logic comes in. Whenever the logic is ready it calls the <tt>SoundDelegate</tt> and registers itself as <tt>SoundAdapter</tt> (line 5):</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #9900cc; font-weight: bold;">class</span> SoundLogic implements ISoundAdapter<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #339966; font-weight: bold;">function</span> SoundLogic<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900; font-style: italic;">// Do this after sounds are loaded</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SoundDelegate<span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">init</span><span style="color: #000000;">&#40;</span><span style="color: #0033ff; font-weight: bold;">this</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #339966; font-weight: bold;">function</span> playSound<span style="color: #000000;">&#40;</span>key<span style="color: #000066; font-weight: bold;">:</span><a href="http://www.google.com/search?q=string%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:string.html"><span style="color: #004993;">String</span></a><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">:</span><span style="color: #0033ff; font-weight: bold;">void</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900; font-style: italic;">// play the sound for 'key'</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>The <tt>SoundLogic</tt> class implements the <tt>ISoundAdapter</tt> interface. Now whenever someone calls <tt>playSound("foo")</tt> the method <tt>SoundLogic.playSound()</tt> will be called with the string &#8220;<tt>foo</tt>&#8220;. Here you can now put all the logic that is necessary to play the sound for string &#8220;<tt>foo</tt>&#8220;.</p>
<h4>Adding new sounds</h4>
<p>Well you could now argue that, with this solution, adding new sounds still requires programmatic effort. In <a href="http://apps.facebook.com/magicland/" target="_blank">Magic Land</a> (the game I worked on <a href="http://www.wooga.com/" target="_blank">at wooga</a>) we also found a proper solution for this. Before I can explain it you have to know that in our game the sound logic is encapsulated within a module (<em>SWF</em>). This module is loaded lazy because it is less important than other parts of the game. A user can already play our game while the sounds are still loading.</p>
<p>The idea is to embed all sounds that could be triggered from the timeline in a single <em>FLA</em>, so the artists can maintain it. Sounds have to be exported for ActionScript, where the linkage name matches the string that will be later used for the <tt>playSound()</tt> method parameter. In order to make the sounds available to the sound logic we chose to compile them into the sound module itself. This way we get good compression and have no additional loading effort. Note however that this approach wouldn&#8217;t make sense for large sound files.</p>
<div id="attachment_476" class="wp-caption aligncenter" style="width: 532px"><a href="http://blog.mattes-groeger.de/wp-content/uploads/2012/01/sound-library.png"><img class=" wp-image-476  " title="Sound FLA" src="http://blog.mattes-groeger.de/wp-content/uploads/2012/01/sound-library.png" alt="" width="522" height="192" /></a><p class="wp-caption-text">sounds.fla</p></div>
<p>The question is now, how do we get new sounds automatically compiled into the sound module? What we did, we created a Sprite that contains all sounds. The <em>FLA</em> file then gets compiled into a <em>SWC</em> library and is part of the sound module classpath. To enforce the inclusion of the sound definitions the exported <tt>SoundInclusionContainer</tt> class is once referenced in the module:</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900; font-style: italic;">// Sound module constructor</span><br />
<span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #339966; font-weight: bold;">function</span> SoundModule<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; SoundInclusionContainer<span style="color: #000066; font-weight: bold;">;</span> <span style="color: #009900; font-style: italic;">// sound embedding</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>This way, whenever the sound module gets compiled, all linked sounds within the container will be made available for the <tt>playSound()</tt> method call. Now the complete flow of adding and using timeline sounds is independent of the programmers while providing an optimized sound loading experience.</p>
<h3>Summary</h3>
<p>This post showed how artists can easily link timeline animations to a more complex logic. As this post is more about the general idea I didn&#8217;t explain how the sound logic itself looks like.</p>
<p>I found another use cases for this pattern in our game <a href="http://apps.facebook.com/magicland/" target="_blank">Magic Land</a>. We use it for displaying visual effects. Similar to sounds they are part of a separate module that is lazy loaded. On low performance computers we could disable the effects completely.</p>
<p>Finally, lets have a look on the pros and cons of this pattern.</p>
<h4>Disadvantages</h4>
<p>The artists won&#8217;t be able to hear the sound wile testing their sole assets. They have to start the game including the sound logic in order to hear something. In <a href="http://apps.facebook.com/magicland/" target="_blank">Magic Land</a> the artists are able to build the game locally on their computer (probably a topic for another blog post). So they can hear how it feels in the actual game.</p>
<p>Another drawback is that each asset <em>FLA</em> that makes use of the timeline actions has to link the <em>timeline-sound.swc</em>, which adds 2 Kb. A solution would be to exclude the library for compiling and enforce it to compile in the main application. But then running the asset <em>SWF</em> outside the final application/game throws errors and timeline animations won&#8217;t be visible anymore.</p>
<h4>Advantages</h4>
<p>On the positive side programmers get less distracted by sound issues because artists can do everything on their own. They are free to add the <tt>playSound()</tt> call in any asset file, as long as they link the <em>timeline-sound.swc</em> into the <em>FLA</em> file.</p>
<p>At the same time the sounds itself can be loaded after more important stuff has been done loading. This leads to a much better user experience. Also imagine a user turned off sounds. Now you can just not load the sounds at all and the <tt>playSound()</tt> call will be silently ignored (null-implementation of <tt>ISoundAdapter</tt>).</p>
<h4>Sources</h4>
<p>You can find all source files for the timeline-sound library in <a href="https://github.com/MattesGroeger/as3-timeline-sound" target="_blank">this GitHub repository</a>. If you have any questions feel free to comment below. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattes-groeger.de/actionscript/flash-timeline-actions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Context-aware Tasks</title>
		<link>http://blog.mattes-groeger.de/actionscript/context-aware-tasks/</link>
		<comments>http://blog.mattes-groeger.de/actionscript/context-aware-tasks/#comments</comments>
		<pubDate>Sun, 13 Mar 2011 19:03:07 +0000</pubDate>
		<dc:creator>Mattes</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[parsley]]></category>
		<category><![CDATA[spicelib]]></category>
		<category><![CDATA[task]]></category>

		<guid isPermaLink="false">http://blog.mattes-groeger.de/?p=364</guid>
		<description><![CDATA[This article shows an useful way how to combine the Spicelib Task Framework with Parsley. This way you can access everything from the context during the execution of a Task: &#8220;The Task Framework is a general abstraction for asynchronous operations. It allows nesting / grouping of Tasks in TaskGroup instances for concurrent or sequential execution&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>This article shows an useful way how to combine the <a href="http://www.spicefactory.org/parsley/download.php" target="_blank">Spicelib</a> <a href="http://www.spicefactory.org/parsley/docs/2.3/manual/task.php#intro" target="_blank">Task Framework</a> with <a href="http://www.spicefactory.org/parsley/download.php" target="_blank">Parsley</a>. This way you can access everything from the context during the execution of a <tt>Task</tt>:</p>
<p><em>&#8220;The Task Framework is a general abstraction for asynchronous operations. It allows nesting / grouping of Tasks in TaskGroup instances for concurrent or sequential execution&#8221;</em> [source: <a href="http://www.spicefactory.org/parsley/docs/2.3/manual/task.php#intro" target="_blank">Parsley Documentation</a>]</p>
<p>One way to access the <tt>Context</tt> from within a <tt>Task</tt> would be to define it during the <a href="http://www.spicefactory.org/parsley/docs/2.3/manual/config.php" target="_blank">Parsley Configuration</a> (<tt>Context</tt>). But this would mean, that the <tt>Task</tt> will not be removed until the context gets destroyed. Because a <tt>Task</tt> is only active during a limited time, this doesn&#8217;t make much sense.</p>
<p>Another approach would be, not to define the <tt>Task</tt> in the <tt>Context</tt> but passing in all the necessary dependencies within the constructor. Depending on the amount of required dependencies, the constructor can become quite big. Also <tt>Parsley</tt> features like <a href="http://www.spicefactory.org/parsley/docs/2.3/manual/messaging.php#intro" target="_blank">Messaging</a> are not directly supported anymore.</p>
<h3>Solution</h3>
<p>That&#8217;s why this solution utilizes the <a href="http://www.spicefactory.org/parsley/docs/2.3/manual/lifecycle.php#dynamic" target="_blank">Dynamic Object</a> feature of Parsley. It allows to add any instance to the <tt>Context</tt> during runtime and also removing it again, if not required anymore. For a <tt>Task</tt> this means that it needs to be added before the <tt>start()</tt> is called, and removed after the <tt>complete()</tt> has been triggered.</p>
<p>This adding/removing happens through the <tt>Context</tt> interface of Parsley. It should happen automatically in the <tt>Task</tt> to reduce the amount of code to write. In order to not have to pass the <tt>Context</tt> to each <tt>Task</tt> it could just be set once in the parent <tt>TaskGroup</tt>. The child <tt>Task</tt> then accesses it via the <tt>parent</tt> getter:</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SequentialContextTaskGroup <span style="color: #0066CC;">extends</span> <br />
&nbsp; &nbsp; SequentialTaskGroup <span style="color: #0066CC;">implements</span> IContextProvider<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _context:Context;<br />
<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> SequentialContextTaskGroup<span style="color: #66cc66;">&#40;</span>context:Context, <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">name</span>:<span style="color: #0066CC;">String</span> = <span style="color: #000000; font-weight: bold;">null</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; _context = context;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">super</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">name</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #0066CC;">get</span> context<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:Context<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> _context;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>And this is how the <tt>IContextProvider</tt> interface looks like:</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #0066CC;">interface</span> IContextProvider<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #0066CC;">get</span> context<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:Context;<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>The following <tt>AbstractContextTask</tt> is then responsible for adding itself to the <tt>Context</tt> as soon as it is started. It also removes itself as soon as the <tt>complete()</tt>, <tt>cancel()</tt> or <tt>skip()</tt> has been called. Furthermore it provides a <tt>doStartContext()</tt> method (read more in the next paragraph).</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AbstractContextTask <span style="color: #0066CC;">extends</span> Task<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _dynamicObject:DynamicObject;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; protected override <span style="color: #000000; font-weight: bold;">function</span> doStart<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; _dynamicObject = IContextProvider<span style="color: #66cc66;">&#40;</span>parent<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #006600;">context</span>.<span style="color: #006600;">addDynamicObject</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">this</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; doStartContext<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">super</span>.<span style="color: #006600;">doStart</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; protected <span style="color: #000000; font-weight: bold;">function</span> doStartContext<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* base implementation does nothing */</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; protected override <span style="color: #000000; font-weight: bold;">function</span> doCancel<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cleanContext<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">super</span>.<span style="color: #006600;">doCancel</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; protected override <span style="color: #000000; font-weight: bold;">function</span> doSkip<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cleanContext<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">super</span>.<span style="color: #006600;">doSkip</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; protected override <span style="color: #000000; font-weight: bold;">function</span> complete<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">Boolean</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cleanContext<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0066CC;">super</span>.<span style="color: #006600;">complete</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> cleanContext<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; _dynamicObject.<span style="color: #006600;">remove</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>The following class is a concrete implementation of <tt>AbstractContextTask</tt>. That&#8217;s why it gets the <tt>HintComponent</tt> injected (line 4). Please also note that this <tt>Task</tt> overrides the method <tt>doStartContext()</tt> (line 13). This way we ensure that the class already has been added to the <tt>Context</tt>.</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ShowHintTask <span style="color: #0066CC;">extends</span> AbstractContextTask<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>Inject<span style="color: #66cc66;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">var</span> hint:HintComponent;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">type</span>:HintType;<br />
<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> ShowHintTask<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">type</span>:HintType<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">this</span>.<span style="color: #0066CC;">type</span> = <span style="color: #0066CC;">type</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; protected override <span style="color: #000000; font-weight: bold;">function</span> doStartContext<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; hint.<span style="color: #006600;">showHint</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">type</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; complete<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>The following code shows how everything can be glued together. Note, that you don&#8217;t have to pass the <tt>Context</tt> to each task.</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TaskController<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>Inject<span style="color: #66cc66;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">var</span> context:Context;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>Init<span style="color: #66cc66;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> initialize<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> taskGroup:SequentialContextTaskGroup<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; = <span style="color: #000000; font-weight: bold;">new</span> SequentialContextTaskGroup<span style="color: #66cc66;">&#40;</span>context<span style="color: #66cc66;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; taskGroup.<span style="color: #006600;">addTask</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> ShowHintTask<span style="color: #66cc66;">&#40;</span>HintType.<span style="color: #006600;">ATTENTION</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; taskGroup.<span style="color: #006600;">addTask</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> PointToTask<span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Point<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span>, <span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// add more tasks here...</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; taskGroup.<span style="color: #0066CC;">start</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<h3>Summary</h3>
<p>This approach of <tt>Context</tt>-aware <tt>Tasks</tt> ensures that you don&#8217;t have a lot of <tt>Tasks</tt> at the same time in the <tt>Context</tt>. The adding and removing from the <tt>Context</tt> happens in an encapsulated class. The <tt>Task</tt> itself can directly access injected objects during execution time.</p>
<h3>Links</h3>
<ul>
<li><a href="http://blog.mattes-groeger.de/actionscript/strong-typed-constants/" target="_blank">Strong typed constants</a></li>
<li><a href="http://www.spicefactory.org/parsley/docs/2.3/manual/task.php" target="_blank">Task framework documentation</a></li>
<li><a href="http://www.spicefactory.org/parsley/download.php">Parsley/Spicelib download</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattes-groeger.de/actionscript/context-aware-tasks/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Label validation with FlexUnit</title>
		<link>http://blog.mattes-groeger.de/actionscript/label-validation-with-flexunit/</link>
		<comments>http://blog.mattes-groeger.de/actionscript/label-validation-with-flexunit/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 21:36:46 +0000</pubDate>
		<dc:creator>Mattes</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[label]]></category>
		<category><![CDATA[swc]]></category>
		<category><![CDATA[unit tests]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://blog.mattes-groeger.de/?p=249</guid>
		<description><![CDATA[While working in interdisciplinary teams where graphics are produced by artists and the code comes from the developers, a solid designer-developer work-flow is crucial. At my current project team at wooga we already established a very good work-flow. The artists can produce graphics and see them in the running application after committing them. Therefore we [...]]]></description>
			<content:encoded><![CDATA[<p>While working in interdisciplinary teams where graphics are produced by artists and the code comes from the developers, a solid designer-developer work-flow is crucial. At my current project team at <a href="http://www.wooga.com" target="_blank">wooga</a> we already established a very good work-flow. The artists can produce graphics and see them in the running application after committing them. Therefore we use <a href="http://subversion.tigris.org/" target="_blank">SVN</a> and the <a href="http://hudson-ci.org/" target="_blank">Hudson integration server</a>. </p>
<h3>The problem</h3>
<p>In our project we use <a href="http://www.richardleggett.co.uk/blog/index.php/2010/03/08/flash_builder_and_flash_pro_asset_workflows" target="_blank">SWC asset libraries</a> to have a compile time check and strong typed access to all our graphics. To add logic to <tt>MovieClip</tt> frames you could either put the code directly on the timeline or the artist defines labels which are then utilized from the code. In order to keep the view separated from the code you should always use the label approach. But this is also risky if the artist accidentally deletes or renames a label. The code would then behave unexpectedly without knowing it. The only way to see the problem is to start the application and test all the <tt>MovieClip</tt> logic.</p>
<h3>The first approach</h3>
<p>To protect the labels from unintended changes, our first approach was to check their existence wherever we used them in code. This means we had to provide a separate <tt>Vector</tt> that contained all the expected labels.</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">private</span> <span style="color: #0066CC;">static</span> <span style="color: #000000; font-weight: bold;">var</span> labels:Vector.<span style="color: #66cc66;">&lt;</span>String<span style="color: #66cc66;">&gt;</span> = <span style="color: #000000; font-weight: bold;">new</span> Vector.<span style="color: #66cc66;">&lt;</span>String<span style="color: #66cc66;">&gt;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> view:IconView;<br />
<br />
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> IconMediator<span style="color: #66cc66;">&#40;</span>view:IconView<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; initializeLabels<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; assertLabelsExist<span style="color: #66cc66;">&#40;</span>view<span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span><br />
<br />
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> initializeLabels<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>labels.<span style="color: #0066CC;">length</span> == <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; labels.<span style="color: #0066CC;">push</span><span style="color: #66cc66;">&#40;</span>IconState.<span style="color: #0066CC;">ON</span>, IconState.<span style="color: #006600;">OFF</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span><br />
<br />
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> assertLabelsExist<span style="color: #66cc66;">&#40;</span>view:ButtonRounded<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> requiredMatchesRemaining:<span style="color: #0066CC;">int</span> = labels.<span style="color: #0066CC;">length</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #b1b100;">each</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> requiredLabel:<span style="color: #0066CC;">String</span> <span style="color: #b1b100;">in</span> labels<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #b1b100;">each</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> label:FrameLabel <span style="color: #b1b100;">in</span> view.<span style="color: #006600;">currentLabels</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>requiredLabel == label.<span style="color: #0066CC;">name</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requiredMatchesRemaining--;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>requiredMatchesRemaining <span style="color: #66cc66;">!</span>= <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> IllegalArgumentError<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'IconView requires all labels: '</span> + labels<span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>Beside this we defined the labels itself in an <a href="http://blog.mattes-groeger.de/actionscript/strong-typed-constants/" target="_blank">enumeration class</a> to provide strong typed access.</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> IconState<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> const <span style="color: #0066CC;">ON</span>:IconState = <span style="color: #000000; font-weight: bold;">new</span> IconState<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;on&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> const OFF:IconState = <span style="color: #000000; font-weight: bold;">new</span> IconState<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;off&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">type</span>:<span style="color: #0066CC;">String</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> IconState<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">type</span>:<span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">this</span>.<span style="color: #0066CC;">type</span> = <span style="color: #0066CC;">type</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #0066CC;">toString</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">String</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0066CC;">type</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>This approach leads to three main problems:</p>
<ol>
<li>Depending on when the validation is executed in code, it could still happen that you don&#8217;t see the problems immediately</li>
<li>We create a lot of code that is only necessary for validation but not for the application itself</li>
<li>We create redundancy because we have to maintain the <tt>Vector</tt> of expected labels and the enumeration class (<tt>IconState</tt>). When changing labels it is very likely that you forget to update the Vector.</li>
</ol>
<h3>The solution</h3>
<p>Thats why we came up with a different approach. We moved the validation into the unit tests. Now the code is separated but still executed because of our integration server (Hudson with <a href="http://www.flexunit.org/" target="_blank">FlexUnit support</a>). The normal application code is now much slimmer and better readable. The artists/developers are automatically notified by mail if their changes break the tests.</p>
<p>To solve point 3 I wrote an assertion method that can reflect on enumeration classes and check all the defined labels on a certain MovieClip.</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> assertLabelEnum<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">target</span>:<span style="color: #0066CC;">MovieClip</span>, <br />
&nbsp; &nbsp; enumClass:<span style="color: #000000; font-weight: bold;">Class</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> classInfo:ClassInfo = ClassInfo.<span style="color: #006600;">forClass</span><span style="color: #66cc66;">&#40;</span>enumClass<span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> properties:<span style="color: #0066CC;">Array</span> = classInfo.<span style="color: #006600;">getStaticProperties</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> expectedLabel : <span style="color: #0066CC;">String</span>;<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">type</span>:<span style="color: #66cc66;">*</span>;<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> labelCounter:<span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #b1b100;">each</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> property : Property <span style="color: #b1b100;">in</span> properties<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">type</span> = property.<span style="color: #006600;">getValue</span><span style="color: #66cc66;">&#40;</span>enumClass<span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">type</span> is <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; expectedLabel = <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">type</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">type</span> is enumClass<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">type</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">&quot;toString&quot;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; labelCounter++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; expectedLabel = <span style="color: #0066CC;">type</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">&quot;toString&quot;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; assertLabel<span style="color: #66cc66;">&#40;</span>expectedLabel, <span style="color: #0066CC;">target</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; assertEquals<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Amount of expected labels differs from the <br />
&nbsp; &nbsp; &nbsp; &nbsp; amount of existing labels&quot;</span>, labelCounter, <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">target</span>.<span style="color: #006600;">currentLabels</span>.<span style="color: #0066CC;">length</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>This method internally calls another assertion method <tt>assertLabel()</tt>. This method can also be used independently for testing specific labels without using enumeration classes.</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> assertLabel<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">target</span>:<span style="color: #0066CC;">MovieClip</span>, <br />
&nbsp; &nbsp; expectedLabel:<span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">var</span> found:<span style="color: #0066CC;">Boolean</span> = <span style="color: #000000; font-weight: bold;">false</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #b1b100;">each</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> label:FrameLabel <span style="color: #b1b100;">in</span> <span style="color: #0066CC;">target</span>.<span style="color: #006600;">currentLabels</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>expectedLabel == label.<span style="color: #0066CC;">name</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; found = <span style="color: #000000; font-weight: bold;">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">!</span>found<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; fail<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Expected label [&quot;</span> + expectedLabel + <span style="color: #ff0000;">&quot;] not <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; found in &quot;</span> + <span style="color: #0066CC;">target</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p><strong>Note:</strong> I used the reflection library from spicelib to retrieve all the static members of the enumeration class. You can <a href="http://www.spicefactory.org/parsley/" target="_blank">download the library here</a>.</p>
<p>And this is how the test method would look like:</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#91;</span>Test<span style="color: #66cc66;">&#93;</span><br />
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> test_icon_frame_labels<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; assertLabelEnum<span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> IconView<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, IconState<span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<h3>Summary</h3>
<p>We made very good experiences with this approach because unintended changes on the labels no longer lead to awkward behavior in the application itself. And of course the application code can focus on the main logic and is therefor better readable.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattes-groeger.de/actionscript/label-validation-with-flexunit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Strong typed constants</title>
		<link>http://blog.mattes-groeger.de/actionscript/strong-typed-constants/</link>
		<comments>http://blog.mattes-groeger.de/actionscript/strong-typed-constants/#comments</comments>
		<pubDate>Sun, 02 Jan 2011 18:19:10 +0000</pubDate>
		<dc:creator>Mattes</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[enum]]></category>

		<guid isPermaLink="false">http://blog.mattes-groeger.de/?p=284</guid>
		<description><![CDATA[Constants are commonly occurring in the ActionScript core classes. Typical examples are events (Event.COMPLETE) or general configurations (StageAlign.TOP_LEFT). These constants are typically of type String and grouped in one class. If you want to set the align property of the Stage for example you have to know where to look up the different possible constants. [...]]]></description>
			<content:encoded><![CDATA[<p>Constants are commonly occurring in the ActionScript core classes. Typical examples are events (<tt>Event.COMPLETE</tt>) or general configurations (<tt>StageAlign.TOP_LEFT</tt>). These constants are typically of type <tt>String</tt> and grouped in one class. </p>
<p>If you want to set the <tt>align</tt> property of the <tt>Stage</tt> for example you have to know where to look up the different possible constants. This can be done by looking up the documentation or by guessing the potential class name (<tt>StageAlign</tt>). IDEs like <a href="http://fdt.powerflasher.com" target="_blank">FDT</a> provide support for these constants by suggesting them in the auto completion. </p>
<p>However, the programmer is never enforced to use the existing constants and can assign any other string. This is error prone because the string is eventually misspelled. It is also annoying if you have to look up the documentation because your IDE doesn&#8217;t suggest them. If you use your own constants in an application or library then you are completely on your own.</p>
<p>Other programming languages like Java provide a special syntax for this problem: <tt>enum</tt></p>
<div class="codecolorer-container java dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">enum</span> Direction <span style="color: #009900;">&#123;</span>LEFT, RIGHT<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>This enumerations can then be used strong typed in code. For example a function can define this as type in the signature. Assigning something else than one of the predefined constants (<tt>LEFT</tt> or <tt>RIGHT</tt>) would cause a compiler error:</p>
<div class="codecolorer-container java dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> applyDirection<span style="color: #009900;">&#40;</span>Direction direction<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// use the enum here</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>The ActionScript language itself has no support for enumerations. But there is a solution: Instead of using constants of type <tt>String</tt> just use the type of the constants class itself.</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Direction<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> const <span style="color: #0066CC;">LEFT</span>:Direction = <span style="color: #000000; font-weight: bold;">new</span> Direction<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> const <span style="color: #0066CC;">RIGHT</span>:Direction = <span style="color: #000000; font-weight: bold;">new</span> Direction<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>A function can then look like this:</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> applyDirection<span style="color: #66cc66;">&#40;</span>direction:Direction<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span><br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">switch</span> <span style="color: #66cc66;">&#40;</span>direction<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">case</span> Direction.<span style="color: #0066CC;">LEFT</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// use direction here...</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">case</span> Direction.<span style="color: #0066CC;">RIGHT</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">// use direction here...</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">default</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> IllegalOperationError<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;Unsupported direction &quot;</span> + direction<span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">applyDirection<span style="color: #66cc66;">&#40;</span>Direction.<span style="color: #0066CC;">LEFT</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>You would still be able to create new instances of <tt>Direction</tt> and assign them. But the implementation of <tt>applyDirection()</tt> relies on the predefined constants. An error would be thrown if another instance would be assigned. Furthermore the user can see the different possible constants because he knows which specific type is required.</p>
<p>If you want to trace the <tt>Direction</tt> or if you want to store more information this is no problem, too:</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Direction<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> const <span style="color: #0066CC;">LEFT</span>:Direction = <span style="color: #000000; font-weight: bold;">new</span> Direction<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;left&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> const <span style="color: #0066CC;">RIGHT</span>:Direction = <span style="color: #000000; font-weight: bold;">new</span> Direction<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;right&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> direction:<span style="color: #0066CC;">String</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> Direction<span style="color: #66cc66;">&#40;</span>direction:<span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">this</span>.<span style="color: #006600;">direction</span> = direction;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #0066CC;">toString</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">String</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> direction;<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>Right now, this approach is the only way to provide type save enumerations in ActionScript. You should always use them if you write third party libraries. Also in projects with multiple developers this makes sense.</p>
<p><strong>Update 2011/03/13:</strong> In order to to restrict the enum to the predefined constants you could combine the declaration with a singleton enforcing approach. Just expect an instance of a nested class in the constructor:</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">package<br />
<span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Direction<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> const <span style="color: #0066CC;">LEFT</span>:Direction = <span style="color: #000000; font-weight: bold;">new</span> Direction<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">new</span> EnumEnforcer<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #ff0000;">&quot;left&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> const <span style="color: #0066CC;">RIGHT</span>:Direction = <span style="color: #000000; font-weight: bold;">new</span> Direction<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">new</span> EnumEnforcer<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #ff0000;">&quot;right&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> direction:<span style="color: #0066CC;">String</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> Direction<span style="color: #66cc66;">&#40;</span>enumEnforcer:EnumEnforcer, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; direction:<span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">this</span>.<span style="color: #006600;">direction</span> = direction;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #0066CC;">toString</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">String</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> direction;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> EnumEnforcer<br />
<span style="color: #66cc66;">&#123;</span><br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>Of course this is still not 100% save because you could just pass in <tt>null</tt>. In this case an error could be thrown. But this would happen at runtime only then.</p>
<p>Thanks to Thijs for pointing out this problem in the comments and Peter Höche for suggesting this solution.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattes-groeger.de/actionscript/strong-typed-constants/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Review: Logging with Trazzle</title>
		<link>http://blog.mattes-groeger.de/libraries/review-logging-with-trazzle/</link>
		<comments>http://blog.mattes-groeger.de/libraries/review-logging-with-trazzle/#comments</comments>
		<pubDate>Sun, 14 Nov 2010 16:39:01 +0000</pubDate>
		<dc:creator>Mattes</dc:creator>
				<category><![CDATA[Libraries]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[trazzle]]></category>

		<guid isPermaLink="false">http://blog.mattes-groeger.de/?p=155</guid>
		<description><![CDATA[A few weeks ago I discovered an ActionScript 3.0 Logger called Trazzle. It&#8217;s available for Mac only and provides a well-arranged, beautiful logging output, a performance monitor, bitmap logging and much more. In order to use this logger, you need to install the Logger Client and include the SWC files within your project. All source [...]]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago <a href="https://twitter.com/MattesGroeger/status/24742440693">I discovered</a> an ActionScript 3.0 Logger called Trazzle. </p>
<p>It&#8217;s available for Mac only and provides a well-arranged, beautiful logging output, a performance monitor, bitmap logging <a href="http://www.nesium.com/products/trazzle">and much more</a>. In order to use this logger, you need to install the <a href="http://www.nesium.com/products/trazzle">Logger Client</a> and include the <a href="http://github.com/nesium/trazzlelib-as3/downloads">SWC files</a> within your project. </p>
<p><img src="http://blog.mattes-groeger.de/wp-content/uploads/2010/09/Bildschirmfoto-2010-09-20-um-23.15.35.jpg" alt="" title="Trazzle" width="662" height="367" class="aligncenter size-full wp-image-160" /></p>
<p>All source files are <a href="http://github.com/nesium/trazzlelib-as3">available on GitHub</a> as well as a <a href="http://github.com/nesium/trazzle-demo-app">simple example</a>.</p>
<h3>Usage</h3>
<p>I assume the author tried to build a logger that is very easy to use. Therefor he provides package level functions which allow fast access to the core features. The logger classes behind can also be used. But this should not be part of this post. </p>
<p>The first step is to initialize to logging framework:</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">zz_init<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">stage</span>, <span style="color: #ff0000;">&quot;Logger app title&quot;</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>
<p><strong>Please note:</strong> The logging only works if you import the class <em>TrazzleLogger</em>. The reason why the demo application works: the <em>StatusBar</em> class holds a reference to <em>TrazzleLogger</em>. But normal logging will retrieve the reference only dynamically at runtime, so you have to take care of importing it on your own.</p>
<p>After initialization you can trigger the log messages. By default they will be displayed as plain white text. To make use of the different log levels you have to prepend one of the following characters:</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;normal&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;d debug&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;i info&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;n notice&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;w warning&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;e error&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;c critical&quot;</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;f fatal&quot;</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>This syntax is one of the main differences to other logging frameworks. Because of this convention it es very fast to use. You don&#8217;t have to retrieve a logger instance and define a strong typed log level. Unfortunately the drawback is, you have to know the convention and you are responsible to use it correctly as there is no compile time check.</p>
<p>You can also use the classical <em>printf</em> behavior which allows to define a string with placeholders that will be replaced at runtime. Again, in order to use this feature you have to make sure that the method printf is compiled into the application.</p>
<div class="codecolorer-container actionscript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="actionscript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">logf<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;There is a difference between %s and %s&quot;</span>, <span style="color: #ff0000;">&quot;good&quot;</span>, <span style="color: #ff0000;">&quot;evil&quot;</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>Furthermore with the function <em>zz_inspect(object)</em> you should be able to see all the fields and values of an instance. For some reason I didn&#8217;t get it to work. Please comment below if you found a solution.</p>
<h3>Filtering</h3>
<p>In contrast to other logging frameworks it is not possible to configure the logging visibility for certain packages and log levels from within the flash client. Instead the configuration will completely take place in the Trazzle application by using the filters window. Here you can define and combine different rules. Excluding specific packages is not possible. You can save each filter set for later usage.</p>
<p><img src="http://blog.mattes-groeger.de/wp-content/uploads/2010/09/Screen-shot-2010-09-26-at-22.43.12.png" title="Trazzle Filters" width="784" height="302" class="aligncenter size-full wp-image-173" /></p>
<h3>Performance Monitor</h3>
<p>The performance monitor gives you a chronological sequence of the memory consumption and the frames per second (fps). It worked for me but I have not really tested it.</p>
<h3>Conclusion</h3>
<p>Using the trazzle logging framework will force you to use the Trazzle application which is available for OS X only. So if you work in larger teams you have to take into consideration that you can not exchange the logging appender easily. </p>
<p>What I think is a bit strange, is that you have to manually import the TrazzleLogger in order to use it via the package level functions. This makes it difficult to enable/disable the logging on different environments like on debug and release stages. Reading traces is also very exhausting because you have to read small grey text on a black background. And if you copy the text into another editor it is broken by the line numbers. The other log messages are better readable (see first image).</p>
<p>Apart from this cons you get an easy to use logger which has useful additional features like bitmap data output. With this feature I was able to easily find a bitmap that accidentally prevented clicks. What I especially like is the StackTrace which you can see for each log entry. Because the logger is very easy and fast to use you can eventually use him for some special cases only.</p>
<p>One final note: To see the line numbers you have to compile with the compiler flag &#8220;-verbose-stacktraces&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattes-groeger.de/libraries/review-logging-with-trazzle/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Short-lived Commands with Parsley</title>
		<link>http://blog.mattes-groeger.de/actionscript/short-lived-commands-with-parsley/</link>
		<comments>http://blog.mattes-groeger.de/actionscript/short-lived-commands-with-parsley/#comments</comments>
		<pubDate>Sun, 31 Oct 2010 12:45:23 +0000</pubDate>
		<dc:creator>Mattes</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[command]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[parsley]]></category>

		<guid isPermaLink="false">http://blog.mattes-groeger.de/?p=187</guid>
		<description><![CDATA[This week we had to decide on a MVC Framework for our next game at Wooga. In the end we had to decide between Robotlegs and Parsley. Both of them had pros and cons which I will maybe explain at a later time. One aspect we came across was the support of Short-lived Command Objects. [...]]]></description>
			<content:encoded><![CDATA[<p>This week we had to decide on a <a href="http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller" target="_blank">MVC Framework</a> for our next game at <a href="http://www.wooga.com">Wooga</a>. In the end we had to decide between <strong><a href="http://www.robotlegs.org/" target="_blank">Robotlegs</a></strong> and <strong><a href="http://www.spicefactory.org/parsley/" target="_blank">Parsley</a></strong>. Both of them had pros and cons which I will maybe explain at a later time.</p>
<p>One aspect we came across was the support of <em>Short-lived Command Objects</em>. These Commands hold no state and will be garbage collected after execution. In Robotlegs they are supported via the <a href="http://api.robotlegs.org/org/robotlegs/core/ICommandMap.html" target="_blank"><em>ICommandMap</em></a> interface. Parsley also provides an implementation of this pattern called <a href="http://www.spicefactory.org/parsley/docs/2.3/manual/messaging.php#command_objects" target="_blank"><em>DynamicCommand</em></a>. In contrast to Robotlegs, Parsley provides 4 different ways to build and configure a context:</p>
<ul>
<li><a href="http://www.spicefactory.org/parsley/docs/2.3/manual/config.php#mxml" target="_blank">MXML</a>: DynamicCommand Tag. Only for Flex projects.</li>
<li><a href="http://www.spicefactory.org/parsley/docs/2.3/manual/config.php#xml" target="_blank">XML</a>: DynamicCommand Node. No compiler check on types possible.</li>
<li><a href="http://www.spicefactory.org/parsley/docs/2.3/manual/config.php#as3" target="_blank">ActionScript</a>: No way to configure dynamic Commands.</li>
<li><a href="http://www.spicefactory.org/parsley/docs/2.3/manual/config.php#dsl" target="_blank">Configuration DSL</a>: Programmatic configuration of Dynamic Commands.</li>
</ul>
<p>Because our game should not use the Flex framework, the last option is our only choice if we want to have strongly typed Command mappings like in Robotlegs. </p>
<h3>DynamicCommands via Configuration DSL</h3>
<p>Because a documentation is not available for this case it was a bit tricky to find the solution (thanks for the hint, Jens). This was the first result:</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #6699cc; font-weight: bold;">var</span> contextBuilder<span style="color: #000066; font-weight: bold;">:</span>ContextBuilder = ContextBuilder<span style="color: #000066; font-weight: bold;">.</span>newSetup<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>viewRoot<span style="color: #000000;">&#40;</span><span style="color: #0033ff; font-weight: bold;">this</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>newBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
<span style="color: #6699cc; font-weight: bold;">var</span> targetDef<span style="color: #000066; font-weight: bold;">:</span>DynamicObjectDefinition = contextBuilder<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>objectDefinition<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>forClass<span style="color: #000000;">&#40;</span>CommandType<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>asDynamicObject<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>build<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
DynamicCommandBuilder<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>newBuilder<span style="color: #000000;">&#40;</span>targetDef<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>builder<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>messageType<span style="color: #000000;">&#40;</span>MessageType<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>stateful<span style="color: #000000;">&#40;</span><span style="color: #0033ff; font-weight: bold;">false</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">.</span>build<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
contextBuilder<span style="color: #000066; font-weight: bold;">.</span>config<span style="color: #000000;">&#40;</span>ActionScriptConfig<span style="color: #000066; font-weight: bold;">.</span>forClass<span style="color: #000000;">&#40;</span>MainConfig<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
contextBuilder<span style="color: #000066; font-weight: bold;">.</span>build<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span></div></td></tr></tbody></table></div>
<p>Note that you can not use the <em>ActionScriptContexBuilder.build()</em> notation anymore. Instead you have to configure the whole context via the DSL. In line 18, the actual configuration (<em>MainConfig</em>) which contains all object definitions is passed in. </p>
<p>Because this configuration is very hard to read and redundant if you want to map several Commands, I encapsulated the mapping to a separate class <em>CommandMap</em>. Now the configuration looks like this:</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #6699cc; font-weight: bold;">var</span> contextBuilder<span style="color: #000066; font-weight: bold;">:</span>ContextBuilder = ContextBuilder<span style="color: #000066; font-weight: bold;">.</span>newSetup<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
<span style="color: #000066; font-weight: bold;">.</span>viewRoot<span style="color: #000000;">&#40;</span><span style="color: #0033ff; font-weight: bold;">this</span><span style="color: #000000;">&#41;</span><br />
<span style="color: #000066; font-weight: bold;">.</span>newBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
<span style="color: #6699cc; font-weight: bold;">var</span> commandMap<span style="color: #000066; font-weight: bold;">:</span>CommandMap = <span style="color: #0033ff; font-weight: bold;">new</span> CommandMap<span style="color: #000000;">&#40;</span>contextBuilder<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
commandMap<span style="color: #000066; font-weight: bold;">.</span>register<span style="color: #000000;">&#40;</span>LoginCommand<span style="color: #000066; font-weight: bold;">,</span> LoginRequest<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
commandMap<span style="color: #000066; font-weight: bold;">.</span>register<span style="color: #000000;">&#40;</span>LogoutCommand<span style="color: #000066; font-weight: bold;">,</span> LogoutRequest<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
contextBuilder<span style="color: #000066; font-weight: bold;">.</span>config<span style="color: #000000;">&#40;</span>ActionScriptConfig<span style="color: #000066; font-weight: bold;">.</span>forClass<span style="color: #000000;">&#40;</span>MainConfig<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
contextBuilder<span style="color: #000066; font-weight: bold;">.</span>build<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span></div></td></tr></tbody></table></div>
<p>Until now I found no way to map or un-map Commands after the context has been built. The only way would be to destroy the context they are registered in.</p>
<p>To get a better impression how short-lived commands are used in Parsley, I implemented a small example, which you can <a href="http://github.com/MattesGroeger/as3-parsley-example" target="_blank">access on GitHub</a>. The CommandMap class can be <a href="http://github.com/MattesGroeger/as3-parsley-example/blob/master/src/de/mattesgroeger/parsley/core/CommandMap.as" target="_blank">found here</a>.</p>
<p>And this is how the login example looks like. Invalid credentials lead to an error pop up. Valid login works with &#8220;<strong>admin</strong>&#8221; and password &#8220;<strong>test</strong>&#8220;:</p>
<p><object style="width: 580px; height: 250px;" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="580" height="250" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="/wp-content/uploads/2010/10/ParsleyExample1.swf" /><embed style="width: 580px; height: 250px;" type="application/x-shockwave-flash" width="580" height="250" src="/wp-content/uploads/2010/10/ParsleyExample1.swf"></embed></object></p>
<h3>Summary</h3>
<p>The Robotlegs implementation is very straight forward. Commands can be mapped and un-mapped at any time. This is not possible in Parsley. But you have other features that give maybe similar results (for example <a href="http://www.spicefactory.org/parsley/docs/2.3/manual/messaging.php#interceptors" target="_blank">MessageInterceptors</a>). </p>
<p>Because Parsley reflects on the types you can pass data directly to the execute method. This way, each concrete execute method can receive strong typed parameters (see line 9). No framework class has to be extended for custom Commands. This is how a command can look like:</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #9900cc; font-weight: bold;">class</span> LogoutCommand<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Inject<span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #6699cc; font-weight: bold;">var</span> service<span style="color: #000066; font-weight: bold;">:</span>ISessionService<span style="color: #000066; font-weight: bold;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>MessageDispatcher<span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #6699cc; font-weight: bold;">var</span> dispatcher<span style="color: #000066; font-weight: bold;">:</span><a href="http://www.google.com/search?q=function%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:function.html"><span style="color: #004993;">Function</span></a><span style="color: #000066; font-weight: bold;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #339966; font-weight: bold;">function</span> execute<span style="color: #000000;">&#40;</span><span style="color: #004993;">message</span><span style="color: #000066; font-weight: bold;">:</span>LogoutRequest<span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> ServiceRequest<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">return</span> service<span style="color: #000066; font-weight: bold;">.</span>logout<span style="color: #000000;">&#40;</span><span style="color: #004993;">message</span><span style="color: #000066; font-weight: bold;">.</span>sessionId<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #339966; font-weight: bold;">function</span> result<span style="color: #000000;">&#40;</span>success<span style="color: #000066; font-weight: bold;">:</span><a href="http://www.google.com/search?q=boolean%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:boolean.html"><span style="color: #004993;">Boolean</span></a><span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> <span style="color: #0033ff; font-weight: bold;">void</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; dispatcher<span style="color: #000000;">&#40;</span><span style="color: #0033ff; font-weight: bold;">new</span> LogoutSuccess<span style="color: #000000;">&#40;</span>success<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>I also like the native support of synchronous and asynchronous Commands in Parsley. No special configuration is necessary, because Parsley reflects on the return type of the <em>execute()</em> method (line 9, <em>ServiceRequest</em>).</p>
<p><strong>Links:</strong></p>
<ul>
<li><a href="http://github.com/MattesGroeger/as3-parsley-example" target="_blank">Browse the example sources on GitHub</a></li>
<li><a href="http://github.com/MattesGroeger/as3-parsley-example/blob/master/README.md" target="_blank">Readme of the Example</a></li>
<li><a href="http://github.com/MattesGroeger/as3-parsley-example/blob/master/src/de/mattesgroeger/parsley/core/CommandMap.as" target="_blank">CommandMap source</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattes-groeger.de/actionscript/short-lived-commands-with-parsley/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Icon Badge for Windows</title>
		<link>http://blog.mattes-groeger.de/libraries/icon-badge-for-windows/</link>
		<comments>http://blog.mattes-groeger.de/libraries/icon-badge-for-windows/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 21:54:56 +0000</pubDate>
		<dc:creator>Mattes</dc:creator>
				<category><![CDATA[Air Icon Badge]]></category>
		<category><![CDATA[Libraries]]></category>
		<category><![CDATA[air]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[badge]]></category>
		<category><![CDATA[icon]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[system tray]]></category>

		<guid isPermaLink="false">http://blog.mattes-groeger.de/?p=122</guid>
		<description><![CDATA[Until now the Air Icon Badge library implementation only supports the OS X dock icon. Nevertheless it is easy to extend the implementation for utilizing it as Windows system tray icon. In this article I will demonstrate how this could be realized. Demo Therefore I extended the existing example implementation. Just choose &#8220;Window Tray Icon&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>Until now the <a href="http://blog.mattes-groeger.de/libraries/icon-badge-library-for-air/">Air Icon Badge library</a> implementation only supports the OS X dock icon. Nevertheless it is easy to extend the implementation for utilizing it as Windows system tray icon. In this article I will demonstrate how this could be realized.</p>
<h3>Demo</h3>
<p>Therefore I extended the existing example implementation. Just choose &#8220;Window Tray Icon&#8221; from the right panel for previewing the new icon.</p>
<p><object style="width: 580px; height: 350px;" width="580" height="350" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="/wp-content/uploads/2010/03/WebBadgeExample.swf" /><embed style="width: 580px; height: 350px;" width="580" height="350" type="application/x-shockwave-flash" src="/wp-content/uploads/2010/03/WebBadgeExample.swf" /></object></p>
<p>And this is how it will look like on Windows XP (Windows Vista and 7 will look the same).</p>
<p><img class="aligncenter size-full wp-image-138" title="WindowsSystemTray" src="http://blog.mattes-groeger.de/wp-content/uploads/2010/03/WindowsSystemTray.jpg" alt="" width="382" height="201" /></p>
<h3>Implementation</h3>
<p>The first class that I create is the <em>SystemTrayIconBuilder</em> (it must implement <em>IconBuilder</em> interface). This class is responsible for composing the system tray icon. It also sets the general icon size to 16 by 16 pixels.</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #9900cc; font-weight: bold;">class</span> SystemTrayIconBuilder <span style="color: #0033ff; font-weight: bold;">extends</span> AbstractIconBuilder<br />
implements IconBuilder<br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #0033ff; font-weight: bold;">public</span> override <span style="color: #339966; font-weight: bold;">function</span> createNewIcon<span style="color: #000000;">&#40;</span><span style="color: #004993;">width</span> <span style="color: #000066; font-weight: bold;">:</span> <a href="http://www.google.com/search?q=int%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:int.html"><span style="color: #004993;">int</span></a><span style="color: #000066; font-weight: bold;">,</span><br />
<span style="color: #004993;">height</span> <span style="color: #000066; font-weight: bold;">:</span> <a href="http://www.google.com/search?q=int%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:int.html"><span style="color: #004993;">int</span></a><span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> <span style="color: #0033ff; font-weight: bold;">void</span><br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #0033ff; font-weight: bold;">super</span><span style="color: #000066; font-weight: bold;">.</span>createNewIcon<span style="color: #000000;">&#40;</span><span style="color: #000000; font-weight:bold;">16</span><span style="color: #000066; font-weight: bold;">,</span> <span style="color: #000000; font-weight:bold;">16</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<span style="color: #000000;">&#125;</span><br />
<br />
<span style="color: #0033ff; font-weight: bold;">public</span> override <span style="color: #339966; font-weight: bold;">function</span> addBackground<span style="color: #000000;">&#40;</span><br />
<span style="color: #004993;">background</span> <span style="color: #000066; font-weight: bold;">:</span> <a href="http://www.google.com/search?q=bitmap%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:bitmap.html"><span style="color: #004993;">Bitmap</span></a><span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> <span style="color: #0033ff; font-weight: bold;">void</span><br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #004993;">background</span><span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">width</span> = <span style="color: #004993;">background</span><span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">height</span> = <span style="color: #000000; font-weight:bold;">16</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
container<span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">addChild</span><span style="color: #000000;">&#40;</span><span style="color: #004993;">background</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<span style="color: #000000;">&#125;</span><br />
<br />
<span style="color: #0033ff; font-weight: bold;">public</span> override <span style="color: #339966; font-weight: bold;">function</span> addBadge<span style="color: #000000;">&#40;</span>label <span style="color: #000066; font-weight: bold;">:</span> <a href="http://www.google.com/search?q=string%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:string.html"><span style="color: #004993;">String</span></a><span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> <span style="color: #0033ff; font-weight: bold;">void</span><br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #6699cc; font-weight: bold;">var</span> badge <span style="color: #000066; font-weight: bold;">:</span> TrayIconBadge = <span style="color: #0033ff; font-weight: bold;">new</span> TrayIconBadge<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
badge<span style="color: #000066; font-weight: bold;">.</span>label<span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">text</span> = label<span style="color: #000066; font-weight: bold;">;</span><br />
<br />
container<span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">addChild</span><span style="color: #000000;">&#40;</span>badge<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Please note the the <em>TrayIconBadge</em> class used in this example (line 17) is a MovieClip designed and exported (swc) with the Flash IDE. I used a pixel font for better readability. Because of the small icon size the visible letter count is also limited.</p>
<p>The next step is to create a custom <em>SystemTrayIconBadge</em> which has to implement the <em>IconBadge</em> interface. To avoid redundancies I extend the <em>DockIconBadge</em> class and override the factory method &#8220;<em>createIconBuilder()</em>&#8220;.</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #9900cc; font-weight: bold;">class</span> SystemTrayIconBadge <span style="color: #0033ff; font-weight: bold;">extends</span> DockIconBadge<br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #0033ff; font-weight: bold;">protected</span> override <span style="color: #339966; font-weight: bold;">function</span> createIconBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> IconBuilder<br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #0033ff; font-weight: bold;">return</span> <span style="color: #0033ff; font-weight: bold;">new</span> SystemTrayIconBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>The last step is to build the <em>CrossPlatformIconBadgeFactory</em> which implements <em>IconBadgeFactory</em>. It is responsible for detecting the users operating system and returning the corresponding <em>IconBadge</em>. Again I extend the existing factory class to avoid redundancies:</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #9900cc; font-weight: bold;">class</span> CrossPlatformIconBadgeFactory <span style="color: #0033ff; font-weight: bold;">extends</span><br />
AirIconBadgeFactroy<br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #0033ff; font-weight: bold;">public</span> override <span style="color: #339966; font-weight: bold;">function</span> create<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> IconBadge<br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #0033ff; font-weight: bold;">if</span> <span style="color: #000000;">&#40;</span>NativeApplication<span style="color: #000066; font-weight: bold;">.</span>supportsSystemTrayIcon<span style="color: #000000;">&#41;</span><br />
<span style="color: #0033ff; font-weight: bold;">return</span> <span style="color: #0033ff; font-weight: bold;">new</span> SystemTrayIconBadge<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
<span style="color: #0033ff; font-weight: bold;">return</span> <span style="color: #0033ff; font-weight: bold;">super</span><span style="color: #000066; font-weight: bold;">.</span>create<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<p>Finally for using the new factory it has to be assigned to the <em>AirIconBadge</em> class.</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">AirIconBadge<span style="color: #000066; font-weight: bold;">.</span>factory = <span style="color: #0033ff; font-weight: bold;">new</span> CrossPlatformIconBadgeFactory<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
AirIconBadge<span style="color: #000066; font-weight: bold;">.</span>label = <span style="color: #990000;">&quot;1&quot;</span><span style="color: #000066; font-weight: bold;">;</span></div></td></tr></tbody></table></div>
<h3>Summary</h3>
<p>As you can see, it is very little effort to add the windows system tray icon capability. You are free to (re)use this example. <a href="http://code.google.com/p/air-icon-badge/downloads/list" target="_blank">Binaries</a> and <a href="http://code.google.com/p/air-icon-badge/source/browse/#svn/air-icon-badge-examples/trunk/dev/src/de/mgroeger/air/icon/example/windows" target="_blank">sources</a> can be downloaded from the <a href="http://code.google.com/p/air-icon-badge/" target="_blank">google code project site</a>.</p>
<ul>
<li><a href="http://code.google.com/p/air-icon-badge/downloads/detail?name=air-icon-badge-examples.zip&amp;can=2&amp;q=#makechanges" target="_blank">Example Download (air/swf)</a></li>
<li><a href="http://code.google.com/p/air-icon-badge/source/browse/#svn/air-icon-badge-examples/trunk/dev/src/" target="_blank">Browse Example Sources</a></li>
<li><a href="http://code.google.com/p/air-icon-badge/downloads/detail?name=air-icon-badge-0.1.zip" target="_blank">Library Download</a></li>
</ul>
<p>Any comments will be appreciated.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattes-groeger.de/libraries/icon-badge-for-windows/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Icon Badge Library for Air</title>
		<link>http://blog.mattes-groeger.de/libraries/icon-badge-library-for-air/</link>
		<comments>http://blog.mattes-groeger.de/libraries/icon-badge-library-for-air/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 13:06:14 +0000</pubDate>
		<dc:creator>Mattes</dc:creator>
				<category><![CDATA[Air Icon Badge]]></category>
		<category><![CDATA[Libraries]]></category>
		<category><![CDATA[air]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[dock]]></category>
		<category><![CDATA[icon]]></category>
		<category><![CDATA[label]]></category>
		<category><![CDATA[library]]></category>

		<guid isPermaLink="false">http://blog.mattes-groeger.de/?p=9</guid>
		<description><![CDATA[A lot of Air applications are feed readers or social media clients. For this kind of applications it would be nice to be able to display the amount of unread news or messages while the application itself is hidden. With OS X you can use the dock icon for that purpose. The Cocoa Framework allows to display a user defined text consistently on top of the application icon. The screen shot at the right for example shows 2 unread messaged in the Mail.app inbox.]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p><img class="alignright size-full wp-image-102" title="OS X Dock Tile Badge" src="http://blog.mattes-groeger.de/wp-content/uploads/2010/02/mail.png" alt="" width="167" height="151" /> <a href="http://www.adobe.com/products/air/" target="_blank">Adobe Air</a> is often used to build feed readers or social media clients. This kind of applications can retrieve new data while they are running in the background. In that case it would be great to inform the user about the amount of new items. With OS X you can use the dock icon for that purpose. The Cocoa Framework allows to display a user defined text consistently on top of the application dock tile (icon). E.g. the screenshot at the right shows 2 unread mails in the inbox.</p>
<div id="attachment_104" class="wp-caption alignleft" style="width: 208px"><img class="size-full wp-image-104" title="Comparision between native and emulated badge" src="http://blog.mattes-groeger.de/wp-content/uploads/2010/02/comparision.png" alt="" width="198" height="139" /><p class="wp-caption-text">Native and emulated badge</p></div>
<p>Unfortunately the Air runtime allows no access to this native functionality. Thats why the idea for this library came up. It tries to emulate the native badge with the possibilities Air provides (see left image). Until now only the OS X badge is supported but a Windows implementation is possible, too. I will demonstrate the extensibility in one of the following blog posts.</p>
<h3>Demo</h3>
<p>If you have a Mac, you can <a href="http://code.google.com/p/air-icon-badge/downloads/detail?name=air-icon-badge-examples.zip&amp;can=2&amp;q=#makechanges" target="_blank">download this Air application</a> where the badge shows up on the real application icon. Running this application on windows will have no visual effect.</p>
<p>None Mac users can use the following demo that shows a preview of the dock icon:</p>
<p><object style="width: 580px; height: 400px;" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="580" height="400" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="/wp-content/uploads/2010/02/WebBadgeExample.swf" /><embed style="width: 580px; height: 400px;" type="application/x-shockwave-flash" width="580" height="400" src="/wp-content/uploads/2010/02/WebBadgeExample.swf"></embed></object></p>
<p>You can browse the sources for this example on the <a href="https://code.google.com/p/air-icon-badge/source/browse/#svn/air-icon-badge-examples/trunk" target="_blank">google code repository</a>.</p>
<h3>Usage</h3>
<p>To show the badge label you can use the static facade <em>AirIconBadge</em>. Internally it will create an <em>IconBadge</em> appropriate for the current operating system. <strong>Note:</strong> only one implementation for OS X is provided until now! Windows or Linux users won&#8217;t see a badge label.</p>
<p>With the static property <em>label</em> you can assign any string that should be displayed. Thats it.</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">AirIconBadge<span style="color: #000066; font-weight: bold;">.</span>label = <span style="color: #990000;">&quot;1&quot;</span><span style="color: #000066; font-weight: bold;">;</span></div></td></tr></tbody></table></div>
<p>If you assign an empty string or <em>null</em>, no badge will be displayed. To remove the current badge label you can also call the method <em>clearLabel()</em>.</p>
<p>By default the biggest icon defined within the <a href="http://livedocs.adobe.com/flex/3/html/help.html?content=File_formats_1.html" target="_blank">application descriptor</a> will be loaded and shown. If no icon has been defined or the path is incorrect you must assign a <em>customIcon</em> in order to see the label. You can also assign a <em>customIcon</em> if you want to replace the default icon temporarily. Removing the <em>customIcon</em> will show up the default icon again.</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">AirIconBadge<span style="color: #000066; font-weight: bold;">.</span>customIcon = <span style="color: #0033ff; font-weight: bold;">new</span> CustomIconBitmap<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span></div></td></tr></tbody></table></div>
<p>If neither of the icons could be loaded, no badge will be displayed. In this case an error event will be dispatched (<em>UpdateErrorEvent</em>). To get status information about the internals you can register for the InformationEvent. Both events will be dispatched by the <em>IconBadge</em> witch is statically stored within the AirIconBadge.</p>
<div class="codecolorer-container actionscript3 dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="actionscript3 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #6699cc; font-weight: bold;">var</span> iconBadge <span style="color: #000066; font-weight: bold;">:</span> IconBadge = AirIconBadge<span style="color: #000066; font-weight: bold;">.</span>iconBadge<span style="color: #000066; font-weight: bold;">;</span><br />
iconBadge<span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">addEventListener</span><span style="color: #000000;">&#40;</span>UpdateErrorEvent<span style="color: #000066; font-weight: bold;">.</span>UPDATE_ERROR<span style="color: #000066; font-weight: bold;">,</span><br />
handleError<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
iconBadge<span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">addEventListener</span><span style="color: #000000;">&#40;</span>InformationEvent<span style="color: #000066; font-weight: bold;">.</span>INFORMATION<span style="color: #000066; font-weight: bold;">,</span><br />
handleInformation<span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<br />
<span style="color: #339966; font-weight: bold;">function</span> handleError<span style="color: #000000;">&#40;</span>event <span style="color: #000066; font-weight: bold;">:</span> UpdateErrorEvent<span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> <span style="color: #0033ff; font-weight: bold;">void</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #009900; font-style: italic;">// do some error handling</span><br />
<span style="color: #000000;">&#125;</span><br />
<br />
<span style="color: #339966; font-weight: bold;">function</span> handleInformation<span style="color: #000000;">&#40;</span>event <span style="color: #000066; font-weight: bold;">:</span> InformationEvent<span style="color: #000000;">&#41;</span> <span style="color: #000066; font-weight: bold;">:</span> <span style="color: #0033ff; font-weight: bold;">void</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #004993;">trace</span><span style="color: #000000;">&#40;</span>event<span style="color: #000066; font-weight: bold;">.</span>information<span style="color: #000066; font-weight: bold;">.</span><span style="color: #004993;">toString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000066; font-weight: bold;">;</span><br />
<span style="color: #000000;">&#125;</span></div></td></tr></tbody></table></div>
<h3>Download</h3>
<p>All sources, binaries and examples are <a href="http://code.google.com/p/air-icon-badge/downloads/list" target="_blank">available for download</a> under the MIT license.</p>
<h3>Whats next</h3>
<p>The documentation (especially the ASDocs) will be improved as well as the sources. If you have questions or feature requests, please let my know. The next blog posts will give you a deeper insight in the architecture and extensibility of this library.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattes-groeger.de/libraries/icon-badge-library-for-air/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

