<?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"
	>

<channel>
	<title>Kevin Hoyt</title>
	<atom:link href="http://blog.kevinhoyt.org/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.kevinhoyt.org</link>
	<description>On the desktop, on the web, on the device ... On the Platform</description>
	<pubDate>Tue, 10 Mar 2009 14:49:52 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>ActionScript 3 TIFF Encoder</title>
		<link>http://blog.kevinhoyt.org/2009/03/10/actionscript-3-tiff-encoder/</link>
		<comments>http://blog.kevinhoyt.org/2009/03/10/actionscript-3-tiff-encoder/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 14:49:52 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<category><![CDATA[Flash]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=319</guid>
		<description><![CDATA[Yeah, yeah, I know that there’s already ActionScript 3 encoders for a variety of image formats.  I’ve used the PNG and JPEG encoders from the AS3 Core Library on numerous projects.  These days, if you’re a Flex developer, PNG and JPEG support are baked right into the framework.  So why TIFF?  [...]]]></description>
			<content:encoded><![CDATA[<p>Yeah, yeah, I know that there’s already ActionScript 3 encoders for a variety of image formats.  I’ve used the PNG and JPEG encoders from the AS3 Core Library on numerous projects.  These days, if you’re a Flex developer, PNG and JPEG support are baked right into the framework.  So why <a href="http://en.wikipedia.org/wiki/Tagged_Image_File_Format">TIFF</a>?  I mean, it’s not like browsers support the format.  TIFF however is still very common in the world of <a href="http://en.wikipedia.org/wiki/Document_management">document</a> and <a href="http://en.wikipedia.org/wiki/GeoTIFF">scientific</a> imaging.  I ran across just such a need the other day, and necessity is the mother of invention.<br />
<span id="more-319"></span><br />
Getting going on this project was actually pretty easy.  The first thing I needed was a sample TIFF image file.  Since virtually every image editor can produce TIFF files, it was pretty easy to make my own.  Then I needed a way to see the bytes of the file, for which I turned to my favorite hex editor, <a href="http://www.suavetech.com/0xed/0xed.html">0xED</a>.  Finally I needed the <a href="http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf">specification</a>, which Adobe controls, and is publicly available on it’s web site.  Version 6.0 is the most recent, and was published in 1992, so it’s a very stable specification.</p>
<p>Once you crack open the specification, and start mapping it to the bytes of your test file, you’ll find the basic pretty straightforward.  There’s a header section that identifies the file type, then one or more file descriptors (IFD), and of course the image data itself.  How that image data is stored is up to you, and the TIFF specification provides lots of options, but since I wasn’t interest size, I just went with raw RGB.  There’s a section in the specification that talks about how this choice is formatted, among which are the required markers in the IFD.</p>
<p>Markers follow a twelve (12) byte pattern, where there’s two bytes that say what the marker holds, two bytes that say what the data type of the marker is, four bytes that say how many of said type exist, and then another four bytes that hold the actual value.  That is, that hold the value most of the times, and there’s where I got stuck.  The are certain markers that don’t fit into four bytes.  Say for example, an array of three values that specify color depth - red, green and blue as three two byte (short) values equals six bytes needed.</p>
<p>In these cases, the value contained in the marker is a pointer, or file offset, to the actual values.  As an example, the required bits per sample marker (258) there’s supposed to be three values of eight (8).  Depending on the file you’re looking at in your trusty hex editor, you’ll find any variety of values that don’t look anything like “8” or any derivative therein.  In this case, and a few others, the value is actually a pointer to the place in the file where you can actually find the three “8” values (as three consecutive shorts).  It’s subtle, but critical in getting the format of the file correct.</p>
<p>Yeah, I know, you’re bored.  This is a lame discussion of pointers to offsets, and the values you’ll find there.  Not particularly exciting (but very helpful if you’re like me and blow half a day figuring it out).  What <em>is</em> exciting is that since I don’t worry about compression, the encoding of the file is lightening fast.  A 640&#215;480 image takes under a second to encode.  The resulting 900 kb can then be uploaded to a server for further processing.  Worth consideration if you’ve ever hit the lag associated with the other encoders out there.  Okay, here’s the <a href="http://blog.kevinhoyt.org/wp-content/tiff-encoder.zip">code</a> (and an example below), go have fun.</p>
<p><object width="600" height="600"><param name="movie" value="http://blog.kevinhoyt.org/wp-content/TiffCapture.swf"><embed src="http://blog.kevinhoyt.org/wp-content/TiffCapture.swf" width="600" height="600"></embed></object></p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2009/03/10/actionscript-3-tiff-encoder/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Collaborative Calendar with AFCS and iLog</title>
		<link>http://blog.kevinhoyt.org/2009/03/02/collaborative-calendar-with-afcs-and-ilog/</link>
		<comments>http://blog.kevinhoyt.org/2009/03/02/collaborative-calendar-with-afcs-and-ilog/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 17:43:23 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[ActionScript]]></category>

		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=313</guid>
		<description><![CDATA[Recently, the “Cocomo” project lost it’s Beach Boys theme, and got an official name: Adobe Flash Collaboration Services (AFCS).  I’ve been really fond of this project since I was first able to get my hands on it, but there were aspects of its approach that I just didn’t get.  Last week I got [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, the “Cocomo” project lost it’s Beach Boys theme, and got an official name: <a href="http://labs.adobe.com/technologies/afcs/">Adobe Flash Collaboration Services</a> (AFCS).  I’ve been really fond of this project since I was first able to get my hands on it, but there were aspects of its approach that I just didn’t get.  Last week I got a chance to pick <a href="http://blogs.adobe.com/collabmethods/">Nigel Pegg’s</a> (AFCS Architect) brain a little bit, and walked away with a much better understanding of some of the details.  Last week, iLog also launched <a href="http://www.ilog.com/products/ilogelixir/demos/">Elixir 2.0</a> with a calendar component (among many others).  The two, I thought, were a match made in heaven, so here is a little collaborative calendaring experiment.<br />
<span id="more-313"></span><br />
<a href="http://www.kevinhoyt.org/scheduling"><img src="http://blog.kevinhoyt.org/wp-content/uploads/afcs-scheduling.jpg" alt="" title="afcs-scheduling" width="500" height="364" class="alignnone size-full wp-image-315" /></a></p>
<p>To be sure, I’m not an AFCS master by any stretch of the imagination.  I’ve long since got a handle on the messaging systems offered by <a href="http://opensource.adobe.com/wiki/display/blazeds/BlazeDS">BlazeDS</a> and it’s big brother <a href="http://www.adobe.com/products/livecycle/dataservices/">LiveCycle DS</a>, but these are both very granular approaches.  By comparison AFCS accounts for access control, permissions, control management and more, before it even gets to sending a message.  While it sounds overwhelming, it’s really great to not have to think about how this happens in a system where there might be a large number of collaborators.</p>
<p>I should also note the Sean Hess’s ongoing <a href="http://code.seanhess.net/?p=122">AFCS tutorial</a> helped me immensely!  I don’t know if it is Sean’s intent or not, but his tutorials seem to approach AFCS from the point of view of somebody coming from Blaze or LiveCycle, and at the same time each tutorial is laser focused on a specific task.  I highly recommend Sean’s tutorials if you’re getting started with AFCS.</p>
<p>It turns out that there’s a lot of ways to synchronize data with AFCS.  The SharedPropery class and it’s subclass BatonProperty were really appealing at first, but I ended up using a separate Baton and CollectionNode.  The concept of a “baton” is to handle who’s in control of a piece of data, such that two participants don’t try to edit the same piece of data at the same time.  The collection node is a marker for data off in the AFCS cloud.  For the purposes of this demonstration it’s what I use to send change messages.  To get logged in then, and setup the baton and collection node, you’re looking at roughly the following lines of code.</p>

<div class="wp_syntax"><div class="code"><pre class="xml xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- Authenticator (room setup to auto promote --&gt;</span>
<span style="color: #808080; font-style: italic;">&lt;!-- Connection to AFCS --&gt;</span>
<span style="color: #808080; font-style: italic;">&lt;!-- Collection node to share data --&gt;</span>
<span style="color: #808080; font-style: italic;">&lt;!-- Baton to control who is editing --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rtc:AdobeHSAuthenticator</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;auth&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rtc:ConnectSession</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;session&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">authenticator</span>=<span style="color: #ff0000;">&quot;{auth}&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">roomURL</span>=<span style="color: #ff0000;">&quot;{ROOM_URL}&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">synchronizationChange</span>=<span style="color: #ff0000;">&quot;doSync( event )&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>		
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;afcs:CollectionNode</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;node&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">sharedID</span>=<span style="color: #ff0000;">&quot;sharedCalendar&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">connectSession</span>=<span style="color: #ff0000;">&quot;{session}&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">itemReceive</span>=<span style="color: #ff0000;">&quot;doReceive( event )&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">synchronizationChange</span>=<span style="color: #ff0000;">&quot;doNode( event )&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;afcs:Baton</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;baton&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">batonHolderChange</span>=<span style="color: #ff0000;">&quot;doBaton( event )&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

<p>I spend a lot of times in meetings, or in transit to them.  Suffice to say, for those of you that hate meetings, I’m generally the cause of them.  It’s my job - interrupt your otherwise normally scheduled project, to inject an air of possibility and vision.  Or chaos.  You know, it’s all good.  Anyways, as you might imagine, my life revolves around my calendar.  When I heard that iLog was releasing a calendar control with Elixir 2.0 I instantly got excited about the possibilities.  For what it’s worth, the list of controls that comes with Elixir is astonishing, and there’s a free 66 (?) day trial available as well.  An editable calendar in a “month” view is as simple as the following.</p>

<div class="wp_syntax"><div class="code"><pre class="xml xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- iLog Elixer calendar control --&gt;</span>	
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ilog:Calendar</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">showEffect</span>=<span style="color: #ff0000;">&quot;{fadein}&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;calendar&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">bottom</span>=<span style="color: #ff0000;">&quot;72&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">left</span>=<span style="color: #ff0000;">&quot;40&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">right</span>=<span style="color: #ff0000;">&quot;40&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">top</span>=<span style="color: #ff0000;">&quot;40&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">dataProvider</span>=<span style="color: #ff0000;">&quot;{appointments}&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">startTimeField</span>=<span style="color: #ff0000;">&quot;start&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">endTimeField</span>=<span style="color: #ff0000;">&quot;end&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">summaryField</span>=<span style="color: #ff0000;">&quot;summary&quot;</span>  </span>
<span style="color: #009900;">	<span style="color: #000066;">mode</span>=<span style="color: #ff0000;">&quot;month&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">visible</span>=<span style="color: #ff0000;">&quot;false&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">itemEditBegin</span>=<span style="color: #ff0000;">&quot;doBegin( event )&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">itemEditEnd</span>=<span style="color: #ff0000;">&quot;doEnd( event )&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

<p>To populate the calendar, I load an ICS (iCalender) file via HTTP, and parse it as raw text into “event” objects.  I’ve written about working with ICS file before, so I’ll spare you the details, but in general, ICS files are text where individual lines contain the data.  A little state machine makes processing the file a snap.  Also, it is worth noting that HTTPService is capable of loading any text, it just turns out that most of the time you’re working with XML, and you want an object model.  Not so here, where I just want to handle the raw text myself, which HTTPService can accommodate as well.</p>

<div class="wp_syntax"><div class="code"><pre class="xml xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- Collection to hold appointments on calendar --&gt;</span>
<span style="color: #808080; font-style: italic;">&lt;!-- Service to fetch calendar --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:ArrayCollection</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;appointments&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:HTTPService</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;svcCal&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">url</span>=<span style="color: #ff0000;">&quot;data/tripit.ics&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">resultFormat</span>=<span style="color: #ff0000;">&quot;text&quot;</span> </span>
<span style="color: #009900;">	<span style="color: #000066;">result</span>=<span style="color: #ff0000;">&quot;doCalendar( event )&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">// Handle the load of the data file by parsing the appointments</span>
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> doCalendar<span style="color: #66cc66;">&#40;</span> event:ResultEvent <span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #808080; font-style: italic;">// Break data into discreet data lines</span>
	<span style="color: #000000; font-weight: bold;">var</span> line:<span style="color: #0066CC;">Array</span> = <span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#40;</span> svcCal.<span style="color: #006600;">lastResult</span> <span style="color: #66cc66;">&#41;</span>.<span style="color: #0066CC;">split</span><span style="color: #66cc66;">&#40;</span> CR_LF <span style="color: #66cc66;">&#41;</span>;
	<span style="color: #000000; font-weight: bold;">var</span> vevent:VEvent = <span style="color: #000000; font-weight: bold;">null</span>;
&nbsp;
	lblStatus.<span style="color: #0066CC;">text</span> = <span style="color: #ff0000;">&quot;Parsing calendar file into appointment collection...&quot;</span>;
&nbsp;
	<span style="color: #808080; font-style: italic;">// Build appointment object from lines of data</span>
	<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span> <span style="color: #000000; font-weight: bold;">var</span> a:<span style="color: #0066CC;">Number</span> = 0; a <span style="color: #66cc66;">&lt;</span> line.<span style="color: #0066CC;">length</span>; a++ <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #808080; font-style: italic;">// Put the object into the collection when the data has been parsed</span>
		<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> line<span style="color: #66cc66;">&#91;</span>a<span style="color: #66cc66;">&#93;</span> == END_VEVENT <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			appointments.<span style="color: #006600;">addItem</span><span style="color: #66cc66;">&#40;</span> vevent <span style="color: #66cc66;">&#41;</span>;
			vevent = <span style="color: #000000; font-weight: bold;">null</span>;
		<span style="color: #66cc66;">&#125;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;">// Parse the lines of data between a begin and end marker</span>
		<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> vevent <span style="color: #66cc66;">!</span>= <span style="color: #000000; font-weight: bold;">null</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			vevent.<span style="color: #006600;">parse</span><span style="color: #66cc66;">&#40;</span> line<span style="color: #66cc66;">&#91;</span>a<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#41;</span>;
		<span style="color: #66cc66;">&#125;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;">// Found a new begin, so setup a new appointment object</span>
		<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> line<span style="color: #66cc66;">&#91;</span>a<span style="color: #66cc66;">&#93;</span> == BEGIN_VEVENT <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			vevent = <span style="color: #000000; font-weight: bold;">new</span> VEvent<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
		<span style="color: #66cc66;">&#125;</span>
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	lblStatus.<span style="color: #0066CC;">visible</span> = <span style="color: #000000; font-weight: bold;">false</span>;				
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>At a high level, I’ve not gotten a connection to AFCS, put a calendar on the screen, and loaded and parsed some event data to display.  Now all that’s left is to let people edit the calendar on their side, and then notify everybody else that a change has been made.  The bulk of this work lies in two methods.  The first is one to send the changes, which makes a duplicate of the changed event data and sends it along as a message on the collection node.  The second is the logic to receive changes, find them in the data model, and apply the update.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">// Called when a calendar item has been edited/changed			</span>
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> doEnd<span style="color: #66cc66;">&#40;</span> event:CalendarEvent <span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">var</span> mess:MessageItem = <span style="color: #000000; font-weight: bold;">null</span>;				
	<span style="color: #000000; font-weight: bold;">var</span> update:VEvent = <span style="color: #000000; font-weight: bold;">new</span> VEvent<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
	<span style="color: #808080; font-style: italic;">// Create a representation of the change to pass to other clients</span>
	update.<span style="color: #0066CC;">start</span> = event.<span style="color: #006600;">startDate</span>;
	update.<span style="color: #0066CC;">end</span> = event.<span style="color: #006600;">endDate</span>;
	update.<span style="color: #006600;">summary</span> = event.<span style="color: #006600;">item</span>.<span style="color: #006600;">summary</span>;
	update.<span style="color: #006600;">uid</span> = event.<span style="color: #006600;">item</span>.<span style="color: #006600;">uid</span>;
&nbsp;
	<span style="color: #808080; font-style: italic;">// Sends changed data</span>
	mess = <span style="color: #000000; font-weight: bold;">new</span> MessageItem<span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">&quot;appt&quot;</span>, update <span style="color: #66cc66;">&#41;</span>;
	node.<span style="color: #006600;">publishItem</span><span style="color: #66cc66;">&#40;</span> mess <span style="color: #66cc66;">&#41;</span>;				
<span style="color: #66cc66;">&#125;</span>	
&nbsp;
<span style="color: #808080; font-style: italic;">// Called when the appointment node has changed</span>
<span style="color: #808080; font-style: italic;">// Updates calendar if necessary</span>
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> doReceive<span style="color: #66cc66;">&#40;</span> event:CollectionNodeEvent <span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">var</span> item:VEvent = <span style="color: #000000; font-weight: bold;">null</span>;
	<span style="color: #000000; font-weight: bold;">var</span> update:VEvent = <span style="color: #000000; font-weight: bold;">null</span>;
&nbsp;
	<span style="color: #808080; font-style: italic;">// Make sure this is an appointment value</span>
	<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> event.<span style="color: #006600;">item</span>.<span style="color: #006600;">body</span>.<span style="color: #0066CC;">start</span> == <span style="color: #0066CC;">undefined</span> <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #b1b100;">return</span>;
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #808080; font-style: italic;">// Do not need to register changes if I made the change</span>
	<span style="color: #808080; font-style: italic;">// Do need to release the baton so others can edit</span>
	<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> baton.<span style="color: #006600;">amIHolding</span> <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		baton.<span style="color: #006600;">putDown</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
		<span style="color: #b1b100;">return</span>;
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	<span style="color: #808080; font-style: italic;">// Find a match in the data model for the changed appointment</span>
	<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span> <span style="color: #000000; font-weight: bold;">var</span> a:<span style="color: #0066CC;">Number</span> = 0; a <span style="color: #66cc66;">&lt;</span> appointments.<span style="color: #0066CC;">length</span>; a++ <span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		item = appointments.<span style="color: #006600;">getItemAt</span><span style="color: #66cc66;">&#40;</span> a <span style="color: #66cc66;">&#41;</span> as VEvent;
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span> item.<span style="color: #006600;">uid</span> == event.<span style="color: #006600;">item</span>.<span style="color: #006600;">body</span>.<span style="color: #006600;">uid</span> <span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			update = <span style="color: #000000; font-weight: bold;">new</span> VEvent<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
			update.<span style="color: #0066CC;">start</span> = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">Date</span><span style="color: #66cc66;">&#40;</span> event.<span style="color: #006600;">item</span>.<span style="color: #006600;">body</span>.<span style="color: #0066CC;">start</span>.<span style="color: #0066CC;">time</span> <span style="color: #66cc66;">&#41;</span>;
			update.<span style="color: #0066CC;">end</span> = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">Date</span><span style="color: #66cc66;">&#40;</span> event.<span style="color: #006600;">item</span>.<span style="color: #006600;">body</span>.<span style="color: #0066CC;">end</span>.<span style="color: #0066CC;">time</span> <span style="color: #66cc66;">&#41;</span>;
			update.<span style="color: #006600;">summary</span> = event.<span style="color: #006600;">item</span>.<span style="color: #006600;">body</span>.<span style="color: #006600;">summary</span>;
			update.<span style="color: #006600;">uid</span> = event.<span style="color: #006600;">item</span>.<span style="color: #006600;">body</span>.<span style="color: #006600;">uid</span>;
&nbsp;
			<span style="color: #808080; font-style: italic;">// Update the appointment data</span>
			appointments.<span style="color: #006600;">setItemAt</span><span style="color: #66cc66;">&#40;</span> update, a <span style="color: #66cc66;">&#41;</span>;
			<span style="color: #b1b100;">break</span>;
		<span style="color: #66cc66;">&#125;</span>
	<span style="color: #66cc66;">&#125;</span> 
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>One weak area that I noticed as I was wrapping up is that I expect event data on the collection node, when that may not always be the case.  More importantly is that it could be reused for multiple purposes with a little additional work.  For example, when the calendar week selection is changed, I could publish a message to get everybody on the same view.  I suspect that I’d probably add a “label” property to the body of the message, and make a “data” property the related object.  That’s another task for another day however.  If you want the source code, you can right click on the <a href="http://www.kevinhoyt.org/scheduling/">example application</a> to view and download it.</p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2009/03/02/collaborative-calendar-with-afcs-and-ilog/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Types of Evangelists</title>
		<link>http://blog.kevinhoyt.org/2009/02/21/types-of-evangelists/</link>
		<comments>http://blog.kevinhoyt.org/2009/02/21/types-of-evangelists/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 03:15:23 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[Business]]></category>

		<category><![CDATA[Evangelism]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=309</guid>
		<description><![CDATA[It surprises me just how frequently I hear somebody mention that they think Adobe evangelists should behave one way or another.  Or that they should be more involved more in a certain aspect of business than they may be.  The problem with these perceptions is that they assume all evangelists are identical in [...]]]></description>
			<content:encoded><![CDATA[<p>It surprises me just how frequently I hear somebody mention that they think Adobe evangelists should behave one way or another.  Or that they should be more involved more in a certain aspect of business than they may be.  The problem with these perceptions is that they assume all evangelists are identical in skill, and equally motivated by the same interests.  It is with that in mind that I thought I would continue my series on the business of technology evangelism by exploring the types of evangelists.<br />
<span id="more-309"></span><br />
<em>Note: The thoughts contained in this discussion are far from entirely my own.  There are many cases in which I have paraphrased extensively from the work of Rick Greenwald entitled “<a href="http://www.amazon.com/Making-Technical-Sale-Successful-Consultant/dp/0966288998/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1235272074&#038;sr=8-2">Making the Technical Sale</a>.”  Where I have added however is in the application and transition of the principles presented in that work, into the field of technology evangelism (marketing as opposed to sales).  </em></p>
<p><strong>Introduction</strong></p>
<p>Evangelist are people, and like any other person in any other role across a company, they have personal sets of likes and dislikes.  These sets of likes and dislikes will likely be what has gotten an individual to the point where they have become an evangelist.  That being said, evangelists may have gotten to the role by any myriad of paths.  </p>
<p>That path will have been defined by their characteristics as people, and as such not all evangelists are created equal.  That’s not to say that one is better than another, but simply that an evangelist will function and work best when aligned with their personal sets of likes and dislikes.  This seems like an obvious statement, but it is often overlooked which results in the misperception that all evangelist should behave in a certain manner.</p>
<p>Products are not magically introduced into stardom overnight.  Products must evolve through a process of exploration, adoption and eventual market acceptance by lasting the test of time.  To be sure, not all products can make the transition effectively, and will either be aggregated by one that can, or simply cease to exist.  For the purposes of this discussion, we’ll call that process the product life cycle, and start by defining the various stages.</p>
<p><strong>Market Definition</strong></p>
<p><em>Early Market</em></p>
<p>When a product is first released to the market, it enters the “early market” phase of it’s life cycle.  In this phase, companies look to the technology as a potential means of competitive advantage.  By moving faster, and potentially willing to take on some risk, some companies look to out-innovate their competition by investing in emerging technologies.  These companies are willing to forgo solid documentation, potential product quality issues, or even reference accounts.</p>
<p><em>Popular Market</em></p>
<p>Over time a product will gain more market share and become more widely known.  This is the “popular market” portion of a product’s life cycle.  With more market share comes more acceptance of the product and subsequently more deployments.  The view of the product will become more legitimate as it evolves to be more feature complete and stable.  This stage of the product’s life cycle invites competition to challenge its success as well.  With additional competition, also comes the definition of a standard set of expected features.</p>
<p>In my opinion, Adobe Flex as an example, has firmly left the early market phase of it’s life and is now in the beginning stages of the popular market phase.</p>
<p><em>Mature Market</em></p>
<p>The final stage in the product life cycle then is the “mature market.”  The robust ecosystem of competitive and supportive products now in place will bring with the product an enormous amount of purchasing power.  This also ultimately results in a lengthening of the sales cycle as companies dig deep on features and business value.  Examples of products in this space today include the relational database and the web browser.</p>
<p><strong>The Maverick</strong></p>
<p>The “maverick” technology evangelist thrives best in the early market phase of the product life cycle.  This individual enjoys technology for technologies sake, and requires almost no support.  The maverick is less sensitive to corporate messaging, and more inclined to give straight answers regardless of how it may impact a customer’s perception.  They will code live demonstrations in front of the customer, and even spend time with the customer creating solutions that fill the inherent weaknesses in the fledgling product.  </p>
<p>An interesting characteristic of the maverick is that they immediately see the product’s market benefit.  To that end, they may go out and evangelize the product based strictly on the potential.  When they encounter technical challenges, they may not know the answer, but they will understand the basis of the question, and they’ll know where to get answers.  Where this gets interesting is that if there is no good answer, then the maverick will be entirely up front about it.</p>
<p>Eventually the product that the maverick became infatuated with, will grow into the popular and mature markets.  As it does so, the maverick will eventually become dissatisfied with either the role, the product, or both, and move onto the “next big thing.”  Depending on the nature of the product, some mavericks may realign themselves with different aspects of the product - those complementary products or features which feel compelling to their nature.  As a product matures, mavericks will also be looked upon to help newcomers get up to speed.</p>
<p><strong>The Demo Demon</strong></p>
<p>The “demo demon” loves riding the wave of a product’s growing success as it moves from the early market to the popular market.  These evangelists are highly adaptable and can become proficient very quickly with any additional technology.  The demo demon perfectly fits the classic “mile wide and inch deep” metaphor.  They don’t have to embrace ancillary technologies in order to show how they integrate with their product(s), but simply get deep enough to communicate the key points and value proposition.</p>
<p>To that end, a demo demon will likely have no desire to ever fully master a technology - potentially even the very one(s) they are evangelizing.  This type evangelist also loves to travel, and can memorize new demos and scripts quickly.</p>
<p>Demo demons aren’t deep enough technically to do well in the early market where customers require their partners to roll up their sleeves and get dirty.  That’s not to say that they’ll be entirely ineffective however as their demo skills will allow them to talk around any remaining product weak points.</p>
<p>The popular market is where the demo demon shines as they eagerly hit the streets.  Their mastery of the demos and key messaging are so powerful that they become key contributors to the product’s explosion in growth.  The demo demon is slightly ahead of the market in this respect and ready for the next big thing.  They can be helpful allies to the product marketing teams in this respect.</p>
<p>In the mature market the demo demon is going to get bored.  Long since past will be the days of spinning and weaving a story around the product(s) they once defended through eloquence.  Because they’re generally not interested in technical deep dives and the product guts, a demo demon will require a good support organization as their product(s) enter the mature market.  In that same sense, these individuals may eventually look to transition to sales representatives.</p>
<p><strong>The Implementor</strong></p>
<p>The “implementor” is well organized, genuinely likes technology, and is steady and loyal to specific products.  These individuals could really care less about the next big thing and are completely happy to fully master one technology.  The implementor will likely be inclined to stay with a single company for a long period of time.  This tenure will make them ideal resources in understanding the history of features and why something is implemented in the product in a specific manner.</p>
<p>The implementor does not perform well in the early market phase of the product life cycle.  Their expectations for robust feature depth will not translate well to new products.  The implementor will likely care less about a new products proposed innovations and will quickly point out technical flaws.</p>
<p>Implementors may be helpful in the late phases of the popular market, but will have a distinct distaste for the fast pace required to keep up with the growth of the product in the early stages.</p>
<p>The mature market is where an implementor will shine.  Being less impressed with fancy features, and short on hype, this is where the implementor hits their stride.  This is perfect of course as customers evaluating products in the mature market will expect thorough support.  The implementor will also likely be very familiar with the standards now surrounding a product in the mature market.  Finally, the implementor will enjoy long-term exposure with a defined set of customers so they can see the growth of projects using the technology they’ve been promoting.</p>
<p><strong>Conclusion</strong></p>
<p>To be sure, there are no hard and fast rules here, and lots of grey area and overlap.  If you’re an evangelist however, chances are that one of these groupings will have likely jumped out at you.  Though realistically, you’ll probably see yourself playing other roles on occasion due to the nature of the job.  This overlap will be especially true if you have more than one product to evangelize, and even more pronounced if those products cross different phases of the product life cycle.  </p>
<p>The key to your success as an evangelist will be to take a long, hard look at where you fit, and focus your energies on your strengths.  </p>
<p>If you regularly work with an evangelist (i.e. product marketing teams), you might do well to consider where those individuals can best work for you.  Don’t try and make an implementor be the maverick.  Determine which phase of the life cycle in which your product fits, and then establish a good relationship with evangelists that work best in that environment.  If you’ve argued with an evangelist about the qualities or merits of your product, then you were probably talking to the wrong type of evangelist for where your product fits in the life cycle.</p>
<p>If you manage evangelists, then understanding the dynamics of these individuals will get you the most bang for your buck.  Not every evangelist fits into one uniform evangelist mold.  Different evangelists with different personality characteristics can work towards your mission if you have an honest evaluation of your team.  Use these characteristics to align your staff with your mission, and hire accordingly depending on the products you need to evangelize and where they are in the product life cycle.</p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2009/02/21/types-of-evangelists/feed/</wfw:commentRss>
		</item>
		<item>
		<title>JavaScript AIR Samples Updated (and More)</title>
		<link>http://blog.kevinhoyt.org/2009/01/17/javascript-air-samples-updated-and-more/</link>
		<comments>http://blog.kevinhoyt.org/2009/01/17/javascript-air-samples-updated-and-more/#comments</comments>
		<pubDate>Sat, 17 Jan 2009 17:05:42 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[AIR]]></category>

		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[HTML]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=303</guid>
		<description><![CDATA[The last time I wrote about my collection of JavaScript samples for Adobe AIR was in February of 2008.  I had just updated the then 35+ samples for AIR Beta 3.  Well, Adobe AIR has since launched (and released two minor versions), but the samples haven’t evolved.  That is until today.  [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://blog.kevinhoyt.org/2007/12/18/samples-updated-for-air-beta-3/">last time</a> I wrote about my collection of JavaScript samples for Adobe AIR was in February of 2008.  I had just updated the then 35+ samples for AIR Beta 3.  Well, <a href="http://www.adobe.com/go/air">Adobe AIR</a> has since launched (and released two minor versions), but the samples haven’t evolved.  That is until today.  I’m happy to announce that I’ve updated all the examples, combined them into a single project, and made them available as open source.<br />
<span id="more-303"></span><br />
One of the problems I had in the early days of maintaining the samples was simply that the APIs of beta products tend to change.  And quite frankly it was a lot more fun to create new samples than to maintain old outdated code.  That is of course no longer the case, the AIR APIs are solid, and we have in fact even seen features added.</p>
<p>The other problem is that the samples evolved independently of one another.  I built an example that did X, and included its own JavaScript file(s), and images, and CSS, and application manifest file, and so on down the line.  Then I moved onto the next example.  This meant that each sample had its own dependencies and needed to be updated in several places, not just the code showing how the API worked.</p>
<p>With the release, both of these problems have been solved by unifying the samples into one single application that contains all the smaller samples.  Each sample is laser focused on showing a specific part of the API, not a comprehensive example with lots of moving parts.  This makes it easier to maintain, but has the added side-effect of making it easier to learn how to use AIR features.  It also opens some interesting possibilities as a “viewer” type application.</p>
<p><img src="http://blog.kevinhoyt.org/wp-content/air-samples-dnd.jpg" width="600" height="467" /></p>
<p>While I’ve never intended to profit off the samples, I’ve also never officially released them under any specific license.  I was also the only holder of the source code, which made it impossible for anybody to really contribute to the project.  This update rolls the samples under the MIT license and moves the source code into the public domain on <a href="http://code.google.com/p/jsairsamples/">Google Code</a>.  If you want to maintain, contribute, or otherwise get involved, just let me know and I’ll add you to the SVN repository.</p>
<p>Building on the backs of giants, I also use <a href="http://jquery.com/">jQuery 1.3</a> for all the event handling in the application.  While I’d encourage you to check out jQuery if you haven’t already, knowing it is not a prerequisite to understanding how the AIR APIs function.</p>
<p>There’s now 75 samples included with the application, and there’s plenty of room to grow too.  The main areas I’d like help in is adding sections for the asynchronous features of the AIR APIs (e.g. file and database).  After that I’d like to add a “view source” option so all you actually need is the application itself.  Adding auto update should be in there somewhere as well so folks get updated when the project gets updated.  And&#8230;  Well, like I said, feel free to get involved!</p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2009/01/17/javascript-air-samples-updated-and-more/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Where Technology Evangelism Fits</title>
		<link>http://blog.kevinhoyt.org/2009/01/09/where-technology-evangelism-fits/</link>
		<comments>http://blog.kevinhoyt.org/2009/01/09/where-technology-evangelism-fits/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 21:28:52 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[Business]]></category>

		<category><![CDATA[Evangelism]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=296</guid>
		<description><![CDATA[In the world of high technology, there’s a gap between what you have to offer and what your sales force can communicate.  In many cases, the technology you have to offer simply can’t be effectively promoted in a single presentation alone.  Your technology may require that you get hands-on with the customer’s environment. [...]]]></description>
			<content:encoded><![CDATA[<p>In the world of high technology, there’s a gap between what you have to offer and what your sales force can communicate.  In many cases, the technology you have to offer simply can’t be effectively promoted in a single presentation alone.  Your technology may require that you get hands-on with the customer’s environment.  This means less cycles working new leads, and less customers you can touch, and spells disaster for a sales representative.  This is the genesis for a sales engineer and I would suggest that there’s parallels for technology evangelism as well.<br />
<span id="more-296"></span><br />
First, a little more on the role of the sales engineer.  There are no hard and fast rules here, but generally speaking a sales engineer is a person that has a solid technical understanding of the products his company offers.  His role then is to apply that technical knowledge to the customers he encounters, in a manner consistent with his compensation, to keep sales opportunities moving along.  This work was many facets, but is most commonly seen during customer demonstrations, and supporting the customer during product evaluation.</p>
<p>The sales engineer’s role almost always ends when a deal is closed.  At that point a technology company’s other departments start to get involved, such as technical support, professional services, training, etc.</p>
<p>How then does this relate to technology evangelism?  Quite simply, marketing in the world of high technology faces the same problem.  You can make brochures, place banner ads, send out email notifications, and so on all you want.  The reality is that at some point there’s a gap between where the marketing message stops and where the target customer (generally a developer or the likes) is supposed to pick it up.  This is the genesis for the technology evangelist, whose role it is to continue disseminating the corporate message, but at a technical level.</p>
<p>For all practical purposes, I believe that a better name for technology evangelist is really a marketing engineer.  You’ll find these marketing engineers at conferences, user groups, social events, online at social networking outlets, making tutorials, building new demonstrations that show how the technology could work for you (i.e. vision setting), and more.  Because these types are generally on stage, in front of a crowd, and highly visible, they’re generally considered “rock stars” and generally have some degree of ego to support that perception.</p>
<p>I would argue then, that an evangelist is only truly successful when their actions are supported by, and inline with, the overall marketing messages of the company.  </p>
<p>The relationship between a sales representative and a sales engineer is symbiotic.  Fewer deals will close without technical expertise, and fewer deals will be found without the sales expertise.  So then is the relationship between the various marketing departments of a company, and that company’s evangelists.  Fewer people will know about your product without technical exposure, and fewer opportunities to espouse those messages will be presented without traditional marketing activities.</p>
<p>This goes deeper than simply getting out there and presenting the messages you want, where you want.  To be truly successful, the evangelist and the marketing departments must work together in tandem to determine what content should be presented, where it should be presented, and what’s makes the most impact given the messages in the queue and the skills available.  How then is success measured?  What types of evangelists are there, and how do they work?  I’ll look to these topics in the future as I continue an exploration of the business side of technology evangelism.</p>
<p><em>Note: I’ve talked privately about these ideas at length with numerous members of Adobe and other marketing/technology professionals.  I can’t thank those individuals enough for taking the time to hear me out, and to provide constructive feedback.  You know who you are.  I would however like to single out <a href="http://blogs.nitobi.com/andre/">Andre Charland</a>, who encouraged me to put my thoughts down to be shared with others.</em></p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2009/01/09/where-technology-evangelism-fits/feed/</wfw:commentRss>
		</item>
		<item>
		<title>System Tray, Notification and Flickr (Juice)</title>
		<link>http://blog.kevinhoyt.org/2008/12/15/system-tray-notification-and-flickr-juice/</link>
		<comments>http://blog.kevinhoyt.org/2008/12/15/system-tray-notification-and-flickr-juice/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 21:29:15 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[AIR]]></category>

		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[HTML]]></category>

		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=293</guid>
		<description><![CDATA[In my two previous blog posts I talked about using the system tray and notifications with Adobe AIR from JavaScript-based applications.  As a proof of concept, more to myself than anything else, I also put together a sample application that uses these two techniques.  The combined application, while far more complex than the [...]]]></description>
			<content:encoded><![CDATA[<p>In my two previous blog posts I talked about using the <a href="http://blog.kevinhoyt.org/2008/12/15/using-the-system-tray-from-javascript-with-air/">system tray</a> and <a href="http://blog.kevinhoyt.org/2008/12/15/notification-windows-with-javascript-and-air/">notifications</a> with Adobe AIR from JavaScript-based applications.  As a proof of concept, more to myself than anything else, I also put together a sample application that uses these two techniques.  The combined application, while far more complex than the atomic samples I included previously, shows both of the concepts in action.  The result is an application that checks for recent <a href="http://www.flickr.com/">Flickr</a> photos and alerts you when they arrive.<br />
<span id="more-293"></span><br />
Why is this any more complex or challenging?  Well, most it is that we are dealing with remote data in this case, where the atomic samples are really self-contained shells.  I also wanted to present a somewhat more polished example here that watched the simple yet important things like centering the window.  To round things out I also keep track of a time stamp in a local file so I know if there has been an update.  This local file storage is the glue between the two examples.</p>
<p><img src="http://blog.kevinhoyt.org/wp-content/flickr-juice-main.jpg" /></p>
<p>Whenever I make a request from Flickr, I also ask it for the date the image was uploaded.  I think take this time stamp, available as milliseconds since the epoch, and compare it to what was last stored in the local file (if it exists).  If the file doesn’t exist, or the time stamps are different, then a change has taken place.  I update the locally stored file, and then download the image file from Flickr.</p>
<p>Here is where it starts to get really fun.</p>
<p>If the window is open, the window will be sized to fit the image and chrome nearly perfect, and then centered on the screen.  Along the way, I also capture the raw pixel data (bitmap data) of the downloaded image, size it to fit an icon space, and put the result in the system tray/dock depending on the operating system.  This means that the icon of the application will be constantly changing, and reflect the last access to Flickr.</p>
<p><img src="http://blog.kevinhoyt.org/wp-content/flickr-juice-dock.jpg" /></p>
<p>To take this one step further, if the application has been minimized to the system tray/dock, then whenever a new image is available, the thumbnail of that image will be presented as a notification.  The notification window will not include any chrome, but simply be the thumbnail image floating in the corner screen in front of everything else.  Since Flickr is ever changing, a new thumbnail is produced with every request from the application (every ten seconds).</p>
<p><img src="http://blog.kevinhoyt.org/wp-content/flickr-juice-notify.jpg" /></p>
<p>If you’d like to view the image presented as a thumbnail, you can click on the notification and the registered browser will open to the image on Flickr.  I also take care to clean up after myself so you don’t end up with a bunch of downloaded files hogging up your disk space.  In fact, if you find and watch the application storage directory, you’ll probably be surprised at how much activity is seamless going on behind the scenes (in a cross-platform manner to boot).</p>
<p>The result of this application is a psuedo-constant watch on the images coming into Flickr.  While it isn’t a particularly useful application, it is actually quite mesmerizing.  I found myself intoxicated with the updates on more than one occasion for several minutes.  If nothing else it shows a little of the glue that can go on between system tray/docking, icons, and notifications.  The full source and packaged AIR application is <a href="http://blog.kevinhoyt.org/wp-content/flickr-juice.zip">available for download</a>.  Since this is mostly an entertaining proof of concept, I’ve not tested extensively, but have run it successfully on both Mac and Windows.</p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2008/12/15/system-tray-notification-and-flickr-juice/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Notification Windows with JavaScript and AIR</title>
		<link>http://blog.kevinhoyt.org/2008/12/15/notification-windows-with-javascript-and-air/</link>
		<comments>http://blog.kevinhoyt.org/2008/12/15/notification-windows-with-javascript-and-air/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 20:49:39 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[AIR]]></category>

		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[HTML]]></category>

		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=286</guid>
		<description><![CDATA[While there’s a lot to consider when building notification windows, they are actually pretty easy because there’s minimal cross operating system (OS) differences for which you need to account.  A common pairing with notification windows is system tray/docking which varies considerably across OS, and can be a little more challenging.  More on that [...]]]></description>
			<content:encoded><![CDATA[<p>While there’s a lot to consider when building notification windows, they are actually pretty easy because there’s minimal cross operating system (OS) differences for which you need to account.  A common pairing with notification windows is system tray/docking which varies considerably across OS, and can be a little more challenging.  More on that in a future post.  For now however, let’s take a look at notification windows using JavaScript.  We will walk through what a notification window looks like to AIR, and explore some of the various options you have when you want to alert the user.<br />
<span id="more-286"></span><br />
If you look at the <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/display/NativeWindowType.html">documentation</a> for native windows with AIR, you’ll find a variety of different options.  A “normal” window is what you might expect, a normal OS window with the typical operating specific chrome and handers.  This will usually be a title bar, close/maximize/minimize buttons and a resize handle.  If you are a Mac user, you’ll be very familiar with “utility” windows.  Utility windows are usually what contains a tool palette or the likes, and consists of a slender title bar with some fashion of control (varies per operating system).</p>
<p>Finally is the “lightweight” window.  This is a window without any chrome whatsoever.  In the context of Adobe AIR, this is sometimes valuable; such as when you want to provide your own chrome.  When it comes to a notification window, that’s pretty much exactly what you want to do - create a window without any chrome that appears for a specified duration and then closes itself.  The “lightweight” window is the option we will use for notifications.</p>
<p>Before you go creating that window however, you will want to consider some other options on the window appearance.  Any additional fine grain control you want over that window, as manifest during it’s creation, is set through a series of native window initialization options, which you’ll find in the <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/display/NativeWindowInitOptions.html">NativeWindowInitOptions</a> class.  In the case of a lightweight window, there’s not much we need to specify here except that the type is indeed “lightweight”.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> options <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">NativeWindowInitOptions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
options.<span style="color: #660066;">type</span> <span style="color: #339933;">=</span> air.<span style="color: #660066;">NativeWindowType</span>.<span style="color: #660066;">LIGHTWEIGHT</span>;
options.<span style="color: #660066;">transparent</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span>;
options.<span style="color: #660066;">systemChrome</span> <span style="color: #339933;">=</span> air.<span style="color: #660066;">NativeWindowSystemChrome</span>.<span style="color: #660066;">NONE</span>;</pre></div></div>

<p>You might also want to position your notification window in a specific location on the screen.  There are two approaches here.  The first is the <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/system/Capabilities.html">Capabilities</a> class, which through static properties can give you the screen resolution.  If you want to account for the situation where the user has multiple screens, then you will want to use the <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/display/Screen.html">Screen</a> class.  You can access the main screen and get the a <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/geom/Rectangle.html">Rectangle</a> that represents the viewable space (i.e. taking into account the “start bar” on Windows).  If you know how big the screen is, and you know how big your notification window is, you can position it wherever you would like.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> bounds <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
<span style="color: #003366; font-weight: bold;">var</span> screen <span style="color: #339933;">=</span> air.<span style="color: #660066;">Screen</span>.<span style="color: #660066;">mainScreen</span>.<span style="color: #660066;">visibleBounds</span>;
&nbsp;
bounds <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">Rectangle</span><span style="color: #009900;">&#40;</span>
	screen.<span style="color: #660066;">width</span> <span style="color: #339933;">-</span> WINDOW_WIDTH <span style="color: #339933;">-</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">,</span>
	screen.<span style="color: #660066;">height</span> <span style="color: #339933;">-</span> WINDOW_HEIGHT <span style="color: #339933;">-</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">,</span>
	WINDOW_WIDTH<span style="color: #339933;">,</span>
	WINDOW_HEIGHT
<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>At this point, if you went and created a <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/display/NativeWindow.html">native window</a> using the constructor (i.e. new NativeWindow()) then you’d get your window, but it’d have a Flash stage inside of it.  That’s not going to help you use your HTML, JavaScript and CSS any.  HTML applications in Adobe AIR display inside of an <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/html/HTMLLoader.html">HTMLLoader</a> instance.  You can think of this as the browser’s viewport.  The HTMLLoader class actually expects that you’ll want to create new native windows that contain HTML content, and provides a static convenience method to help you out.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> notification <span style="color: #339933;">=</span> air.<span style="color: #660066;">HTMLLoader</span>.<span style="color: #660066;">createRootWindow</span><span style="color: #009900;">&#40;</span> 
	<span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> 
	options<span style="color: #339933;">,</span> 
	<span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span> 
	bounds 
<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>The result of this call is an HTMLLoader instance - specifically, the HTMLLoader instance of the new window you just created.  Keep in mind that it’s the viewport, not the native window itself.  The HTMLLoader has some additional properties that you might want to set as well, especially in the case of a notification window.  The main one is that you will want this notification to always appear over everything else so the user can see it.  That is set by getting a reference to the native window, and then telling it to be “alwaysInFront”.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">notification.<span style="color: #660066;">paintsDefaultBackground</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span>;
notification.<span style="color: #660066;">stage</span>.<span style="color: #660066;">nativeWindow</span>.<span style="color: #660066;">alwaysInFront</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span>;
notification.<span style="color: #660066;">navigateInSystemBrowser</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span>;</pre></div></div>

<p>The “paintsDefaultBackground” is an interesting property as well.  In the case of any native window that is not using the system chrome, you can set the remainder of the window to be transparent.  In the case of HTML, you will also need to tell the HTMLLoader, the browser viewport, not to use the default background of the HTML page that it would otherwise put in place.  You don’t always need to use this option, but it is handy for cases where you want to infer some style through custom chrome.</p>
<p>The window you just created, whether it be a notification window, or other window, is not going to have any default content - it is just a blank window.  The HTMLLoader provides two means to fill that window with content.  The first is simply to send the viewport some HTML to display, which happens through HTMLLoader.loadString( yourHTML ).  This is great for basic markup, but if you’re doing anything extensive, it will obviously get pretty cumbersome.  </p>
<p>The other option then is to have a HTML page assembled that represents what you want your notification window to look like.  You can tell your new native window to display that content by calling HTMLLoader.load() and passing a new <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/net/URLRequest.html">URLRequest</a> object.  The URLRequest is simply a more formal wrapper around a destination to HTML content (content on the web in general, really).  If your notification page is local, then you will use the appropriate notation, just like in any other web page.  You can also point URLRequest at any other location on the web as well.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">notification.<span style="color: #660066;">load</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">URLRequest</span><span style="color: #009900;">&#40;</span> NOTIFY_SOURCE <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #006600; font-style: italic;">// Alternatively</span>
<span style="color: #006600; font-style: italic;">// notification.loadString( &quot;Foo.  Bar.&quot; );</span></pre></div></div>

<p>You’ve finally got your native notification window, sitting pretty where you want it, looking like you want it, and filled with the content you want.  The shortcoming now is that it does not go away all by itself.  What you will need to do is keep track of how long the window has been open, and then tell it to close itself after that period of time has elapsed.  The first question becomes who does the closing?</p>
<p>You have a reference to the native window in the originating application, and you could use that.  In this case you also control what content that window is loading, so you could have the window watch our for itself.  Generally speaking, I prefer the later as it seems more modular to have the notification window take care of dismissing itself.  </p>
<p>The method to do this, regardless of the approach you take is NativeWindow.close().  If you are calling from the originating application, you’ll need to get a reference to the window itself through the HTMLLoader.  Reference the code for setting the window to always be in front, as to how to get this access to the native window.  If you are going to close the window from the page that is loaded, then “nativeWindow” is just another property like the traditional “window” and “document” properties.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// From within the notification window</span>
nativeWindow.<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #006600; font-style: italic;">// Alternatively, from the originating window</span>
<span style="color: #006600; font-style: italic;">// notification.stage.nativeWindow.close();</span></pre></div></div>

<p>Now that you can tell the window to close, you will need to know how long it has been open.  You can use the traditional JavaScript method of <a href="http://www.w3schools.com/js/js_timing.asp">setTimeout()</a> here, which will work perfectly.  Adobe AIR also offers us a more robust <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/utils/Timer.html">Timer</a> class that I prefer to use.  Keep in mind that you may not want to close the window automatically at all.  Maybe you want to leave it on the screen until the user takes some action to dismiss the window.  If that’s the case, don’t forget to include some fashion of button in your HTML page.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> timer <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">Timer</span><span style="color: #009900;">&#40;</span> DELAY<span style="color: #339933;">,</span> REPEAT <span style="color: #009900;">&#41;</span>;
&nbsp;
timer.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">TimerEvent</span>.<span style="color: #660066;">TIMER_COMPLETE</span><span style="color: #339933;">,</span> doTimerComplete <span style="color: #009900;">&#41;</span>;
timer.<span style="color: #660066;">start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> doTimerComplete<span style="color: #009900;">&#40;</span> evt <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	nativeWindow.<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>At this point, you have all the tools you need to get going with your own notification windows.  I have put together a simple example and made the <a href="http://blog.kevinhoyt.org/wp-content/js-notification.zip">source available</a>.  The example creates a notification every ten seconds.  The notification window removes itself after four seconds have elapsed.  My notification window stays where I put it, but from here you might explore other options, such as letting the user move the window, and then remembering where they moved it to to the next notification shows up in the same place.  The options with Adobe AIR, once you’re on the desktop and out of the browser are limitless.</p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2008/12/15/notification-windows-with-javascript-and-air/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using the System Tray from JavaScript with AIR</title>
		<link>http://blog.kevinhoyt.org/2008/12/15/using-the-system-tray-from-javascript-with-air/</link>
		<comments>http://blog.kevinhoyt.org/2008/12/15/using-the-system-tray-from-javascript-with-air/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 20:47:52 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[AIR]]></category>

		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[HTML]]></category>

		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=288</guid>
		<description><![CDATA[Adobe AIR is designed to be consistent across operating systems.  The result is that AIR applications can also run consistently across operating systems.  The reality however is that there are certainly places that operating systems differ significantly, yet present metaphors that users expect.  Among those more pervasive differences is the Windows system [...]]]></description>
			<content:encoded><![CDATA[<p>Adobe AIR is designed to be consistent across operating systems.  The result is that AIR applications can also run consistently across operating systems.  The reality however is that there are certainly places that operating systems differ significantly, yet present metaphors that users expect.  Among those more pervasive differences is the Windows system tray.  The same metaphor exists, but differently for Mac, and may not exist at all depending on your Linux distribution.  Let’s take a look at what is involved to use JavaScript to interact with the system tray in a cross operating system fashion.<br />
<span id="more-288"></span><br />
<em>Note that just because you can write an AIR application to behave consistently, doesn’t mean that one cannot be written to focus on a specific operating system.  If you chose to leave out support for other operating systems, then be aware that decision may come back to haunt you later.</em></p>
<p>When I set out to build this I did a little searching first and found a Flex example that originated from <a href="http://www.saskovic.com/blog/?p=5">Sasa Radovanovic</a>, and that was updated by <a href="http://www.jeffryhouser.com/index.cfm/2008/1/8/How-do-you-put-an-AIR-App-in-the-System-Tray">Jeff Houser</a> circa the Flex 3 Beta 3 timeline.  What follows is a migration of that work from Flex to JavaScript, with a lot more verbiage around the why and how of the details.  All things considered however, when you develop in AIR, you have many of the same classes available to you in both the Flash world and the JavaScript world.  I encourage you to explore what’s available from both APIs.</p>
<p>When it comes to the system tray, it is generally common to have an icon that represents your application.  This is important as your application itself won’t show up in the “start bar” when it has been minimized.  On Mac, the equivalent is the “dock” and the icon that shows up there is generally the one associated with the application itself.  In both cases, you can actually control at runtime how you want that icon to appear.  With that in mind, let’s first start by loading our own custom icon.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> imgDock <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
&nbsp;
$<span style="color: #009900;">&#40;</span> document <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// Loader to load the icon image</span>
	<span style="color: #006600; font-style: italic;">// Use Loader not HTML image to get at bitmap data (pixels)</span>
	<span style="color: #003366; font-weight: bold;">var</span> loader <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">Loader</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #006600; font-style: italic;">// Handle when the icon image is loaded</span>
	<span style="color: #006600; font-style: italic;">// Load the icon image (in this case local)</span>
	loader.<span style="color: #660066;">contentLoaderInfo</span>.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">Event</span>.<span style="color: #660066;">COMPLETE</span><span style="color: #339933;">,</span> doLoaderComplete <span style="color: #009900;">&#41;</span>;
	loader.<span style="color: #660066;">load</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">URLRequest</span><span style="color: #009900;">&#40;</span> SPLASH_IMAGE <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #006600; font-style: italic;">// Custom event handler for window closing</span>
	<span style="color: #006600; font-style: italic;">// Want to prompt the user to see if they want to close or minimize</span>
	nativeWindow.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">Event</span>.<span style="color: #660066;">CLOSING</span><span style="color: #339933;">,</span> doClosing <span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>You might initially be inclined to use an IMG tag.  The problem with this approach is that it doesn’t give you access to the raw pixel data that the operating system will expect.  To get at this data we will use an instance of the Loader class.  Like most things web, the loader works asynchronously, so we will want to register for notification when the icon is loaded.  Since this is local (in this case) it should be nearly instantaneous, but still we need to wait at least that instant.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Called when the icon image is loaded</span>
<span style="color: #006600; font-style: italic;">// Setup systray/dock actions depending on operating system</span>
<span style="color: #003366; font-weight: bold;">function</span> doLoaderComplete<span style="color: #009900;">&#40;</span> evt <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> isMac <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
&nbsp;
	<span style="color: #006600; font-style: italic;">// Get the bitmap data (pixels) of the icon for the system</span>
	<span style="color: #006600; font-style: italic;">// The system will size and convert to the appropriate format</span>
	imgDock <span style="color: #339933;">=</span> evt.<span style="color: #660066;">target</span>.<span style="color: #660066;">content</span>.<span style="color: #660066;">bitmapData</span>;
&nbsp;
	<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">NativeApplication</span>.<span style="color: #660066;">supportsSystemTrayIcon</span> <span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// Setup Windows specific system tray functionality</span>
		air.<span style="color: #660066;">NativeApplication</span>.<span style="color: #660066;">nativeApplication</span>.<span style="color: #660066;">icon</span>.<span style="color: #660066;">tooltip</span> <span style="color: #339933;">=</span> SYSTRAY_TOOLTIP;
		air.<span style="color: #660066;">NativeApplication</span>.<span style="color: #660066;">nativeApplication</span>.<span style="color: #660066;">icon</span>.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">MouseEvent</span>.<span style="color: #660066;">CLICK</span><span style="color: #339933;">,</span> doTrayClick <span style="color: #009900;">&#41;</span>;		
&nbsp;
		isMac <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span>;
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		isMac <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// Override the default minimize behavior and use our own</span>
	nativeWindow.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">NativeWindowDisplayStateEvent</span>.<span style="color: #660066;">DISPLAY_STATE_CHANGING</span><span style="color: #339933;">,</span> doStateChange <span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #006600; font-style: italic;">// Setup a menu on the docked icon to restore or close</span>
	air.<span style="color: #660066;">NativeApplication</span>.<span style="color: #660066;">nativeApplication</span>.<span style="color: #660066;">icon</span>.<span style="color: #660066;">menu</span> <span style="color: #339933;">=</span> createMenu<span style="color: #009900;">&#40;</span> isMac <span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Once our icon has been loaded, we will go ahead and get the pixels, referred to as bitmap data, of the image.  We’ll store that in a reference for later use - specifically, we will show the icon in the system tray when the application is minimized and remove it when the window is restored.  We’ll also want to put the icon back should the application window be minimized again.  </p>
<p>What comes next is the main branch between Windows and Mac, and AIR gives you hooks to find out on which operating system your application is running.  The <a href="http://help.adobe.com/en_US/AIR/1.5/jslr/flash/desktop/NativeApplication.html">NativeApplication</a> class has a static property for “supportsSystemTrayIcon” and “supportsDockIcon” which represents Windows and Mac respectively.  There are also many other useful properties on the NativeApplication class to include a check for menu support, and the flag to start the application when the user logs into the system.</p>
<p>If the application is running on a Windows operating system, then there are some additional options that we can leverage.  Notably in this case are putting a tooltip on the system tray icon, and also listening for a click on the icon to restore the application window.  Regardless of operating system, we want to catch a minimize gesture from the user and replace the default behavior with our own; namely minimize to the system tray and not the “start bar”.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Called when the docked icon is clicked (Windows only)</span>
<span style="color: #006600; font-style: italic;">// Calls a shared function to restore the window</span>
<span style="color: #003366; font-weight: bold;">function</span> doTrayClick<span style="color: #009900;">&#40;</span> evt <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	undock<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;	
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Called when the window is minimized</span>
<span style="color: #006600; font-style: italic;">// Minimizes to systray/dock in place of traditional minimize</span>
<span style="color: #003366; font-weight: bold;">function</span> doStateChange<span style="color: #009900;">&#40;</span> evt <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> evt.<span style="color: #660066;">afterDisplayState</span> <span style="color: #339933;">==</span> air.<span style="color: #660066;">NativeWindowDisplayState</span>.<span style="color: #660066;">MINIMIZED</span> <span style="color: #009900;">&#41;</span> 
	<span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// Stop the default behavior</span>
		<span style="color: #006600; font-style: italic;">// Call shared function to systray/dock</span>
		evt.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
		dock<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>	
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>While we are at it, we will go ahead and create the menu on the system tray/dock icon for the application on the whole.  I’ve made the effort here to track the operating system when I create the menu.  This is subtle but important.  In the case of Windows the common term to close an application is “Exit” while on a Mac the term is “Quit”.  The menu items create here can call the same functionality, that part doesn’t differ per OS, but I wanted to present the user with terminology they’d expect to encounter.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Called to create a menu on the systray/dock icon</span>
<span style="color: #006600; font-style: italic;">// Takes operating system into consideration</span>
<span style="color: #003366; font-weight: bold;">function</span> createMenu<span style="color: #009900;">&#40;</span> isMac <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> menu <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">NativeMenu</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #003366; font-weight: bold;">var</span> openItem <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">NativeMenuItem</span><span style="color: #009900;">&#40;</span> OPEN_ITEM <span style="color: #009900;">&#41;</span>;
	<span style="color: #003366; font-weight: bold;">var</span> exitItem <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
&nbsp;
	<span style="color: #006600; font-style: italic;">// Both operating systems have an option to open the window</span>
	openItem.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">Event</span>.<span style="color: #660066;">SELECT</span><span style="color: #339933;">,</span> doOpenSelect <span style="color: #009900;">&#41;</span>;	
	menu.<span style="color: #660066;">addItem</span><span style="color: #009900;">&#40;</span> openItem <span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span>isMac <span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// Mac provides built-in &quot;Quit&quot; item</span>
		<span style="color: #006600; font-style: italic;">// Create an &quot;Exit&quot; item for Windows</span>
		exitItem <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">NativeMenuItem</span><span style="color: #009900;">&#40;</span> EXIT_ITEM <span style="color: #009900;">&#41;</span>;		
		menu.<span style="color: #660066;">addItem</span><span style="color: #009900;">&#40;</span> exitItem <span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000066; font-weight: bold;">return</span> menu;	
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Before we talk about the actions in those specific menu items, let’s pause and talk about what the application has done so far, and is now displaying.  </p>
<p>When the application started, it loaded a custom icon to use in the system tray/dock.  Once that icon was loaded, we grabbed the bitmap data for reference, and then proceeded to create platform-specific hooks for the application when hidden; namely the menu.  Now the application is running, displaying it’s main window, and expecting some fashion of user interaction.  Let’s say the user is next ready to minimize the application.</p>
<p>Keeping in mind that we want this application to sit in the system tray/dock, not on the “start bar” we want to catch the default behavior and insert our own.  We’ve already setup the application even handlers for minimize, so let’s take a closer look at the actual functionality.  The first step is to prevent the actual minimize behavior, which can be done with the preventDefault() function call.  Then to formally “dock” the application, we hide the main window, and associate the icon we loaded earlier with the application.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Called to put the window on the systray/dock</span>
<span style="color: #006600; font-style: italic;">// Hides window and puts icon in place</span>
<span style="color: #003366; font-weight: bold;">function</span> dock<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	nativeWindow.<span style="color: #660066;">visible</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span>;
	air.<span style="color: #660066;">NativeApplication</span>.<span style="color: #660066;">nativeApplication</span>.<span style="color: #660066;">icon</span>.<span style="color: #660066;">bitmaps</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span>imgDock<span style="color: #009900;">&#93;</span>;	
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Note that AIR can take a variety of sizes for the icon, and that they may differ depending on operating system.  On Windows as an example, this icon tends to be displayed at 16&#215;16.  On a Mac it is very user-definable and may be anywhere between 16&#215;16 and 128&#215;128.  You may want to account for this to get the best display for your icon, but when in doubt, the operating system will actually scale the icon image appropriately.</p>
<p>Now with the application safely tucked away, the user can continue on along with their business.  At some point in the future we’ll assume that they want to bring your application back front and center however, and we’ve already laid the groundwork to make this happen.  On Windows, clicking the system tray icon will “undock” the application, while selecting the “Open” context menu item on both Windows and Mac will perform the same function.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Called to restore the window to normal mode</span>
<span style="color: #006600; font-style: italic;">// Shared function called by multiple event handlers</span>
<span style="color: #003366; font-weight: bold;">function</span> undock<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #006600; font-style: italic;">// Show the window and bring it to the front</span>
	nativeWindow.<span style="color: #660066;">visible</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span>;
	nativeWindow.<span style="color: #660066;">orderToFront</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #006600; font-style: italic;">// Clear out the systray/dock icon (optional)</span>
	air.<span style="color: #660066;">NativeApplication</span>.<span style="color: #660066;">nativeApplication</span>.<span style="color: #660066;">icon</span>.<span style="color: #660066;">bitmaps</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span>;	
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>In the case of restoring the application window to it’s former glory, we’ll first want to make it visible.  To make sure the user isn’t blocking our newly visible window with one of their own, we’ll also want to bring our application to the front.  Finally we’ll pull any custom icon indicator from the application.  On Windows this will remove the icon from the system tray while the window is visible.  </p>
<p>You may want to keep the icon in the system tray at all times regardless of state, in which case you’ll not clear the icon.  You’d also likely not wait to put the icon in place for when the user minimized the application, and make the assignment as soon as the image is loaded.  The real detail here is that AIR doesn’t presume to know how your application should behave.  You need to design the behavior you want, while also taking into consideration operating system differences.</p>
<p>Now your user can start the application, “dock” the main window to the system tray, and restore the window through some user gesture (which again is going to differ depending on operating system).  How about closing your application once and for all?</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Called when the native window is starting to close</span>
<span style="color: #006600; font-style: italic;">// Prompts the user to see if they want to close or minimize</span>
<span style="color: #003366; font-weight: bold;">function</span> doClosing<span style="color: #009900;">&#40;</span> evt <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> answer <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
&nbsp;
	<span style="color: #006600; font-style: italic;">// Stop the default of actually closing the window</span>
	evt.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #006600; font-style: italic;">// Ask the user what action to take</span>
	answer <span style="color: #339933;">=</span> <span style="color: #000066;">confirm</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">&quot;Select <span style="color: #000099; font-weight: bold;">\&quot;</span>OK<span style="color: #000099; font-weight: bold;">\&quot;</span> to exit or <span style="color: #000099; font-weight: bold;">\&quot;</span>Cancel<span style="color: #000099; font-weight: bold;">\&quot;</span> to minimize.&quot;</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> answer <span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// If they actually want to close the application</span>
		closeApplication<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;		
	<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">// If they really just want to minimize the window</span>
		dock<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;	
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>One of the lines of code we didn’t talk about up front was that we added a listener to the native window to catch the closing event.  This happens before the window is actually closed, and gives us a chance to more formally handle the event.  In this case, we will ask the user if they are sure they want to close.  This is a good practice since the user may not know what gesture to provide to actually put the application into the system tray/dock.</p>
<p>Very much like the minimize event, we can prevent the default behavior by calling preventDefault().  Next we can use the good old JavaScript confirm() method to ask the user about their real intentions.  If they really want to close the application, then we’ll go ahead and make that call at the application level.  If they actually want to put the application into the system tray/dock, then we’ll call the “dock” method we discussed earlier during the minimize operation.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Called to close the window</span>
<span style="color: #006600; font-style: italic;">// Shared by multiple event handlers</span>
<span style="color: #003366; font-weight: bold;">function</span> closeApplication<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	nativeWindow.<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;	
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>As a summary, we first need to manage a custom icon, potentially at different sizes based on operating system, create the appropriate context menus for the application, and stop some of the default behavior and inject our own.  </p>
<p>While that’s it in a nutshell, the variables get involved in how you want your application to behave when running on different operating systems.  When does the icon get generated or put into the system tray?  What should the context menu say to the user?  How should the prompt to stop closing be worded depending on OS?  These are all decision you will need to consider as you implement your own approach to docking.  I’ve included a <a href="http://blog.kevinhoyt.org/wp-content/js-system-tray.zip">sample application</a> with the above behaviors for your use as a template.</p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2008/12/15/using-the-system-tray-from-javascript-with-air/feed/</wfw:commentRss>
		</item>
		<item>
		<title>More on Thumbnail Generation with AIR</title>
		<link>http://blog.kevinhoyt.org/2008/12/02/more-on-thumbnail-generation-with-air/</link>
		<comments>http://blog.kevinhoyt.org/2008/12/02/more-on-thumbnail-generation-with-air/#comments</comments>
		<pubDate>Tue, 02 Dec 2008 19:47:33 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[AIR]]></category>

		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[HTML]]></category>

		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=283</guid>
		<description><![CDATA[In a previous post I described a process for analyzing the image type and dimensions of image files (PNG, JPEG, GIF) without having to actually display the image, or load it onto the Flash display list.  It was called to my attention that the post did not also include image sizing, or generating thumbnails. [...]]]></description>
			<content:encoded><![CDATA[<p>In a previous post I described a process for analyzing the image type and dimensions of image files (PNG, JPEG, GIF) without having to actually display the image, or load it onto the Flash display list.  It was called to my attention that the post did not also include image sizing, or generating thumbnails.  While I want to cover an example of this, I think it also makes for an interesting discussion on image processing in general and <a href="http://www.adobe.com/go/air">Adobe AIR</a>.<br />
<span id="more-283"></span><br />
You can obviously do a lot with image files using Adobe AIR, especially those parts that leverage the Flash Player features, or canvas features in HTML.  The problem with all the amazing visuals we see with these technologies is that the content has been specifically loaded into memory and dropped onto the display list.  While that works for known content, it doesn’t scale well for two reasons.  The first is that it consumes memory, and the second is that images are regularly larger than Flash itself can handle.</p>
<p>Yes, the Flash Player has a limitation in the dimensions of the main rendering pipeline called the “stage”.  The stage cannot exceed 8,192 pixels in either width or height, and the total number of pixels cannot be more than 16,777,216.  This is especially important if you’re interested in image transformations, and aren’t directly familiar with the dimensions of that content.  If the single item you load on the stage exceeds the stage dimension limitations, it won’t be displayed - and you need it to be displayed in order to apply transformations in this manner.  Take for example something coming out of the latest digital SLR cameras.</p>
<p>You see, if all you want is to generate a thumbnail of an image file, with AIR, you’ll still have to load it entirely into memory and onto the display list.  Then you’ll capture a copy of the bitmap data that represents that image.  At that point, the classes are in place to provide a variety of scaling and/or other effects.  Once you’ve got it all figured out, you’ll want to encode those bytes into a recognizable format.  This in it’s own right is going to take time (in addition to the memory you’re already consuming).  Then you get to write the encoded file to disk, which thanks to AIR can be done asynchronously, keeping your user interface responsive.</p>
<p>Should there be alternatives?  You bet!  And there has been for about as long as image files have been around.</p>
<p>The alternative is to directly manipulate the bytes of the image itself while you’re processing.  This is especially effective for image that you want to scale down, removing bytes along the way.  This is the road my previous post started down.  It reads bytes to determine the specifics.  It does not load the images onto the display list.  Getting dimensions and file type this way however, is significantly easier than applying actual transformations.  The scope of that work is beyond my skills, and really should use the native libraries that already exist to do this work.  And therein lies the rub as AIR doesn’t provide native extensibility.</p>
<p>The rest of this post goes to a brief description of how to read in, and scale, multiple images selected by the user.  Before I go there however, note that Adobe recently announce <a href="http://labs.adobe.com/technologies/alchemy/">Project Alchemy</a> which compiles C/C++ source code to Flash bytecode.  It stands to reason that these libraries could be compiled to Flash SWC libraries, and then image files could be manipulated directly at the byte level without loading onto the display list.  To date however, this work has not yet been completed.</p>
<p><strong>Selecting, Loading, Resizing and Writing Images</strong></p>
<p>The first objective here is simply to let the user select one or more images.  To do this we’ll prepare a file object instance to handle user interaction.  We’ll also listen on a button in the HTML page for the user to invoke the selection dialog.  When the files are selected, there’s a little trick to handling what the user has selected.  The main problem is that if they’ve selected more than one, we can’t work on them all simultaneously because all the processes happen asynchronously to emulate threading.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> browse <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
<span style="color: #003366; font-weight: bold;">var</span> files <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
<span style="color: #003366; font-weight: bold;">var</span> index <span style="color: #339933;">=</span> 0;
<span style="color: #003366; font-weight: bold;">var</span> loader <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
<span style="color: #003366; font-weight: bold;">var</span> output <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> doLoad<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  browse <span style="color: #339933;">=</span> air.<span style="color: #660066;">File</span>.<span style="color: #660066;">documentsDirectory</span>;	
  browse.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">FileListEvent</span>.<span style="color: #660066;">SELECT_MULTIPLE</span><span style="color: #339933;">,</span> doFilesSelect <span style="color: #009900;">&#41;</span>;
&nbsp;
  loader <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">Loader</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
  loader.<span style="color: #660066;">contentLoaderInfo</span>.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> air.<span style="color: #660066;">Event</span>.<span style="color: #660066;">COMPLETE</span><span style="color: #339933;">,</span> doLoaderComplete <span style="color: #009900;">&#41;</span>;
  window.<span style="color: #660066;">nativeWindow</span>.<span style="color: #660066;">stage</span>.<span style="color: #660066;">addChild</span><span style="color: #009900;">&#40;</span> loader <span style="color: #009900;">&#41;</span>;
&nbsp;
  btnOpen.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> doOpenClick <span style="color: #009900;">&#41;</span>;	
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> doFilesSelect<span style="color: #009900;">&#40;</span> e <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  files <span style="color: #339933;">=</span> e.<span style="color: #660066;">files</span>;
  index <span style="color: #339933;">=</span> 0;
&nbsp;
  loadImages<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> doOpenClick<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>	
  browse.<span style="color: #660066;">browseForOpenMultiple</span><span style="color: #009900;">&#40;</span> 
    <span style="color: #3366CC;">'Select Images'</span><span style="color: #339933;">,</span> 
    <span style="color: #009900;">&#91;</span><span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">FileFilter</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Image Files'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'*.gif;*.jpg;*.jpeg;*.png'</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span> 
  <span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This means that we’ll need to work on each individual image in turn.  To keep track of what file in the list of those selected that we’re currently processing, make sure you store and index at a scope that can be repeatedly accessed.  Now that we can process the images in turn, lets next actually load the image.  To complicate matters, image loading occurs asynchronously as well.  Not only will this trigger when to scale the image, it will also fire the next iteration in our list.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> COMPRESSION <span style="color: #339933;">=</span> <span style="color: #CC0000;">85</span>;
<span style="color: #003366; font-weight: bold;">var</span> MAX_HEIGHT <span style="color: #339933;">=</span> <span style="color: #CC0000;">100</span>;
<span style="color: #003366; font-weight: bold;">var</span> MAX_WIDTH <span style="color: #339933;">=</span> <span style="color: #CC0000;">100</span>;
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> loadImages<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> index <span style="color: #339933;">&lt;</span> files.<span style="color: #660066;">length</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    output <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'div'</span> <span style="color: #009900;">&#41;</span>;
    loader.<span style="color: #660066;">load</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">URLRequest</span><span style="color: #009900;">&#40;</span> files<span style="color: #009900;">&#91;</span>index<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">url</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;	
  <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
    loader.<span style="color: #660066;">visible</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span>;
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> doLoaderComplete<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> bmp <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
  <span style="color: #003366; font-weight: bold;">var</span> bmpd <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
  <span style="color: #003366; font-weight: bold;">var</span> encoder <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
  <span style="color: #003366; font-weight: bold;">var</span> img <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
  <span style="color: #003366; font-weight: bold;">var</span> jpg <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
  <span style="color: #003366; font-weight: bold;">var</span> matrix <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
  <span style="color: #003366; font-weight: bold;">var</span> ratio <span style="color: #339933;">=</span> 0;
  <span style="color: #003366; font-weight: bold;">var</span> realHeight <span style="color: #339933;">=</span> loader.<span style="color: #660066;">contentLoaderInfo</span>.<span style="color: #660066;">height</span>;	
  <span style="color: #003366; font-weight: bold;">var</span> realWidth <span style="color: #339933;">=</span> loader.<span style="color: #660066;">contentLoaderInfo</span>.<span style="color: #660066;">width</span>;
  <span style="color: #003366; font-weight: bold;">var</span> stream <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
  <span style="color: #003366; font-weight: bold;">var</span> thumb <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span>;
  <span style="color: #003366; font-weight: bold;">var</span> thumbHeight <span style="color: #339933;">=</span> 0;
  <span style="color: #003366; font-weight: bold;">var</span> thumbWidth <span style="color: #339933;">=</span> 0;
&nbsp;
  <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> realWidth <span style="color: #339933;">&gt;</span> realHeight <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    thumbWidth <span style="color: #339933;">=</span> MAX_WIDTH;
    thumbHeight <span style="color: #339933;">=</span> Math.<span style="color: #660066;">round</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span> MAX_WIDTH <span style="color: #339933;">/</span> realWidth <span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> realHeight <span style="color: #009900;">&#41;</span>;
    ratio <span style="color: #339933;">=</span> MAX_WIDTH <span style="color: #339933;">/</span> realWidth;
  <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
    thumbHeight <span style="color: #339933;">=</span> MAX_HEIGHT;
    thumbWidth <span style="color: #339933;">=</span> Math.<span style="color: #660066;">round</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span> MAX_HEIGHT <span style="color: #339933;">/</span> realHeight <span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> realWidth <span style="color: #009900;">&#41;</span>;
    ratio <span style="color: #339933;">=</span> MAX_HEIGHT <span style="color: #339933;">/</span> realHeight;		
  <span style="color: #009900;">&#125;</span>
&nbsp;
  matrix <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">Matrix</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
  matrix.<span style="color: #660066;">scale</span><span style="color: #009900;">&#40;</span> ratio<span style="color: #339933;">,</span> ratio <span style="color: #009900;">&#41;</span>;
&nbsp;
  bmpd <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">BitmapData</span><span style="color: #009900;">&#40;</span> thumbWidth<span style="color: #339933;">,</span> thumbHeight <span style="color: #009900;">&#41;</span>;	
  bmpd.<span style="color: #660066;">draw</span><span style="color: #009900;">&#40;</span> loader<span style="color: #339933;">,</span> matrix<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
  encoder <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> runtime.<span style="color: #660066;">com</span>.<span style="color: #660066;">adobe</span>.<span style="color: #660066;">images</span>.<span style="color: #660066;">JPGEncoder</span><span style="color: #009900;">&#40;</span> COMPRESSION <span style="color: #009900;">&#41;</span>;
  jpg <span style="color: #339933;">=</span> encoder.<span style="color: #660066;">encode</span><span style="color: #009900;">&#40;</span> bmpd <span style="color: #009900;">&#41;</span>;
&nbsp;
  thumb <span style="color: #339933;">=</span> air.<span style="color: #660066;">File</span>.<span style="color: #660066;">desktopDirectory</span>.<span style="color: #660066;">resolvePath</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'thumb_'</span> <span style="color: #339933;">+</span> files<span style="color: #009900;">&#91;</span>index<span style="color: #009900;">&#93;</span>.<span style="color: #000066;">name</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
  stream <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> air.<span style="color: #660066;">FileStream</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
  stream.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span> thumb<span style="color: #339933;">,</span> air.<span style="color: #660066;">FileMode</span>.<span style="color: #000066; font-weight: bold;">WRITE</span> <span style="color: #009900;">&#41;</span>;
  stream.<span style="color: #660066;">writeBytes</span><span style="color: #009900;">&#40;</span> jpg<span style="color: #339933;">,</span> 0<span style="color: #339933;">,</span> 0 <span style="color: #009900;">&#41;</span>;
  stream.<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
  output.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> files<span style="color: #009900;">&#91;</span>index<span style="color: #009900;">&#93;</span>.<span style="color: #000066;">name</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">': '</span> <span style="color: #339933;">+</span> realWidth <span style="color: #339933;">+</span> <span style="color: #3366CC;">' x '</span> <span style="color: #339933;">+</span> realHeight;
  document.<span style="color: #660066;">body</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span> output <span style="color: #009900;">&#41;</span>;
&nbsp;
  img <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'img'</span> <span style="color: #009900;">&#41;</span>;
  img.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> thumb.<span style="color: #660066;">url</span>;
  output.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span> img <span style="color: #009900;">&#41;</span>;
&nbsp;
  index <span style="color: #339933;">=</span> index <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span>;
  loadImages<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>In this example, I’ve chosen to write the image files synchronously.  It’s very easy and simple code, but I’m making a huge assumption - that the files to write are small and/or are not being written on a network drive.  If either of these problems should creep up, we’ll need to introduce one more asynchronous flow.  This means that the close the file, after being written, would actually trigger the next iteration.  Now you’re talking nested asynchronous processes on an unknown list of files.  It only gets more messy if you’re also concerned that the extension “JPEG” that the user selected, is actually a JPEG file and not a “DOC” with the wrong extension.</p>
<p>Bringing this full circle, this is where we come back to native libraries.  Between all the potential memory and processing pitfalls, image processing proper in AIR is a little hit and miss.  It’s good for basics, but will certainly fail you when you start pushing the envelope.  Project Alchemy certainly is a promising light at the end of the tunnel for these purposes.  To make it even more exciting, Alchemy is capable of processing data across frame boundaries.  Frame boundaries?  Yeah, well, let’s not go there; the rabbit hole gets very deep indeed.  In the meantime here&#8217;s <a href="http://blog.kevinhoyt.org/wp-content/thumbnails-revisited.zip">the source</a> for a simple AIR application that does the resizing covered above.</p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2008/12/02/more-on-thumbnail-generation-with-air/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MAX 2008 Review and Content</title>
		<link>http://blog.kevinhoyt.org/2008/11/25/max-2008-review-and-content/</link>
		<comments>http://blog.kevinhoyt.org/2008/11/25/max-2008-review-and-content/#comments</comments>
		<pubDate>Tue, 25 Nov 2008 04:19:39 +0000</pubDate>
		<dc:creator>Kevin Hoyt</dc:creator>
		
		<category><![CDATA[AIR]]></category>

		<category><![CDATA[ActionScript]]></category>

		<category><![CDATA[ColdFusion]]></category>

		<category><![CDATA[Conferences]]></category>

		<category><![CDATA[Flash]]></category>

		<category><![CDATA[Flex]]></category>

		<category><![CDATA[LiveCycle]]></category>

		<guid isPermaLink="false">http://blog.kevinhoyt.org/?p=279</guid>
		<description><![CDATA[Well, another MAX North America has come and gone.  In general, my perceptions of this year’s event puts it at among the best we have ever been able to put on - going back to Allaire, and Dev Con in Washington, D.C.  Certainly, no event with record attendance of over 5,000 is going [...]]]></description>
			<content:encoded><![CDATA[<p>Well, another <a href="http://max.adobe.com">MAX North America</a> has come and gone.  In general, my perceptions of this year’s event puts it at among the best we have ever been able to put on - going back to Allaire, and Dev Con in Washington, D.C.  Certainly, no event with record attendance of over 5,000 is going to please everybody, but the MAX team came really close.  I had a total of six hands-on labs presentations, and an unconference presentation as well.  Needless to say, I kept busy.  Here’s a few thoughts on MAX 2008, as well as descriptions and content for my sessions. <br />
<span id="more-279"></span><br />
<strong>MAX Review</strong></p>
<p>The MAX team has already announced that they’d like your <a href="http://onflash.org/ted/2008/11/maxowg-how-was-max-na.php">feedback in the guidance of 2009</a>.  I don’t know that I’ve ever seen a conference of this scale organized in public, but I complement their vision.  Some of the reviews early in to that process talk about presenters that seemed unprepared and criticism on the unconference events.  I’d like to call out a few thoughts on these comments.</p>
<p>Presenters were kept to a strict timeline this year.  The first scheduled review of content was scheduled on July 18, 2008.  That’s a full four (4) months ahead of the actual event.  That’s not to mention the actual call for papers.  Final content was due September 29, 2008; almost two months before the event.  Imagine then, preparing a presentation today, and then being expected to deliver it perfectly two months later, right out of the gate.  If you did well on your content, your first delivery might be four months later!</p>
<p>I guess the point is that if the presenters seemed a bit rough on the first day, there’s a reason.  I know I felt a bit rough.  That being said, as a lab presenter, I was ecstatic to have been able to work with the actual VMWare image as part of the preparation process.  Usually you just hand the assets over and hope everything works out as you hoped.  I was able to significantly refine my presentations over the course of MAX because I knew my assets on the actual machines of the students.  Easily my favorite part of the preparation process.</p>
<p>As for the unconferences, I only attended and presented at the <a href="http://www.coldfusionjedi.com/page.cfm/ColdFusion-Unconference">CF Unconference</a>, but I thought it was a great place to talk about those thing that mattered to you.  If you’ve ever been to a barcamp or other unconference, the agenda is usually set as part of the opening hours of the event.  Unconferences aren’t supposed to be formal events like MAX itself, <a href="http://www.360conferences.com/360flex/">360Flex</a>, or others.  The thing I really like about an unconference is that I can experiment with new content and content that is maybe too off-track for a typical conference, I thought MAX fit that ideal perfectly.</p>
<p>Conversely, I was a bit let down that the unconferences got so little support.  At the CF Unconference as an example, the only way the group would get lunch was to pay for it themselves.  Yes, I understand that a typical unconference gets no support whatsoever, but if you’re giving space and equipment, then the MAX staff should at least also pitch in lunch.  Keep in mind that you didn’t need a badge to attend a MAX unconference, so I appreciate the balancing act from the MAX staff, but no lunch?</p>
<p>As for MAX overall?  Yes, wireless access was abysmal!  I’m still not sure why conferences, especially conferences in Silicon Valley continue to mess this up.  Attendees want to blog, upload pictures, Twitter, share video and more.  No network equals no sharing.  No sharing means less community feel, and less excitement from those that couldn’t make the trip.  Next year is Los Angeles, CA.  Please, give us decent wireless!</p>
<p><strong>Real-Time ColdFusion with LiveCycle Data Services </strong></p>
<p>This is easily one of my favorite subjects.  So many ColdFusion developers I talk to are still using XML over HTTP for their Flex applications.  A very few have made their way to CFCs and remote objects.  Both of those are the very tip of the iceberg!  There’s so much more you can do if you embrace the <a href="http://www.adobe.com/products/livecycle/dataservices/">LiveCycle Data Services</a> that’s included with your <a href="http://www.adobe.com/products/coldfusion/">ColdFusion 8</a> installation.  That’s what this session was all about.</p>
<p>We started with remoting, just to level-set the workflow of connecting <a href="http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK">Flex</a> to data from ColdFusion.  I was pleasantly surprised to find a number of the attendees were entirely new to Flex and <a href="http://www.adobe.com/products/flex/features/flex_builder/">Flex Builder</a>.  From there we moved into the world of asynchronous communications with a chat application (yes, I know it’s cliche).  To show data push, we implemented a ColdFusion Gateway that leveraged threading (introduced in ColdFusion <img src='http://blog.kevinhoyt.org/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> and emulated a long-running server transaction.  We capped off the lab by talking about the possibilities and short-comings of all these by themselves, and rocked the house with data management.</p>
<p><strong>AIR Core Concepts for Flash Developers</strong></p>
<p>When Rob Christensen, the AIR Product Manager, asked if I’d be open to presenting a session, I was quick to accept.  Having spent my fair share of time in the Flash authoring environment in the past, I thought the topic was very compelling.  The lab consisted of six hands-on projects, executed with varying degrees of success throughout the week.  I hadn’t considered that a number of the students wouldn’t have had any ActionScript experience whatsoever.  I tried diligently, using the assets shipped months earlier on the VM Ware image, to adjust throughout the week, but to varying degrees of success.</p>
<p>The projects in the lab started with exploring how to create an <a href="http://www.adobe.com/go/air">Adobe AIR</a> application using <a href="http://www.adobe.com/products/flash/">Flash CS4</a>, or the extension available for Flash CS3.  From there we moved into local file IO with a basic text editor.  Exploring the embedded <a href="http://www.sqlite.org/">SQLite</a> database was next with a basic contact manager.  We talked about the differences between an actual browser and the HTML rendering engine (using <a href="http://webkit.org/">WebKit</a>) while making our own loosely formed version.  From there we shifted into <a href="http://www.adobe.com/products/flashplayer/">Flash Player 10</a> features, as a major part of the Adobe AIR 1.5 release announced at MAX 2008.  We leveraged the new text engine and 3D, before circling back around for deploying an AIR application.</p>
<p><strong>ColdFusion Unconference: LCDS, Threading, Gateways and More</strong></p>
<p>The data push I showed in my Real-Time ColdFusion lab was very formal and very abbreviated over what I actually wanted to show.  I used the CF Unconference as my opportunity to explore the full story.  That story starts with a simple Flex application to manage GPS data.  The problem was that uploading a large data set took time, and I felt uninformed.  I wanted to push updates while the database inserts were actually being executed.  From there I needed threads to separate the processing against the actual upload.  Further on I need to use gateways to push data from the ColdFusion server into the LiveCycle Data Services instance.</p>
<p>The morning of the unconference I also got permission to show ColdFusion in the cloud on <a href="http://aws.amazon.com/ec2/">Amazon EC2</a> via <a href="http://www.stax.net">Stax</a>.  Stax is an upstart that is in part run by the legendary Spike Washburn, who you’ll recall if you were around during the ColdFusion 5 to ColdFusion 6 migration (native to Java).  The part of Stax that makes it so exceptionally compelling is that it has an SDK that makes developing on ColdFusion, exactly like developing on ColdFusion locally.  That means you can use all your normal tools and workflows during development.  I can’t explain the details on this exactly now, but watch for more information as Stax and Adobe figure out the details (such a licensing).</p>
<p><strong>Conclusion</strong></p>
<p>No conference is without it’s flaws, but MAX 2008 was about as exceptional a conference as ever I’ve attended; and given that I attend and present at conferences for a living, that’s saying something.  I think being open about the 2009 details will aid significantly in making it even better.  I had a ton of labs sessions, and presented at the ColdFusion Unconference.  All those presentations, and their code, can be downloaded for your viewing pleasure (<a href="http://blog.kevinhoyt.org/wp-content/real-time-cf.zip">Real-Time ColdFusion</a>, <a href="http://blog.kevinhoyt.org/wp-content/air-core-concepts.zip">AIR Core Concepts</a>, <a href="http://blog.kevinhoyt.org/wp-content/cf-unconference.zip">ColdFusion Unconference</a>).  I’m not sure what Los Angeles holds for us, but I’m super excited about the 2009 year ahead.  Thanks everybody for such a great event!</p>
<noscript>Tags:<a href="http://www.saveonrefinance.com" title="Current Mortgage Rates">Current Mortgage Rates</a></noscript>]]></content:encoded>
			<wfw:commentRss>http://blog.kevinhoyt.org/2008/11/25/max-2008-review-and-content/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
