<?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>Christophe Coenraets</title>
	<atom:link href="http://coenraets.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://coenraets.org/blog</link>
	<description>Rich Internet Applications, Flex, AIR, Java</description>
	<lastBuildDate>Tue, 02 Feb 2010 15:29:08 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>FlexStore Revisited: Building an Animated Spark Layout</title>
		<link>http://coenraets.org/blog/2010/02/flexstore-revisited-building-an-animated-spark-layout/</link>
		<comments>http://coenraets.org/blog/2010/02/flexstore-revisited-building-an-animated-spark-layout/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 15:29:08 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=460</guid>
		<description><![CDATA[Six years ago, I wrote the FlexStore sample application for Flex 1.0 (code name Royale at the time). The original version is still running here and shows the progress we have made in six years! Two years later, I rewrote the application for Flex 2. One major difference in the Flex 2 version was that [...]]]></description>
			<content:encoded><![CDATA[<p>Six years ago, I wrote the FlexStore sample application for Flex 1.0 (code name Royale at the time). The original version is still running <a href="http://examples.adobe.com/flex3app/flex15/flexstore/flexstore.mxml">here</a> and shows the progress we have made in six years! Two years later, I rewrote the application for Flex 2. One major difference in the <a href="http://examples.adobe.com/flex2/inproduct/sdk/flexstore/flexstore.html">Flex 2 version</a> was that the product Tile List was animated to visually represent the items being filtered out or filtered back in. The animations were helpful, but I was never too happy with the code: the layout animation logic was tightly coupled to the container logic and therefore wasn&#8217;t very reusable.</p>
<p>In Flex 4, the new Spark component architecture cleanly separates containers from their layouts: You declare a container and plug a layout into it. You can use existing Layout classes (VerticalLayout, HorizontalLayout, TileLayout,  LayoutBase), or create your own custom layout classes. So, I thought it would be nice to revisit the AnimatedList component I had written for the FlexStore 2 and take advantage of this new architecture. I created a custom layout class called &#8220;FilteredTileLayout&#8221; that you can plug in Flex 4 list classes. i.e. List or DataGroup.</p>
<p><span id="more-460"></span></p>
<pre class="brush: xml;">
&lt;s:DataGroup dataProvider=&quot;{items}&quot; itemRenderer=&quot;renderers.PhoneRenderer&quot; top=&quot;50&quot; left=&quot;0&quot; right=&quot;0&quot; horizontalCenter=&quot;0&quot;&gt;
	&lt;s:layout&gt;
		&lt;layouts:FilteredTileLayout id=&quot;filterLayout&quot; filteredItems=&quot;{filteredItems}&quot; /&gt;
	&lt;/s:layout&gt;
&lt;/s:DataGroup&gt;
</pre>
<p>The application also provides a simple example of the new two-way data binding feature in Flex 4:</p>
<pre class="brush: xml;">
&lt;s:HSlider id=&quot;priceSlider&quot; minimum=&quot;0&quot; maximum=&quot;1000&quot; snapInterval=&quot;100&quot; value=&quot;@{_maxPrice}&quot; change=&quot;selectionChange()&quot;/&gt;
&lt;s:CheckBox label=&quot;Camera&quot; selected=&quot;@{_camera}&quot; change=&quot;selectionChange()&quot;/&gt;
&lt;s:CheckBox label=&quot;Video&quot; selected=&quot;@{_video}&quot; change=&quot;selectionChange()&quot;/&gt;
&lt;s:CheckBox label=&quot;Triband&quot; selected=&quot;@{_triband}&quot; change=&quot;selectionChange()&quot;/&gt;
</pre>
<p>Here is the running application. The phones are old, but the code is fresh.</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="app3" width="500" height="600" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/samples/flexstore4/flexstore4.swf" /><param name="base" value="." /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/samples/flexstore4/flexstore4.swf" quality="high" bgcolor="#ffffff" width="500" height="600" name="app3" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" base="." type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<h2>More Information</h2>
<p>You can view the complete source code for the application <a href="/samples/flexstore4/srcview/index.html">here</a>.</p>
<p>You can download the source code <a href="/samples/flexstore4/srcview/flexstore4.zip">here</a>.</p>
<p>For more information on Spark layouts, read <a href="http://evtimmy.com/">Evtim Georgiev</a> article on Devnet:<br/> <a href="http://www.adobe.com/devnet/flex/articles/spark_layouts.html">Spark layouts with Flex 4 beta</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2010/02/flexstore-revisited-building-an-animated-spark-layout/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>More Flex 4 / Spark ItemRenderer Samples</title>
		<link>http://coenraets.org/blog/2010/02/more-flex-4-spark-itemrenderer-samples/</link>
		<comments>http://coenraets.org/blog/2010/02/more-flex-4-spark-itemrenderer-samples/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 03:24:18 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=439</guid>
		<description><![CDATA[Here are a few additional examples of Flex 4 / Spark ItemRenderers. They are similar to the examples I provided in my previous post with a different set of items.

Here is a first example using the new &#8220;depth&#8221; attribute, the new States syntax and a PostLayoutTransform:

A second example showing a different approach to &#8220;zoom&#8221; the [...]]]></description>
			<content:encoded><![CDATA[<p>Here are a few additional examples of Flex 4 / Spark ItemRenderers. They are similar to the examples I provided in my <a href="http://coenraets.org/blog/2010/01/cool-itemrenderers-made-easy-in-flex-4/">previous post</a> with a different set of items.</p>
<p><span id="more-439"></span></p>
<p>Here is a first example using the new &#8220;depth&#8221; attribute, the new States syntax and a PostLayoutTransform:</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="app1" width="600" height="320" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/samples/itemrenderers2/flexstore1.swf" /><param name="base" value="." /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/samples/itemrenderers2/flexstore1.swf" quality="high" bgcolor="#ffffff" width="600" height="320" name="app1" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" base="." type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>A second example showing a different approach to &#8220;zoom&#8221; the hovered ItemRenderer:</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="app2" width="600" height="420" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/samples/itemrenderers2/flexstore2.swf" /><param name="base" value="." /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/samples/itemrenderers2/flexstore2.swf" quality="high" bgcolor="#ffffff" width="600" height="420" name="app2" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" base="." type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>A third showing a Rotate3D effect:</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="app3" width="600" height="520" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/samples/itemrenderers2/flexstore3.swf" /><param name="base" value="." /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/samples/itemrenderers2/flexstore3.swf" quality="high" bgcolor="#ffffff" width="600" height="520" name="app3" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" base="." type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>You can view the complete source code for the application <a href="/samples/itemrenderers2/srcview/index.html">here</a>.</p>
<p>You can download the source code <a href="/samples/itemrenderers2/srcview/flexstore.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2010/02/more-flex-4-spark-itemrenderer-samples/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cool ItemRenderers Made Easy in Flex 4</title>
		<link>http://coenraets.org/blog/2010/01/cool-itemrenderers-made-easy-in-flex-4/</link>
		<comments>http://coenraets.org/blog/2010/01/cool-itemrenderers-made-easy-in-flex-4/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 15:37:52 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=420</guid>
		<description><![CDATA[Flex 4 makes a lot of things a lot easier to build. After looking at custom components and skins in my previous post, here are a couple of samples focusing on ItemRenderers, States, and Animations.
In this first example, I use the new &#8220;depth&#8221; attribute together with the new States syntax to make sure that the [...]]]></description>
			<content:encoded><![CDATA[<p>Flex 4 makes a lot of things a lot easier to build. After looking at custom components and skins in <a href="http://coenraets.org/blog/2010/01/creating-a-custom-component-and-skins-in-flex-4/">my previous post</a>, here are a couple of samples focusing on ItemRenderers, States, and Animations.</p>
<p>In this first example, I use the new &#8220;depth&#8221; attribute together with the new States syntax to make sure that the hovered ItemRenderer is always on top of the other ones. I also use a PostLayoutTransform to &#8220;zoom&#8221; the hovered ItemRenderer without any impact on the position of the other ItemRenderers in this TileLayout.</p>
<p><span id="more-420"></span><br />
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="app1" width="600" height="320" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/samples/itemrenderers/office1.swf" /><param name="base" value="." /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/samples/itemrenderers/office1.swf" quality="high" bgcolor="#ffffff" width="600" height="320" name="app1" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" base="." type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>Here is the source code for the ItemRenderer.</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:ItemRenderer xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
				xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
				xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;
				autoDrawBackground=&quot;false&quot;
				depth=&quot;0&quot; depth.hovered=&quot;1&quot;&gt;

	&lt;s:states&gt;
		&lt;s:State name=&quot;normal&quot; /&gt;
		&lt;s:State name=&quot;hovered&quot; /&gt;
	&lt;/s:states&gt;

	&lt;s:postLayoutTransformOffsets&gt;
		&lt;mx:TransformOffsets id=&quot;offsets&quot; x.hovered=&quot;-40&quot; y.hovered=&quot;-40&quot; scaleX.hovered=&quot;2&quot; scaleY.hovered=&quot;2&quot; /&gt;
	&lt;/s:postLayoutTransformOffsets&gt;	

	&lt;s:transitions&gt;
		&lt;mx:Transition fromState=&quot;normal&quot; toState=&quot;hovered&quot; autoReverse=&quot;true&quot;&gt;
			&lt;s:Animate target=&quot;{offsets}&quot; duration=&quot;200&quot;&gt;
				&lt;s:SimpleMotionPath property=&quot;scaleX&quot; /&gt;
				&lt;s:SimpleMotionPath property=&quot;scaleY&quot; /&gt;
				&lt;s:SimpleMotionPath property=&quot;x&quot; /&gt;
				&lt;s:SimpleMotionPath property=&quot;y&quot; /&gt;
			&lt;/s:Animate&gt;
		&lt;/mx:Transition&gt;
		&lt;mx:Transition fromState=&quot;hovered&quot; toState=&quot;normal&quot; autoReverse=&quot;true&quot;&gt;
			&lt;s:Animate target=&quot;{offsets}&quot; duration=&quot;200&quot;&gt;
				&lt;s:SimpleMotionPath property=&quot;scaleX&quot; /&gt;
				&lt;s:SimpleMotionPath property=&quot;scaleY&quot; /&gt;
				&lt;s:SimpleMotionPath property=&quot;x&quot; /&gt;
				&lt;s:SimpleMotionPath property=&quot;y&quot; /&gt;
			&lt;/s:Animate&gt;
		&lt;/mx:Transition&gt;
	&lt;/s:transitions&gt;	

	&lt;mx:Image id=&quot;image&quot; source=&quot;{data.image}&quot; width=&quot;80&quot; height=&quot;80&quot; horizontalCenter=&quot;0&quot; verticalCenter=&quot;0&quot;/&gt;

&lt;/s:ItemRenderer&gt;
</pre>
<p>In this second example, the ItemRenderer uses a simple Rotate3D effect.</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="app2" width="600" height="320" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/samples/itemrenderers/office2.swf" /><param name="base" value="." /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/samples/itemrenderers/office2.swf" quality="high" bgcolor="#ffffff" width="600" height="320" name="app2" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" base="." type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>Here is the source code for the ItemRenderer.</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:ItemRenderer xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
				xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
				xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;
				autoDrawBackground=&quot;false&quot;
				depth=&quot;0&quot; depth.hovered=&quot;1&quot;&gt;

	&lt;s:states&gt;
		&lt;s:State name=&quot;normal&quot; /&gt;
		&lt;s:State name=&quot;hovered&quot; /&gt;
	&lt;/s:states&gt;

	&lt;s:transitions&gt;
		&lt;s:Transition fromState=&quot;normal&quot; toState=&quot;hovered&quot; autoReverse=&quot;true&quot;&gt;
			&lt;s:Parallel&gt;
				&lt;s:Rotate3D target=&quot;{image}&quot; angleYFrom=&quot;0&quot; angleYTo=&quot;360&quot; autoCenterProjection=&quot;true&quot; autoCenterTransform=&quot;true&quot; duration=&quot;400&quot;/&gt;
				&lt;s:Fade target=&quot;{image}&quot; startDelay=&quot;400&quot; duration=&quot;200&quot;/&gt;
				&lt;s:Fade target=&quot;{group}&quot; startDelay=&quot;400&quot; duration=&quot;200&quot;/&gt;
			&lt;/s:Parallel&gt;
		&lt;/s:Transition&gt;
	&lt;/s:transitions&gt;

	&lt;s:Rect id=&quot;rect&quot; left=&quot;0&quot; right=&quot;0&quot; top=&quot;0&quot; bottom=&quot;0&quot;&gt;
		&lt;s:fill&gt;
			&lt;s:SolidColor color=&quot;black&quot; alpha=&quot;0.7&quot;/&gt;
		&lt;/s:fill&gt;
	&lt;/s:Rect&gt;

	&lt;s:Group id=&quot;group&quot; left=&quot;0&quot; right=&quot;0&quot; top=&quot;0&quot; bottom=&quot;0&quot; visible.normal=&quot;false&quot;&gt;
		&lt;s:Label text=&quot;{data.firstName}&quot; verticalCenter=&quot;-10&quot; horizontalCenter=&quot;0&quot; color=&quot;white&quot;/&gt;
		&lt;s:Label text=&quot;{data.lastName}&quot; verticalCenter=&quot;10&quot; horizontalCenter=&quot;0&quot; color=&quot;white&quot;/&gt;
	&lt;/s:Group&gt;

	&lt;mx:Image id=&quot;image&quot; source=&quot;{data.image}&quot; width=&quot;80&quot; height=&quot;80&quot; horizontalCenter=&quot;0&quot; verticalCenter=&quot;0&quot; visible.hovered=&quot;false&quot;/&gt;

&lt;/s:ItemRenderer&gt;
</pre>
<p>You can view the complete source code for the application <a href="/samples/itemrenderers/srcview/index.html">here</a>.</p>
<p>You can download the source code <a href="/samples/itemrenderers/srcview/office.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2010/01/cool-itemrenderers-made-easy-in-flex-4/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating a Custom Component and Skins in Flex 4</title>
		<link>http://coenraets.org/blog/2010/01/creating-a-custom-component-and-skins-in-flex-4/</link>
		<comments>http://coenraets.org/blog/2010/01/creating-a-custom-component-and-skins-in-flex-4/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 18:46:30 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=355</guid>
		<description><![CDATA[The basic idea behind the Spark component model in Flex 4 is to entirely decouple the behavior of a component from its visual representation. You code the behavior of a component in one class and its visual representation in interchangeable MXML skin classes. This new architecture leads to lighter weight and easier to customize components.
As [...]]]></description>
			<content:encoded><![CDATA[<p>The basic idea behind the Spark component model in Flex 4 is to entirely decouple the behavior of a component from its visual representation. You code the behavior of a component in one class and its visual representation in interchangeable MXML skin classes. This new architecture leads to lighter weight and easier to customize components.</p>
<p>As a simple example, I created a Spark version of the PhotoInput component I built for some of my Flex 3 samples (<a href="http://coenraets.org/blog/2009/03/make-and-receive-phone-calls-in-the-new-version-of-the-salesbuilder-sample-flex-application/">Salesbuilder</a> and <a href="http://coenraets.org/blog/2009/07/building-a-flex-application-with-the-parsley-framework/">inSync</a>). The PhotoInput component allows the user to take pictures using the webcam.</p>
<p><span id="more-355"></span></p>
<p>Here is the PhotoInput component with a minimalistic skin. Click the Start Camera button to start your webcam, and the Take Picture button to take a picture.</p>
<p><pre class="brush: xml;">
&lt;components:PhotoInput skinClass=&quot;skins.PhotoInputSkin&quot; width=&quot;200&quot;/&gt;
</pre>
</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="app1" width="300" height="480" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/samples/PhotoInput/PhotoInputDemo.swf" /><param name="base" value="." /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/samples/PhotoInput/PhotoInputDemo.swf" quality="high" bgcolor="#ffffff" width="300" height="480" name="app1" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" base="." type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>&#8230; and here is the same PhotoInput component with a different skin. Click the small webcam icon in the upper left of the component to start the webcam.</p>
<p><pre class="brush: xml;">
&lt;components:PhotoInput skinClass=&quot;skins.PhotoInputSkin2&quot; width=&quot;200&quot;/&gt;
</pre>
</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="app1" width="250" height="250" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/samples/PhotoInput/PhotoInputDemo2.swf" /><param name="base" value="." /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/samples/PhotoInput/PhotoInputDemo2.swf" quality="high" bgcolor="#ffffff" width="250" height="250" name="app1" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" base="." type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>As you can see in the main application class, this is the same PhotoInput component used with two different skins: PhotoInputSkin and PhotoInputSkin2.
<p>PhotoInputSkin.mxml is defined as follows:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:Skin xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
		xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
		xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;&gt;

	&lt;!-- host component --&gt;
	&lt;fx:Metadata&gt;
		[HostComponent(&quot;components.PhotoInput&quot;)]
	&lt;/fx:Metadata&gt;

	&lt;s:states&gt;
		&lt;s:State name=&quot;capturing&quot;/&gt;
		&lt;s:State name=&quot;normal&quot;/&gt;
	&lt;/s:states&gt;

	&lt;s:layout&gt;
		&lt;s:VerticalLayout/&gt;
	&lt;/s:layout&gt;

	&lt;mx:VideoDisplay id=&quot;videoDisplay&quot; width=&quot;{hostComponent.width}&quot; height=&quot;{hostComponent.width}&quot;/&gt;

	&lt;s:BitmapImage id=&quot;image&quot; width=&quot;{hostComponent.width}&quot; height=&quot;{hostComponent.width}&quot;/&gt;

	&lt;s:Button id=&quot;startCameraButton&quot; label=&quot;Start Camera&quot; width=&quot;100%&quot; includeIn=&quot;normal&quot;/&gt;
	&lt;s:Button id=&quot;stopCameraButton&quot; label=&quot;Stop Camera&quot; width=&quot;100%&quot; includeIn=&quot;capturing&quot;/&gt;
	&lt;s:Button id=&quot;takePictureButton&quot; label=&quot;Take Picture&quot; width=&quot;100%&quot; includeIn=&quot;capturing&quot;/&gt;

&lt;/s:Skin&gt;
</pre>
<p>&#8230; and PhotoInputSkin2.mxml is defined as follows:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:Skin xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
		xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
		xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;&gt;

	&lt;fx:Script&gt;
		&lt;![CDATA[

			private function takePicture():void
			{
				// Show the picture that was just taken for 2 seconds,
				// then show the webcam capture again
				image.visible = true;
				var myTimer:Timer = new Timer(2000, 1);
				myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
				myTimer.start();
			}

			private function timerHandler(event:TimerEvent):void
			{
				if (currentState == &quot;capturing&quot;) image.visible = false;
			}

		]]&gt;
	&lt;/fx:Script&gt;

	&lt;fx:Declarations&gt;
		&lt;mx:SoundEffect id=&quot;soundEffect&quot; source=&quot;@Embed(source='assets/camera_click.mp3')&quot; useDuration=&quot;false&quot; /&gt;
	&lt;/fx:Declarations&gt;

	&lt;s:states&gt;
		&lt;s:State name=&quot;capturing&quot;/&gt;
		&lt;s:State name=&quot;normal&quot;/&gt;
	&lt;/s:states&gt;

	&lt;!-- host component --&gt;
	&lt;fx:Metadata&gt;
		[HostComponent(&quot;components.PhotoInput&quot;)]
	&lt;/fx:Metadata&gt;

	&lt;s:layout&gt;
		&lt;s:BasicLayout/&gt;
	&lt;/s:layout&gt;

	&lt;s:Rect radiusX=&quot;8&quot; radiusY=&quot;8&quot; top=&quot;0&quot; bottom=&quot;0&quot; left=&quot;0&quot; right=&quot;0&quot;&gt;
		&lt;s:fill&gt;
			&lt;s:LinearGradient rotation=&quot;90&quot;&gt;
				&lt;s:GradientEntry color=&quot;0x606060&quot; alpha=&quot;1&quot; ratio=&quot;0&quot; /&gt;
				&lt;s:GradientEntry color=&quot;0x303030&quot; alpha=&quot;.8&quot; ratio=&quot;1&quot; /&gt;
			&lt;/s:LinearGradient&gt;
		&lt;/s:fill&gt;
	&lt;/s:Rect&gt;

	&lt;s:Group  top=&quot;4&quot; bottom=&quot;4&quot; left=&quot;4&quot; right=&quot;4&quot;&gt;

		&lt;s:layout&gt;
			&lt;s:BasicLayout/&gt;
		&lt;/s:layout&gt;

		&lt;mx:VideoDisplay id=&quot;videoDisplay&quot; width=&quot;{hostComponent.width - 8}&quot; height=&quot;{hostComponent.width}&quot; includeIn=&quot;capturing&quot;/&gt;

		&lt;s:BitmapImage id=&quot;image&quot; width=&quot;{hostComponent.width - 8}&quot; height=&quot;{hostComponent.width}&quot;
					   source=&quot;@Embed('assets/male_user_gray.png')&quot; visible.capturing=&quot;false&quot;/&gt;

		&lt;s:Button id=&quot;startCameraButton&quot; skinClass=&quot;skins.StartWebCamButtonSkin&quot; toolTip=&quot;Start Camera&quot;/&gt;
		&lt;s:Button id=&quot;stopCameraButton&quot; skinClass=&quot;skins.StopWebCamButtonSkin&quot; includeIn=&quot;capturing&quot; toolTip=&quot;Stop Camera&quot;/&gt;
		&lt;s:Button id=&quot;takePictureButton&quot; skinClass=&quot;skins.TakePictureButtonSkin&quot; label=&quot;Take Picture&quot; width=&quot;100%&quot; bottom=&quot;0&quot; includeIn=&quot;capturing&quot;
				  toolTip=&quot;Take Picture&quot;
				  mouseDownEffect=&quot;{soundEffect}&quot;
				  click=&quot;takePicture()&quot;/&gt;

	&lt;/s:Group&gt;

&lt;/s:Skin&gt;
</pre>
<p>The PhotoInput class provides the basic behavior of the component (start and stop the camera, take the picture, etc.) and is defined as follows:</p>
<pre class="brush: jscript;">
package components
{
	import flash.display.BitmapData;
	import flash.events.MouseEvent;
	import flash.media.Camera;

	import mx.controls.VideoDisplay;
	import mx.graphics.ImageSnapshot;

	import spark.components.Button;
	import spark.components.supportClasses.SkinnableComponent;
	import spark.primitives.BitmapImage;

	[SkinState(&quot;capturing&quot;)]
	public class PhotoInput extends SkinnableComponent
	{
		private var camera:Camera;

		private var isCameraOn:Boolean = false;

		[SkinPart(required=&quot;true&quot;)]
		public var videoDisplay:VideoDisplay;

		[SkinPart(required=&quot;true&quot;)]
		public var image:BitmapImage;

		[SkinPart(required=&quot;false&quot;)]
		public var takePictureButton:Button;

		[SkinPart(required=&quot;false&quot;)]
		public var startCameraButton:Button;

		[SkinPart(required=&quot;false&quot;)]
		public var stopCameraButton:Button;

		public function PhotoInput()
		{
			super();
		}

		override protected function partAdded(partName:String, instance:Object):void
		{
			super.partAdded(partName, instance);

			if (instance == startCameraButton)
			{
				startCameraButton.addEventListener(MouseEvent.CLICK, startCameraButton_click);
			}
			if (instance == stopCameraButton)
			{
				stopCameraButton.addEventListener(MouseEvent.CLICK, stopCameraButton_click);
			}
			if (instance == takePictureButton)
			{
				takePictureButton.addEventListener(MouseEvent.CLICK, takePictureButton_click);
			}
		}

		override protected function partRemoved(partName:String, instance:Object):void
		{
			super.partRemoved(partName, instance);

			if (instance == startCameraButton)
			{
				startCameraButton.removeEventListener(MouseEvent.CLICK, startCameraButton_click);
			}
			if (instance == stopCameraButton)
			{
				stopCameraButton.removeEventListener(MouseEvent.CLICK, stopCameraButton_click);
			}
			if (instance == takePictureButton)
			{
				takePictureButton.removeEventListener(MouseEvent.CLICK, takePictureButton_click);
			}
		}		

		override protected function getCurrentSkinState():String
		{
			if (isCameraOn)
			{
				return &quot;capturing&quot;;
			}

			return &quot;normal&quot;;
		}

		private function startCamera():void
		{
			isCameraOn = true;
			invalidateSkinState();
			callLater(attachCamera);
		}

		private function attachCamera():void
		{
			camera = Camera.getCamera();
			videoDisplay.attachCamera(camera);
		}

		private function stopCamera():void
		{
			isCameraOn = false;
			invalidateSkinState();
			videoDisplay.attachCamera(null);
		}

		private function takePicture():void
		{
			var bd:BitmapData = ImageSnapshot.captureBitmapData(videoDisplay);
			image.source = bd;
		}		

		private function startCameraButton_click(event:MouseEvent):void
		{
			startCamera();
		}

		private function stopCameraButton_click(event:MouseEvent):void
		{
			stopCamera();
		}

		private function takePictureButton_click(event:MouseEvent):void
		{
			takePicture();
		}

	}
}
</pre>
<h2>Source Code</h2>
<p>You can download the source code of the application <a href="http://coenraets.org/samples/PhotoInput/PhotoInputDemo.zip">here</a>.</p>
<h2>More Information</h2>
<p>To learn more about skins, make sure you read <a href="http://www.adobe.com/devnet/flex/articles/flex4_skinning.html">Ryan Frishberg&#8217;s great article</a> on DevNet.</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2010/01/creating-a-custom-component-and-skins-in-flex-4/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Tampa Bay Adobe Developer Event this Thursday</title>
		<link>http://coenraets.org/blog/2010/01/tampa-bay-adobe-developer-event-this-thursday/</link>
		<comments>http://coenraets.org/blog/2010/01/tampa-bay-adobe-developer-event-this-thursday/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 22:50:59 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=344</guid>
		<description><![CDATA[I&#8217;ll be in Tampa with James Ward and Greg Wilson this week, and we thought it would be great to put together an informal event for the local Tampa bay developer community. The details below are from Greg&#8217;s original post.
When:  Thursday, Jan 21 6:30pm-8:30pm
Location:  Taverna Opa Tampa – Channelside – next to Splitsville [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be in Tampa with <a href="http://jamesward.com">James Ward</a> and <a href="http://gregsramblings.com">Greg Wilson</a> this week, and we thought it would be great to put together an informal event for the local Tampa bay developer community. The details below are from <a href=" http://gregsramblings.com/2010/01/18/tampa-bay-adobe-developer-event-this-thursday/">Greg&#8217;s original post</a>.</p>
<p>When:  Thursday, Jan 21 6:30pm-8:30pm<br />
Location:  Taverna Opa Tampa – Channelside – next to Splitsville – http://tavernaopatampa.com/info.html<br />
Map: http://bit.ly/5kF4aR (Google Maps)</p>
<p>No slides and no presentations – just informal chat/Q&#038;A</p>
<p>IMPORTANT PART –> Beer is on James, Christophe and me for the first hour!  How can you resist now?!</p>
<p>Between the 3 of us and some of our local friends, we can answer questions on a wide variety of topics:</p>
<ul>
<li>General questions about Flex, AIR, LiveCycle Data Services, BlazeDS, ColdFusion and more</li>
<li>Connecting applications built on the flash platform (Flex, AIR, etc.) to backend systems such as .NET, Java, PHP, ColdFusion, etc.</li>
<li>What’s new in LiveCycle data services 3.0</li>
<li>What’s new in ColdFusion 9 and ColdFusion Builder</li>
<li>What’s coming in Flex 4, AIR 2.0 and Flash Player 10.1</li>
<li>Everything you wanted to know about Augmented Reality</li>
<li>How to compute the volume of a cone and other mathematical puzzles (just making sure you are still reading)</li>
<li>What’s the deal with the announcement last October about Flash and iPhone?</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2010/01/tampa-bay-adobe-developer-event-this-thursday/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>AIR 2.0 Web Server using the New Server Socket API</title>
		<link>http://coenraets.org/blog/2009/12/air-2-0-web-server-using-the-new-server-socket-api/</link>
		<comments>http://coenraets.org/blog/2009/12/air-2-0-web-server-using-the-new-server-socket-api/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 19:46:21 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=309</guid>
		<description><![CDATA[After exploring Java integration using the new Native Process API (here and here), Excel integration using the new file.openWithDefaultApplication(), and the new Microphone API, here is another application I wrote, this time to explore the new Adobe AIR 2.0 Server Socket API.
The &#8220;Mini AIR Web Server&#8221; is a simplistic implementation of an HTTPServer. Needless to [...]]]></description>
			<content:encoded><![CDATA[<p>After exploring Java integration using the new Native Process API (<a href="http://coenraets.org/blog/2009/12/tomcat-launcher-sample-application-using-the-air-2-0-native-process-api/">here</a> and <a href="http://coenraets.org/blog/2009/12/embedding-tomcat-and-blazeds-in-an-air-2-0-application/">here</a>), <a href="http://coenraets.org/blog/2009/11/open-in-excel-another-air-2-mini-sample/">Excel integration</a> using the new file.openWithDefaultApplication(), and the new <a href="http://coenraets.org/blog/2009/11/voice-notes-record-voice-notes-and-persist-them-in-sqlite-with-air-2/">Microphone API</a>, here is another application I wrote, this time to explore the new Adobe AIR 2.0 Server Socket API.</p>
<p>The &#8220;Mini AIR Web Server&#8221; is a simplistic implementation of an HTTPServer. Needless to say that it is far from being a production quality Web Server. The goal here is simply to use the well understood mechanics of a web server to learn how to use server sockets in AIR 2.0.</p>
<h3>Installation Instructions</h3>
<ol>
<li>Download the AIR 2.0 beta runtime <a href="http://labs.adobe.com/downloads/air2.html">here</a>.</li>
<li>Download MiniAIRWebServer.air <a href="http://coenraets.org/apps/MiniAIRWebServer/MiniAIRWebServer.air">here</a>.</li>
<li>Double-click MiniAIRWebServer.air in Explorer or Finder to start the installation process.</li>
</ol>
<p>To test the application, open a browser and test the sample HTML pages provided with the application: </p>
<ul>
<li><a href="http://localhost:8888/test1.html">http://localhost:8888/test1.html</a></li>
<li><a href="http://localhost:8888/test2.html">http://localhost:8888/test2.html</a></li>
<li><a href="http://localhost:8888/test3.html">http://localhost:8888/test3.html</a></li>
</ul>
<p><strong>NOTE:</strong> You may have to change the port number in these URLs depending on the port number you enter in the application.</p>
<p><span id="more-309"></span></p>
<p>You can add your own content in the webroot folder in the applicationStorageDirectory.</p>
<p>View Source is enabled, but if you just want to take a quick peak at the code, here is MiniAIRWebServer.mxml:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!-- Author: Christophe Coenraets http://coenraets.org --&gt;
&lt;s:WindowedApplication xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
					   xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
					   xmlns:mx=&quot;library://ns.adobe.com/flex/halo&quot;
					   title=&quot;Mini AIR Web Server&quot;
					   applicationComplete=&quot;init()&quot; viewSourceURL=&quot;srcview/index.html&quot;&gt;
	&lt;s:layout&gt;
		&lt;s:VerticalLayout paddingTop=&quot;8&quot; paddingLeft=&quot;8&quot; paddingRight=&quot;8&quot; paddingBottom=&quot;8&quot;/&gt;
	&lt;/s:layout&gt;

	&lt;fx:Script&gt;
		&lt;![CDATA[
			import flash.events.Event;
			import flash.events.ProgressEvent;
			import flash.events.ServerSocketConnectEvent;
			import flash.net.ServerSocket;
			import flash.net.Socket;
			import flash.utils.ByteArray;
			import mx.controls.Alert;

			private var serverSocket:ServerSocket;

			private var mimeTypes:Object = new Object();

			private function init():void
			{
				// The mime types supported by this mini web server
				mimeTypes[&quot;.css&quot;] 	= &quot;text/css&quot;;
				mimeTypes[&quot;.gif&quot;] 	= &quot;image/gif&quot;;
				mimeTypes[&quot;.htm&quot;] 	= &quot;text/html&quot;;
				mimeTypes[&quot;.html&quot;] 	= &quot;text/html&quot;;
				mimeTypes[&quot;.ico&quot;] 	= &quot;image/x-icon&quot;;
				mimeTypes[&quot;.jpg&quot;] 	= &quot;image/jpeg&quot;;
				mimeTypes[&quot;.js&quot;] 	= &quot;application/x-javascript&quot;;
				mimeTypes[&quot;.png&quot;] 	= &quot;image/png&quot;;

				// Initialize the web server directory (in applicationStorageDirectory) with sample files
				var webroot:File = File.applicationStorageDirectory.resolvePath(&quot;webroot&quot;);
				if (!webroot.exists)
				{
					File.applicationDirectory.resolvePath(&quot;webroot&quot;).copyTo(webroot);
				}
			}

			private function listen():void
			{
				try
				{
					serverSocket = new ServerSocket();
					serverSocket.addEventListener(Event.CONNECT, socketConnectHandler);
					serverSocket.bind(Number(port.text));
					serverSocket.listen();
					log.text += &quot;Listening on port &quot; + port.text + &quot;...\n&quot;;
				}
				catch (error:Error)
				{
					Alert.show(&quot;Port &quot; + port.text +
						&quot; may be in use. Enter another port number and try again.\n(&quot; +
						error.message +&quot;)&quot;, &quot;Error&quot;);
				}
			}

			private function socketConnectHandler(event:ServerSocketConnectEvent):void
			{
				var socket:Socket = event.socket;
				socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
			}

			private function socketDataHandler(event:ProgressEvent):void
			{
				try
				{
					var socket:Socket = event.target as Socket;
					var bytes:ByteArray = new ByteArray();
					socket.readBytes(bytes);
					var request:String = &quot;&quot; + bytes;
					log.text += request;
					var filePath:String = request.substring(4, request.indexOf(&quot;HTTP/&quot;) - 1);
					var file:File = File.applicationStorageDirectory.resolvePath(&quot;webroot&quot; + filePath);
					if (file.exists &amp;&amp; !file.isDirectory)
					{
						var stream:FileStream = new FileStream();
						stream.open( file, FileMode.READ );
						var content:ByteArray = new ByteArray();
						stream.readBytes(content);
						stream.close();
						socket.writeUTFBytes(&quot;HTTP/1.1 200 OK\n&quot;);
						socket.writeUTFBytes(&quot;Content-Type: &quot; + getMimeType(filePath) + &quot;\n\n&quot;);
						socket.writeBytes(content);
					}
					else
					{
						socket.writeUTFBytes(&quot;HTTP/1.1 404 Not Found\n&quot;);
						socket.writeUTFBytes(&quot;Content-Type: text/html\n\n&quot;);
						socket.writeUTFBytes(&quot;&lt;html&gt;&lt;body&gt;&lt;h2&gt;Page Not Found&lt;/h2&gt;&lt;/body&gt;&lt;/html&gt;&quot;);
					}
					socket.flush();
					socket.close();
				}
				catch (error:Error)
				{
					Alert.show(error.message, &quot;Error&quot;);
				}
			}

			private function getMimeType(path:String):String
			{
				var mimeType:String;
				var index:int = path.lastIndexOf(&quot;.&quot;);
				if (index &gt; -1)
				{
					mimeType = mimeTypes[path.substring(index)];
				}
				return mimeType == null ? &quot;text/html&quot; : mimeType; // default to text/html for unknown mime types
			}

		]]&gt;
	&lt;/fx:Script&gt;

	&lt;s:HGroup verticalAlign=&quot;middle&quot;&gt;
		&lt;s:Label text=&quot;Port:&quot;/&gt;
		&lt;s:TextInput id=&quot;port&quot; text=&quot;8888&quot; width=&quot;50&quot;/&gt;
		&lt;s:Button label=&quot;Listen&quot; click=&quot;listen()&quot;/&gt;
	&lt;/s:HGroup&gt;

	&lt;s:TextArea id=&quot;log&quot; width=&quot;100%&quot; height=&quot;100%&quot; /&gt;

&lt;/s:WindowedApplication&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/12/air-2-0-web-server-using-the-new-server-socket-api/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Embedding Tomcat and BlazeDS in an AIR 2.0 Application</title>
		<link>http://coenraets.org/blog/2009/12/embedding-tomcat-and-blazeds-in-an-air-2-0-application/</link>
		<comments>http://coenraets.org/blog/2009/12/embedding-tomcat-and-blazeds-in-an-air-2-0-application/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 19:41:58 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=291</guid>
		<description><![CDATA[In my previous post, I demonstrated how to create a simple Tomcat Launcher using the new AIR 2.0 Native Process API. The assumption in that sample was that Tomcat was already installed on your machine.
In this new sample application, I&#8217;m taking that idea a little further by embedding Tomcat as part of the native installer. [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://coenraets.org/blog/2009/12/tomcat-launcher-sample-application-using-the-air-2-0-native-process-api/">previous post</a>, I demonstrated how to create a simple Tomcat Launcher using the new AIR 2.0 Native Process API. The assumption in that sample was that Tomcat was already installed on your machine.</p>
<p>In this new sample application, I&#8217;m taking that idea a little further by embedding Tomcat as part of the native installer. The first time you run the application, Tomcat is automatically copied to your applicationStorageDirectory from where the AIR application starts it. In this sample, I still provide a simple console for the user to start and stop Tomcat manually, but in a real life application, you would probably want to start Tomcat automatically when the AIR application starts.</p>
<p><img src="http://coenraets.org/apps/AIRAppWithEmbeddedTomcat/AIRAppWithEmbeddedTomcat.png" alt="" /></p>
<p><span id="more-291"></span></p>
<p>Why would you want to embed Tomcat as part of an AIR application? First of all, I&#8217;m not saying that you should&#8230; This is just part of my exploration of new capabilities in AIR 2.0. That being said, I can think of a number of use cases where this could make sense. For example:</p>
<ul>
<li>Tighter communication with Java code using BlazeDS locally as a way to directly invoke methods on remote Java classes.</li>
<li>Provide an offline mode for an application that closely mimics the online infrastructure.</li>
</ul>
<h3>Installation Instructions</h3>
<ol>
<li>Download the AIR 2.0 beta runtime <a href="http://labs.adobe.com/downloads/air2.html">here</a>.</li>
<li>Because Tomcat Launcher uses the Native Process API, I had to create native installers:
<ul>
<li>To install the application on Windows, download and run <a href="http://coenraets.org/apps/AIRAppWithEmbeddedTomcat/AIRAppWithEmbeddedTomcat.exe">AIRAppWithEmbeddedTomcat.exe</a>.</li>
<li>To install the application on a Mac, download and run <a href="http://coenraets.org/apps/AIRAppWithEmbeddedTomcat/AIRAppWithEmbeddedTomcat.dmg">AIRAppWithEmbeddedTomcat.dmg</a>.</li>
</ul>
</li>
</ol>
<p>After starting the application, enter the path to your Java home folder, then click the Start button. The application will remember the folder you entered the next time you use the application. Try the &#8220;Embedded JSP Example&#8221; and &#8220;Embedded RemoteObject Example&#8221;. If you get a BindingException when you start Tomcat, make sure it isn&#8217;t already started. You can also click the Stop button to stop a running instance.</p>
<p>You can download the project here: <a href="http://coenraets.org/apps/AIRAppWithEmbeddedTomcat/AIRAppWithEmbeddedTomcat.fxp.zip">AIRAppWithEmbeddedTomcat.fxp.zip</a>. If you just want to take a quick peak at the code, here is AIRAppWithEmbeddedTomcat.mxml:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!--
Christophe Coenraets http://coenraets.org
--&gt;
&lt;s:WindowedApplication xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
					   xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
					   xmlns:mx=&quot;library://ns.adobe.com/flex/halo&quot;
					   title=&quot;AIR Application with Embedded Tomcat&quot;
					   height=&quot;600&quot; width=&quot;800&quot;
					   applicationComplete=&quot;init()&quot;&gt;
	&lt;s:layout&gt;
		&lt;s:VerticalLayout paddingLeft=&quot;8&quot; paddingRight=&quot;8&quot; paddingBottom=&quot;8&quot; paddingTop=&quot;8&quot;/&gt;
	&lt;/s:layout&gt;

	&lt;fx:Script&gt;
		&lt;![CDATA[
			import mx.controls.Alert;

			private var startTomcatProcess:NativeProcess;
			private var stopTomcatProcess:NativeProcess;

			private var tomcatHomeDir:File;

			public function init():void
			{
				if (!NativeProcess.isSupported)
				{
					Alert.show(&quot;NativeProcess not supported&quot;);
				}

				tomcatHomeDir = File.applicationStorageDirectory.resolvePath(&quot;tomcat&quot;);
				if (!tomcatHomeDir.exists)
				{
					var tomcatOriginalDir:File = File.applicationDirectory.resolvePath(&quot;tomcat&quot;);
					trace(&quot;Copying tomcat to appStorageDirectory...&quot;);
					tomcatOriginalDir.copyTo(tomcatHomeDir);
				}
				tomcatHome.text = tomcatHomeDir.nativePath;				

				// Read the last home used to start Tomcat (if any)
				var xml:XML = readConfig();
				if (xml != null)
				{
					javaHome.text = xml.javaHome;
					return;
				}

				// If no known last home, present default/sample values
				if (Capabilities.os.toLowerCase().indexOf(&quot;win&quot;) &gt; -1)
				{
					// default/sample values for Windows users
					javaHome.text = &quot;C:\\Program Files\\Java\\jdk1.6.0&quot;;
				}
				else if (Capabilities.os.toLowerCase().indexOf(&quot;mac&quot;) &gt; -1)
				{
					// default/sample values for Mac users
					javaHome.text = &quot;/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0&quot;;
				}

			}

			public function startTomcat():void
			{
				// Write the Java home path to config.xml so that it can be presented
				// to the user the next time the application is started
				writeConfig();

				log.text = &quot;Starting Tomcat...&quot; + File.lineEnding;
				startTomcatProcess = new NativeProcess();
				execute(startTomcatProcess, &quot;start&quot;);
			}

			public function stopTomcat():void
			{
				log.text = &quot;Stopping Tomcat...&quot; + File.lineEnding;
				stopTomcatProcess = new NativeProcess();
				execute(startTomcatProcess, &quot;stop&quot;);
			}

			public function execute(process:NativeProcess, arg:String):void
			{
				// Get a file reference to the JVM
				var file:File = new File(javaHome.text);
				if (Capabilities.os.toLowerCase().indexOf(&quot;win&quot;) &gt; -1)
				{
					file = file.resolvePath(&quot;bin/javaw.exe&quot;);
				}
				else
				{
					file = file.resolvePath(&quot;Home/bin/java&quot;);
				}

				// Start the process
				try
				{
					var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
					nativeProcessStartupInfo.executable = file;
					nativeProcessStartupInfo.workingDirectory = tomcatHomeDir.resolvePath(&quot;bin&quot;);
					var processArgs:Vector.&lt;String&gt; = new Vector.&lt;String&gt;();
					processArgs[0] = &quot;-Dcatalina.home=&quot;+tomcatHomeDir.nativePath;
					processArgs[1] = &quot;-classpath&quot;;
					processArgs[2] = tomcatHomeDir.resolvePath(&quot;bin/bootstrap.jar&quot;).nativePath;
					processArgs[3] = &quot;org.apache.catalina.startup.Bootstrap&quot;;
					processArgs[4] = arg;
					nativeProcessStartupInfo.arguments = processArgs;
					startTomcatProcess = new NativeProcess();
					startTomcatProcess.start(nativeProcessStartupInfo);
					startTomcatProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA,
						outputDataHandler);
					startTomcatProcess.addEventListener(ProgressEvent.STANDARD_ERROR_DATA,
						errorOutputDataHandler);
				}
				catch (e:Error)
				{
					Alert.show(e.message, &quot;Error&quot;);
				}
			}

			public function outputDataHandler(event:ProgressEvent):void
			{
				var process:NativeProcess = event.target as NativeProcess;
				var data:String = process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable);
				log.text += data;
			}

			public function errorOutputDataHandler(event:ProgressEvent):void
			{
				var process:NativeProcess = event.target as NativeProcess;
				var data:String = process.standardError.readUTFBytes(startTomcatProcess.standardError.bytesAvailable);
				log.text += data;
			}

			private function readConfig():XML
			{
				var file:File = File.applicationStorageDirectory.resolvePath(&quot;config.xml&quot;);
				if (file.exists)
				{
					var fileStream:FileStream = new FileStream();
					fileStream.open(file, FileMode.READ);
					var xml:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
					fileStream.close();
					return xml;
				}
				else
				{
					return null;
				}
			}

			private function writeConfig():void
			{
				var xml:String = '&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;' + File.lineEnding;
				xml += &quot;&lt;config&gt;&quot; + File.lineEnding;
				xml += &quot;&lt;javaHome&gt;&quot; + javaHome.text + &quot;&lt;/javaHome&gt;&quot; + File.lineEnding;
				xml += &quot;&lt;tomcatHome&gt;&quot; + tomcatHome.text + &quot;&lt;/tomcatHome&gt;&quot; + File.lineEnding;
				xml += &quot;&lt;/config&gt;&quot; + File.lineEnding;

				var file:File = File.applicationStorageDirectory.resolvePath(&quot;config.xml&quot;);
				var fileStream:FileStream = new FileStream();
				fileStream.open(file, FileMode.WRITE);
				fileStream.writeUTFBytes(xml);
				fileStream.close();
			}

			private function openWithDefaultEditor():void
			{
				var file:File =
					File.createTempDirectory().resolvePath(&quot;tomcat_launcher_console.txt&quot;);
				var fileStream:FileStream = new FileStream();
				fileStream.open(file, FileMode.WRITE);
				fileStream.writeUTFBytes(log.text);
				fileStream.close();
				file.openWithDefaultApplication();
			}

		]]&gt;
	&lt;/fx:Script&gt;

	&lt;fx:Declarations&gt;
		&lt;s:RemoteObject id=&quot;srv&quot; destination=&quot;contacts&quot;
						endpoint=&quot;http://localhost:8080/messagebroker/amf&quot;/&gt;
	&lt;/fx:Declarations&gt;	

	&lt;mx:TabNavigator width=&quot;100%&quot; height=&quot;100%&quot;&gt;

		&lt;mx:VBox width=&quot;100%&quot; height=&quot;100%&quot; label=&quot;Console&quot; paddingLeft=&quot;8&quot; paddingRight=&quot;8&quot; paddingBottom=&quot;8&quot;&gt;

			&lt;mx:Form width=&quot;100%&quot;&gt;
				&lt;mx:FormItem label=&quot;Java Home&quot; width=&quot;100%&quot;&gt;
					&lt;s:TextInput id=&quot;javaHome&quot; width=&quot;100%&quot;/&gt;
				&lt;/mx:FormItem&gt;
				&lt;mx:FormItem label=&quot;Embedded Tomcat Home&quot; width=&quot;100%&quot;&gt;
					&lt;s:TextInput id=&quot;tomcatHome&quot; width=&quot;100%&quot; enabled=&quot;false&quot;/&gt;
				&lt;/mx:FormItem&gt;
			&lt;/mx:Form&gt;

			&lt;s:HGroup&gt;
				&lt;s:Button label=&quot;Start&quot; click=&quot;startTomcat()&quot;/&gt;
				&lt;s:Button label=&quot;Stop&quot; click=&quot;stopTomcat()&quot;/&gt;
				&lt;s:Button label=&quot;Clear Console&quot; click=&quot;log.text=''&quot;/&gt;
				&lt;s:Button label=&quot;Open in Default Text Editor&quot;
						  click=&quot;openWithDefaultEditor()&quot;/&gt;
			&lt;/s:HGroup&gt;
			&lt;s:TextArea id=&quot;log&quot; width=&quot;100%&quot; height=&quot;100%&quot;/&gt;

		&lt;/mx:VBox&gt;

		&lt;mx:VBox label=&quot;Embedded JSP Example&quot; paddingLeft=&quot;8&quot; paddingRight=&quot;8&quot; paddingBottom=&quot;8&quot;&gt;
			&lt;mx:HTML id=&quot;html&quot; width=&quot;100%&quot; height=&quot;100%&quot;/&gt;
			&lt;s:Button label=&quot;Load JSP&quot; click=&quot;html.location='http://localhost:8080/hello.jsp'&quot;/&gt;
		&lt;/mx:VBox&gt;

		&lt;mx:VBox label=&quot;Embedded Remote Object Example&quot; paddingLeft=&quot;8&quot; paddingRight=&quot;8&quot; paddingBottom=&quot;8&quot;&gt;
			&lt;mx:DataGrid width=&quot;100%&quot; height=&quot;100%&quot; dataProvider=&quot;{srv.findAll.lastResult}&quot;&gt;
				&lt;mx:columns&gt;
					&lt;mx:DataGridColumn dataField=&quot;id&quot; headerText=&quot;Id&quot;/&gt;
					&lt;mx:DataGridColumn dataField=&quot;firstName&quot; headerText=&quot;First Name&quot;/&gt;
					&lt;mx:DataGridColumn dataField=&quot;lastName&quot; headerText=&quot;Last Name&quot;/&gt;
					&lt;mx:DataGridColumn dataField=&quot;city&quot; headerText=&quot;City&quot;/&gt;
				&lt;/mx:columns&gt;
			&lt;/mx:DataGrid&gt;
			&lt;s:Button label=&quot;Get Data&quot; click=&quot;srv.findAll()&quot;/&gt;
		&lt;/mx:VBox&gt;

	&lt;/mx:TabNavigator&gt;

&lt;/s:WindowedApplication&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/12/embedding-tomcat-and-blazeds-in-an-air-2-0-application/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Tomcat Launcher: Sample Application using the AIR 2.0 Native Process API</title>
		<link>http://coenraets.org/blog/2009/12/tomcat-launcher-sample-application-using-the-air-2-0-native-process-api/</link>
		<comments>http://coenraets.org/blog/2009/12/tomcat-launcher-sample-application-using-the-air-2-0-native-process-api/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 17:24:48 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=264</guid>
		<description><![CDATA[I have been playing with the new Native Process API of AIR 2.0, and here is a first sample application I wrote. &#8220;Tomcat Launcher&#8221; is like a mini Tomcat Console that allows you to start / stop Tomcat and view the standard output log without opening a DOS box or Terminal window. It also allows [...]]]></description>
			<content:encoded><![CDATA[<p>I have been playing with the new Native Process API of AIR 2.0, and here is a first sample application I wrote. &#8220;Tomcat Launcher&#8221; is like a mini Tomcat Console that allows you to start / stop Tomcat and view the standard output log without opening a DOS box or Terminal window. It also allows you to open that log in your default Text Editor which is another new feature of AIR 2.0 that I already explored in my &#8220;<a href="http://coenraets.org/blog/2009/11/open-in-excel-another-air-2-mini-sample/">Open in Excel</a>&#8221; sample application. Tomcat Launcher also provides a generic example showing how to use the AIR 2.0 native process API to execute Java code.</p>
<p align="center">
<img src="http://coenraets.org/apps/TomcatLauncher/TomcatLauncherMac.png" alt="" />
</p>
<p><span id="more-264"></span></p>
<p align="center">
<img src="http://coenraets.org/apps/TomcatLauncher/TomcatLauncherWin.png" alt="" />
</p>
<h3>Installation Instructions</h3>
<ol>
<li>Download the AIR 2.0 beta runtime <a href="http://labs.adobe.com/downloads/air2.html">here</a>.</li>
<li>Because Tomcat Launcher uses the Native Process API, I had to create native installers:
<ul>
<li>To install the application on Windows, download and run <a href="http://coenraets.org/apps/TomcatLauncher/TomcatLauncher.exe">TomcatLauncher.exe</a>.</li>
<li>To install the application on a Mac, download and run <a href="http://coenraets.org/apps/TomcatLauncher/TomcatLauncher.dmg">TomcatLauncher.dmg</a>.</li>
</ul>
</li>
</ol>
<p>After starting the application, enter the paths to your Java home folder and to the Tomcat installation you want to start, then click the Start button. The application will remember the folders you entered the next time you use the application. If you get a BindingException, make sure Tomcat isn&#8217;t already started. You can also click the Stop button to stop a running instance.</p>
<p>You can download the project here: <a href="http://coenraets.org/apps/TomcatLauncher/TomcatLauncher.fxp.zip">TomcatLauncher.fxp.zip</a>. If you just want to take a quick peak at the code, here is TomcatLauncher.mxml:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:WindowedApplication xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
					   xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
					   xmlns:mx=&quot;library://ns.adobe.com/flex/halo&quot;
					   title=&quot;Tomcat Launcher&quot;
					   height=&quot;700&quot; width=&quot;500&quot;
					   applicationComplete=&quot;init()&quot;&gt;
	&lt;s:layout&gt;
		&lt;s:VerticalLayout paddingLeft=&quot;8&quot; paddingRight=&quot;8&quot; paddingBottom=&quot;8&quot;/&gt;
	&lt;/s:layout&gt;

	&lt;fx:Script&gt;
		&lt;![CDATA[
			import mx.controls.Alert;

			private var startTomcatProcess:NativeProcess;
			private var stopTomcatProcess:NativeProcess;

			public function init():void
			{
				if (!NativeProcess.isSupported)
				{
					Alert.show(&quot;NativeProcess not supported&quot;);
				}

				// Read the last home used to start Tomcat (if any)
				var xml:XML = readConfig();
				if (xml != null)
				{
					javaHome.text = xml.javaHome;
					tomcatHome.text = xml.tomcatHome;
					return;
				}

				// If no known last home, present default/sample values
				if (Capabilities.os.toLowerCase().indexOf(&quot;win&quot;) &gt; -1)
				{
					// default/sample values for Windows users
					javaHome.text = &quot;C:\\Program Files\\Java\\jdk1.6.0&quot;;
					tomcatHome.text = &quot;C:\\tomcat&quot;;
				}
				else if (Capabilities.os.toLowerCase().indexOf(&quot;mac&quot;) &gt; -1)
				{
					// default/sample values for Mac users
					javaHome.text = &quot;/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0&quot;;
					tomcatHome.text = &quot;/Applications/tomcat/&quot;;
				}

			}

			public function startTomcat():void
			{
				// Write the Java and Tomcat home paths to config.xml so that they can be presented
				// to the user the next time the application is started
				writeConfig();

				log.text = &quot;Starting Tomcat...&quot; + File.lineEnding;
				startTomcatProcess = new NativeProcess();
				execute(startTomcatProcess, &quot;start&quot;);
			}

			public function stopTomcat():void
			{
				log.text = &quot;Stopping Tomcat...&quot; + File.lineEnding;
				stopTomcatProcess = new NativeProcess();
				execute(startTomcatProcess, &quot;stop&quot;);
			}

			public function execute(process:NativeProcess, arg:String):void
			{
				// Get a file reference to the JVM
				var file:File = new File(javaHome.text);
				if (Capabilities.os.toLowerCase().indexOf(&quot;win&quot;) &gt; -1)
				{
					file = file.resolvePath(&quot;bin/javaw.exe&quot;);
				}
				else
				{
					file = file.resolvePath(&quot;Home/bin/java&quot;);
				}

				var tomcatHomeFile:File = new File(tomcatHome.text);

				// Start the process
				try
				{
					var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
					nativeProcessStartupInfo.executable = file;
					nativeProcessStartupInfo.workingDirectory = tomcatHomeFile.resolvePath(&quot;bin&quot;);
					var processArgs:Vector.&lt;String&gt; = new Vector.&lt;String&gt;();
					processArgs[0] = &quot;-Dcatalina.home=&quot;+tomcatHome.text;
					processArgs[1] = &quot;-classpath&quot;;
					processArgs[2] = tomcatHomeFile.resolvePath(&quot;bin/bootstrap.jar&quot;).nativePath;
					processArgs[3] = &quot;org.apache.catalina.startup.Bootstrap&quot;;
					processArgs[4] = arg;
					nativeProcessStartupInfo.arguments = processArgs;
					startTomcatProcess = new NativeProcess();
					startTomcatProcess.start(nativeProcessStartupInfo);
					startTomcatProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA,
						outputDataHandler);
					startTomcatProcess.addEventListener(ProgressEvent.STANDARD_ERROR_DATA,
						errorOutputDataHandler);
				}
				catch (e:Error)
				{
					Alert.show(e.message, &quot;Error&quot;);
				}
			}

			public function outputDataHandler(event:ProgressEvent):void
			{
				var process:NativeProcess = event.target as NativeProcess;
				var data:String = process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable);
				log.text += data;
			}

			public function errorOutputDataHandler(event:ProgressEvent):void
			{
				var process:NativeProcess = event.target as NativeProcess;
				var data:String = process.standardError.readUTFBytes(startTomcatProcess.standardError.bytesAvailable);
				log.text += data;
			}

			private function readConfig():XML
			{
				var file:File = File.applicationStorageDirectory.resolvePath(&quot;config.xml&quot;);
				if (file.exists)
				{
					var fileStream:FileStream = new FileStream();
					fileStream.open(file, FileMode.READ);
					var xml:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
					fileStream.close();
					return xml;
				}
				else
				{
					return null;
				}
			}

			private function writeConfig():void
			{
				var xml:String = '&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;' + File.lineEnding;
				xml += &quot;&lt;config&gt;&quot; + File.lineEnding;
				xml += &quot;&lt;javaHome&gt;&quot; + javaHome.text + &quot;&lt;/javaHome&gt;&quot; + File.lineEnding;
				xml += &quot;&lt;tomcatHome&gt;&quot; + tomcatHome.text + &quot;&lt;/tomcatHome&gt;&quot; + File.lineEnding;
				xml += &quot;&lt;/config&gt;&quot; + File.lineEnding;

				var file:File = File.applicationStorageDirectory.resolvePath(&quot;config.xml&quot;);
				var fileStream:FileStream = new FileStream();
				fileStream.open(file, FileMode.WRITE);
				fileStream.writeUTFBytes(xml);
				fileStream.close();
			}

			private function openWithDefaultEditor():void
			{
				var file:File =
					File.createTempDirectory().resolvePath(&quot;tomcat_launcher_console.txt&quot;);
				var fileStream:FileStream = new FileStream();
				fileStream.open(file, FileMode.WRITE);
				fileStream.writeUTFBytes(log.text);
				fileStream.close();
				file.openWithDefaultApplication();
			}

		]]&gt;
	&lt;/fx:Script&gt;

	&lt;mx:Form width=&quot;100%&quot;&gt;
		&lt;mx:FormItem label=&quot;Java Home&quot; width=&quot;100%&quot;&gt;
			&lt;s:TextInput id=&quot;javaHome&quot; width=&quot;100%&quot;/&gt;
		&lt;/mx:FormItem&gt;
		&lt;mx:FormItem label=&quot;Tomcat Home&quot; width=&quot;100%&quot;&gt;
			&lt;s:TextInput id=&quot;tomcatHome&quot; width=&quot;100%&quot;/&gt;
		&lt;/mx:FormItem&gt;
	&lt;/mx:Form&gt;

	&lt;s:HGroup&gt;
		&lt;s:Button label=&quot;Start&quot; click=&quot;startTomcat()&quot;/&gt;
		&lt;s:Button label=&quot;Stop&quot; click=&quot;stopTomcat()&quot;/&gt;
		&lt;s:Button label=&quot;Clear Console&quot; click=&quot;log.text=''&quot;/&gt;
		&lt;s:Button label=&quot;Open in Default Text Editor&quot;
				  click=&quot;openWithDefaultEditor()&quot;/&gt;
	&lt;/s:HGroup&gt;
	&lt;s:TextArea id=&quot;log&quot; width=&quot;100%&quot; height=&quot;100%&quot;/&gt;

&lt;/s:WindowedApplication&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/12/tomcat-launcher-sample-application-using-the-air-2-0-native-process-api/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>&#8220;Open in Excel&#8221;: Another AIR 2 Mini Sample</title>
		<link>http://coenraets.org/blog/2009/11/open-in-excel-another-air-2-mini-sample/</link>
		<comments>http://coenraets.org/blog/2009/11/open-in-excel-another-air-2-mini-sample/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 17:44:02 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Air]]></category>
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=244</guid>
		<description><![CDATA[
In Adobe AIR 1.0 and 1.5, there were different options to &#8220;open&#8221; the data of a Flex DataGrid in Excel. For example, you could leverage the AIR native drag-and-drop support to drag rows from the DataGrid to an open Excel spreadsheet. You could also drag rows to the desktop (or anywhere on the file system) [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://coenraets.org/AIR2Excel/AIR2Excel.png" alt="" /></p>
<p>In Adobe AIR 1.0 and 1.5, there were different options to &#8220;open&#8221; the data of a Flex DataGrid in Excel. For example, you could leverage the AIR native drag-and-drop support to drag rows from the DataGrid to an open Excel spreadsheet. You could also drag rows to the desktop (or anywhere on the file system) as an .xls file. These two approaches are demonstrated in my <a href="http://coenraets.org/blog/2009/03/make-and-receive-phone-calls-in-the-new-version-of-the-salesbuilder-sample-flex-application/">Salesbuilder sample application</a>. Another approach was to use a server roundtrip to download the generated .xls file from the server and force Excel to open with the data.</p>
<p>There was however no immediate way to implement a straight (client-side only) &#8220;Open in Excel&#8221; feature (aka click a button to open your DataGrid data in Excel). With AIR 2.0 and the new <strong>File.openWithDefaultApplication()</strong> method this becomes extremely easy to implement. In the sample below, I provide an example of this new feature. The sample also supports the drag-and-drop approach from the AIR application to Excel and from the AIR application to the desktop (or anywhere else on the file system). This sample uses the <a href="http://code.google.com/p/as3xls/">as3xls library</a> to create the Excel spreadsheet. View Source is enabled.</p>
<h3>Installation Instructions</h3>
<ol>
<li>Download the AIR 2.0 beta runtime <a href="http://labs.adobe.com/downloads/air2.html">here</a>.</li>
<li>Download AIR2Excel.air <a href="http://coenraets.org/AIR2Excel/AIR2Excel.air">here</a>.</li>
<li>Double-click AIR2Excel.air in Explorer or Finder to start the installation process.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/11/open-in-excel-another-air-2-mini-sample/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>&#8220;Voice Notes&#8221;: Record Voice Notes and Persist them in SQLite with AIR 2</title>
		<link>http://coenraets.org/blog/2009/11/voice-notes-record-voice-notes-and-persist-them-in-sqlite-with-air-2/</link>
		<comments>http://coenraets.org/blog/2009/11/voice-notes-record-voice-notes-and-persist-them-in-sqlite-with-air-2/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 13:42:57 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Air]]></category>
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=214</guid>
		<description><![CDATA[As you probably already know, the Flash Player 10.1 and AIR 2 betas are now available on Adobe Labs. I&#8217;ve been playing with the Microphone API in AIR 2 while working on the booth here at Devoxx, and built this small sample application that allows you to record voice notes and store them in the [...]]]></description>
			<content:encoded><![CDATA[<p>As you probably already know, the Flash Player 10.1 and AIR 2 betas are now available on <a href="http://labs.adobe.com">Adobe Labs</a>. I&#8217;ve been playing with the Microphone API in AIR 2 while working on the booth here at <a href="http://www.devoxx.com">Devoxx</a>, and built this small sample application that allows you to record voice notes and store them in the embedded SQLite database so that you can replay them later.</p>
<p>No rocket science here (and no designer involved), just one more microphone API sample. You can install the application here (AIR 2 required): </p>
<h3>Installation Instructions</h3>
<ol>
<li>Download the AIR 2.0 beta runtime <a href="http://labs.adobe.com/downloads/air2.html">here</a>.</li>
<li>Download voicenotes.air <a href="http://coenraets.org/voicenotes/voicenotes.air">here</a>.</li>
<li>Double-click voicenotes.air in Explorer or Finder to start the installation process.</li>
</ol>
<p>View Source (right click) is enabled.</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/11/voice-notes-record-voice-notes-and-persist-them-in-sqlite-with-air-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
