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

<channel>
	<title>Sean Monahan &#187; Custom Chrom</title>
	<atom:link href="http://seanmonahan.org/tag/custom-chrom/feed/" rel="self" type="application/rss+xml" />
	<link>http://seanmonahan.org</link>
	<description></description>
	<lastBuildDate>Wed, 07 Dec 2011 04:20:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Beer Near Here Desktop Part 4: Using Custom Chrome</title>
		<link>http://seanmonahan.org/2009/03/10/beer-near-here-desktop-part-4-using-custom-chrome/</link>
		<comments>http://seanmonahan.org/2009/03/10/beer-near-here-desktop-part-4-using-custom-chrome/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 02:31:10 +0000</pubDate>
		<dc:creator>Sean</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[AIR]]></category>
		<category><![CDATA[AIR Skinning]]></category>
		<category><![CDATA[Beer Near Here]]></category>
		<category><![CDATA[Custom Chrom]]></category>

		<guid isPermaLink="false">http://seanmonahan.org/?p=356</guid>
		<description><![CDATA[If you&#8217;ve been reading along you&#8217;ll know that&#8230;I haven&#8217;t posted anything in awhile.  Hopefully this post will make up for that a bit.  Today I&#8217;ll be writing about using custom chrome (sometimes called &#8216;skins&#8217;) with AIR.  A quick Google search will pull up quite a few resources on this but I noticed that most of [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve been reading along you&#8217;ll know that&#8230;I haven&#8217;t posted anything in awhile.  Hopefully this post will make up for that a bit.  Today I&#8217;ll be writing about using custom chrome (sometimes called &#8216;skins&#8217;) with AIR.  A quick Google search will pull up quite a few resources on this but I noticed that most of them were for Flex 2 which is, apparently, quite different from Flex 3 when it comes to AIR.  Also I couldn&#8217;t really find a definitive guide that pulled it all together.  Maybe this post can remedy this situation.</p>
<p><span id="more-356"></span></p>
<p>Before we get started diving into custom chrome you should ask yourself if you really need to use it.  There is a performance cost associated with creating your own custom chrome.  It also takes longer to create custom chrome, so not only will your app be slower, it will take longer to develop.  Additionally (man, I&#8217;m really making custom chrome sound like a bad idea, huh?) making a custom skin for your app may decrease usability as you&#8217;ll be forcing your users to become accustomed to an interfaces that differs from the standard one their OSes present.</p>
<p>So custom chrome may not be a good idea.  Then again, it can really set your app apart and to I&#8217;ve yet to see an AIR app resource-intense enough that the performance penalty for using custom chrome would really matter.  Since you&#8217;re reading this you&#8217;ve probably already decided to go ahead and use a custom skin for you application so let&#8217;s get to it.</p>
<p>The first thing to do is open up your application&#8217;s XML descriptor file.  In this file there are two items of interest so far as chrome is concerned:</p>
<ol>
<li>systemChrome and</li>
<li>transparent</li>
</ol>
<p>SystemChrome is a flag that tells your application to either use the &#8220;standard&#8221; chrome (i.e., the OS&#8217;s chrome) or &#8220;none&#8221;.  Since we want to use custom chrome set this to &#8220;none&#8221;.</p>
<p>Transparent is a flag that sets your application window to be transparent.  It takes a value of &#8220;true&#8221; or &#8220;false&#8221;.  You can only use this when systemChrome is set to none.  If you are going to use an unusual shape for you application, like a beer glass, set this to &#8220;true&#8221; so you won&#8217;t have a square application window floating around.</p>
<p>If you were to run your app at this point you&#8217;d see you still have a title bar with maximize, minimize and close buttons.  If you&#8217;re going custom you probably want to go all out and make your own title bar, or not as you may not even want a traditional title bar.  The chrome you are seeing now is called &#8220;FlexChrome&#8221; and to get rid of it you need to make an edit to your application&#8217;s MXML file.  In the WindowedApplication tag add an attribute, &#8220;showFlexChrome&#8221; and set it to &#8220;false&#8221;:</p>
<pre class="brush: xml; title: ; notranslate">

&lt;WindowedApplication
showFlexChrome=&quot;false&quot;/&gt;
</pre>
<p>When you run your app now you&#8217;ll no longer have a title bar or any maximize, minimize or close buttons.  You also can no longer drag your application.  Using system or Flex chrome offers a lot of functionality for free so we&#8217;ve got some work to do to get it back.  Beer Near Here Desktop does not support maximizing or minimizing so I&#8217;ll only be adding a close button and some drag functionality.  Adding maximize and minimize should work in a similar manner to closing.  But first, we&#8217;ll throw in a background so we have something to look at.</p>
<p>The Beer Near Here Desktop application window is exactly 550 pixels wide and 830 pixels tall.  The background beer glass you see when the app loads is 532 pixels wide and 800 pixels tall.  Why the difference?  When you do a search another image is laid on top of the application, dimming it and effectively disabling most of the buttons.  This overlay image is 550&#215;830 pixels.</p>
<p>So the first thing I did was set the width and height for the entire application in the WindowedApplication tag:</p>
<pre class="brush: xml; title: ; notranslate">

&lt;WindowedApplication
showFlexChrome=&quot;false&quot;
width=&quot;550&quot; height=&quot;830&quot;/&gt;
</pre>
<p>I then added an mx:Image control inside WindowedApplication:</p>
<pre class="brush: xml; title: ; notranslate">

&lt;mx:Image
top=&quot;0&quot; left=&quot;0&quot;
id=&quot;background&quot;
width=&quot;532&quot; height=&quot;800&quot;
source=&quot;images/loading-anim/00.png&quot;/&gt;
</pre>
<p>Running the app now shows a nice glass of beer.  In fact, get a beer now, it&#8217;ll make this more fun.</p>
<p>Okay, I&#8217;m back with my beer <img src='http://seanmonahan.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>So we now have our app running with a custom background image but we can&#8217;t move it or close it.  Well, we can close it, but we have to rely on the OS for that rather than the application itself.  For now you can close the app by either right-clicking the application in the Windows start bar or the Mac OS dock and choosing the close command.  Since the background is in place and it&#8217;s easy to do we&#8217;ll implement some dragging next.</p>
<pre class="brush: jscript; title: ; notranslate">

// This drags your application
NativeApplication.nativeApplication.activeWindow.stage.nativeWindow.stage.nativeWindow.startMove();
</pre>
<p>The above is a nice, long line of Actionscript that will drag your application.  To make use of it you&#8217;ll have to import the flash.desktop.NativeApplication package into your application.  To drag the application we are going to listen for the mouse down event on the background image we added earlier.  To handle this we&#8217;ll need an event listener:</p>
<pre class="brush: jscript; title: ; notranslate">

private function _dragStart(event:MouseEvent):void
{
NativeApplication.nativeApplication.activeWindow.stage.nativeWindow.stage.nativeWindow.startMove();
}
</pre>
<p>Now that we have our event listener we can wire it up to the background image:</p>
<pre class="brush: jscript; title: ; notranslate">

// Add the drag event listener
background.addEventListeners(MouseEvent.MOUSE_DOWN, _dragStart);
</pre>
<p>This wires the mouse down event to call the _dragStart method thus our app will be dragged so long as the mouse button is held down over the app.  Easy enough, right?  There is one slight catch: this only works if the background image is clicked.  This means that if you place another image on top of the background image like I did with the Beer Near Here logo, clicking in the logo area will not initiate a drag &#8212; you&#8217;ll have to add a mouse down event listener to this other image (or whatever you added) as well.  There is a nice part to this as well as transparent areas of the background image do not register clicks.  So, while the application window and background image for BNHD are actually rectangular if you click in the transparent part of the application you&#8217;ll actually click through to whatever is beneath the application.</p>
<p>Taking stock of the situation we have an application with a custom background image that can be dragged by clicking the background and dragging the mouse.  In the final part of this post we&#8217;ll add a close button so we can close the app without relying on the user&#8217;s operating system.  To accomplish this with BNHD I created an ImageButton component which can be found in my <a title="Sean's Flex Library." href="/projects/flex-library/">Flex Library</a> (there is some <a title="Sean's Flex Library Documentation." href="/code/flex/docs/">documentation</a> on this component, hopefully I&#8217;ll have a demo soon-ish).</p>
<p>The ImageButton component is very straightforward: you give it an image for the button, an image for the button&#8217;s hover state and a function to call when it is clicked.  If you don&#8217;t want to use ImageButton you can use any clickable control.  So code for the ImageButton looks like this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;smorg:ImageButton
id=&quot;closeBtn&quot;
image=&quot;@Embed('images/close-btn.png')&quot;
hoverImage=&quot;@Embed('images/close-hover-btn.png')&quot;
click=&quot;_closeApp();&quot;
right=&quot;85&quot; top=&quot;19&quot;
width=&quot;42&quot; height=&quot;42&quot;/&gt;
</pre>
<p>Of interest here is the _closeApp function.  Here&#8217;s the function:</p>
<pre class="brush: jscript; title: ; notranslate">

private function _closeApp()
{
var exitingEvent:Event = new Event(Event.EXITING, false, true);
NativeApplication.nativeApplication.dispatchEvent(exitingEvent);
if (!exitingEvent.isDefaultPrevented())
{
NativeApplication.nativeApplication.exit();
}
}
</pre>
<p>This function creates and dispatches an Event.EXITING event.  This announces our intent to close the application.  The function then checks if the event&#8217;s default behavior is being prevent, that is, is there something else going on with the app that is preventing us from exiting?  BNHD is simple and this case never comes up, but it&#8217;s good to be prepared.  Assuming the default event behavior is not prevented, and it never is, we exit the application.</p>
<p>That&#8217;s the basic rundown of how I setup Beer Near Here Desktop.  Now it is a bit more involved but most of the details are rather specific to BNHD so I don&#8217;t really think they deserve much attention here with two exceptions.  The first is the loading/searching animation that drains the beer glass.  This was a lot of work and I think it turned out awesome.  This will probably be the topic of the next AIR post.</p>
<p>The second is the loading overlay image I mentioned above.  This overlay ended up serving a purpose beyond my initial intent quite nicely.  Originally I planned simply to use it to dim the background while the app was doing any &#8220;thinking&#8221; type operations (loading, searching, et cetera) to draw attention to any pop ups.  It does this well enough but by placing well within the app&#8217;s MXML file I was also able to use it to effectively disable all the controls in the main app window during any thinking operations.</p>
<p>If you load up BNHD and do a search you&#8217;ll see that all of the controls in the main app window become unclickable except for the close button (and, of course, any controls in the popup).  Rather than write a method that enables and disables all these controls I just ordered them within the MXML document such that all of them would be beneath the overlay image except the close button (and popups).  This allows users to exit at any time but not to click buttons they shouldn&#8217;t and cause havoc.  Perhaps a useful trick if you plan to do any custom loading overlays or animations with your application.</p>
<p>Until next time.</p>
<p><a href="/2009/04/07/beer-near-here-part-5-creating-the-art-assets/">Read Part 5</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://seanmonahan.org/2009/03/10/beer-near-here-desktop-part-4-using-custom-chrome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

