Archive for May, 2008

Non Standard (Custom) Window in AIR

Tuesday, May 27th, 2008

Monstagon was wanting to create a custom window for an AIR application at work and could not figure out how to do it. I had found a tutorial that used an apple shaped window, but I seem to have lost the bookmark. So I figured I’ll just post my own tutorial. Since that is what this dang blog is for!

First, create a new AIR application in Flex Builder. I called mine NonStandardGUI, but you can call it “whatever.” Then, open up the app-XML file (”NonStandardGUI-app.xml”) and we will edit the properties here first. This file is loaded automatically and contains all of the basic application properties. Set these properties to

systemChrome = none
transparent = true
visible = false
width = 800
height = 600
x = 100
y = 100
in the “initialWindow” section. The width, height, x and y are optional; you just need to make sure the size is big enough for the background image and the location on the screen allows you to see the whole window.

Now we will edit the NonStandardGUI.mxml (the main application file). To the WindowedApplication, add these attributes

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
        showTitleBar="false" showStatusBar="false"
        backgroundAlpha="0.0" borderThickness="0" >
This gets rid of the window. If you were to save and run the app now it would display nothing.

To add your image as the background, simply an Image tag with the source pointing to the actual image file. For better performance, we want to embed these static images. This could be a PNG, JPG, SWF… So the background can be anything you can create.

<mx:Image id="background" source="@Embed(source='nonStandard_GUI_test.png')" />

With the image in place a a background, you can add all the content you like to it. Due to the nonstandard shape of the new window, laying content out might be a little more time consuming since the Flex Builder Design view doesn’t load the image for you. I have attached the source code for my NonStandard GUI for you to dissect.

Source code: nonstandardgui.zip

New Car Gas Savings

Tuesday, May 20th, 2008

I made a little form to estimate how much I would save if I were to buy a new car vs keeping my current truck. Since I don’t have a car payment, the truck is the winner, but if I did then it will be a closer bet. So here is the little form to calculate if you should get that new Fit. (This isn’t going into how ecofriendly your new car is vs old, just monetary savings.)

The savings is how much I would save if I bought the car. You need to drive a lot and get great gas mileage to compensate for a monthly car payment. Buy I am sure you new that already…

P.S. Here is the formula: (Miles / MPG) * $Gas + Payment = Monthly Cost

KatanPG Uploader Beta 1

Thursday, May 8th, 2008

I made a lot of updates to the KatanaPG picture up-loader. I added a little browser to view your Katana Inbox (where the picture are uploaded to). I could not get the authentication to stay outside of the AIR program; meaning, the AIR browser keeps you logged in or you can use your normal browser and have to login again. The browser will automatically pop up once your upload finishes or after you login and you click on the “username Inbox” button.

I also added a directory tree for those directories that are filled with subdirectories of pictures. Basically the list will display the thumbs of the pictures and the tree to the left are the sub directories that may contain more pictures (or no pictures). Double clicking on a directory in the tree will update the picture list. The max file upload is 100MB and it won’t let you upload more than that.

Download: katanapgair-v1beta.zip

Flex Image Resampling

Tuesday, May 6th, 2008

While working on KatanaPG (picture uploader) I ran into a memory issue. Pictures, especially those taken with 6+MP cameras, are HUGE. When I was creating the thumbnails for them in the TileList was was simply resizing them. This kept all that 6MP of data in memory just loooked smaller. I needed to resample it at a lower resolution and then dispose of the original. I tried it multiple ways, first using an Image and setting the source and then the width and height.  Then using a bitmap and scaleX and scaleY (as well as ImageSnapshop, but never go that to even work).  After posting a question to flexcoders a very kind replier said: “Use bitmap.draw.”  That method worked great.  Below is a chart of the Flex Profile peak memory for each method. Pictures imported: 23 Photo Booth pictures 640 x 480 and about 150KB on disk each.

Method Peak Memory (KB)
image.width/height 33,351
bitmap.scaleX/scaleY 61,837
bitmap.draw 7,107
I don’t know exactly why the first two methods take up almost as much memory as Firefox, but I am glad I managed to reduce the memory significantly. Now for he part you all have been waiting for, CODE. I used this code for a TileList.itemRenderer.

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100" height="100" initialize="init();" creationComplete="created();" dataChange="init()">
        <mx:Script>
            <![CDATA[
                import mx.graphics.ImageSnapshot;
                import mx.core.UIComponent;


                private var _created:Boolean = false;

                private function created():void
                {
                    _created = true;
                    init();
                }
                private var contentLoader:Loader;
                private function init():void
                {
                    if(!_created)
                        return;
                    removeAllChildren();
                    contentLoader = new Loader();
                    contentLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, LoadComplete);
                    contentLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, IOErrorHandler);

                    var request:URLRequest = new URLRequest(data.url);
                    contentLoader.load(request);
                }

                //When image loaded, create scaled bitmap
                private function LoadComplete(evt:Event):void
                {
                    evt.stopImmediatePropagation();
                    var loader:Loader = Loader(evt.target.loader);
                    var image:Bitmap = Bitmap(loader.content);

                    var sxy:Number = (image.width > image.height)?(95/image.width):(95/image.height);
                    var scaleMatrix:Matrix = new Matrix();
                    scaleMatrix.scale(sxy,sxy);

                    var container:UIComponent = new UIComponent();
                    addChild(container);

                    var scaledImage:Bitmap = new Bitmap(new BitmapData(95,95,true,0));
                    scaledImage.bitmapData.draw(image,scaleMatrix);

                    container.addChild(scaledImage);
                    contentLoader = null;
                    image.bitmapData.dispose();
                }
                private function IOErrorHandler(evt:IOErrorEvent):void
                {
                    trace("Error loading",data.url);
                }
            ]]>
        </mx:Script>
    </mx:Canvas>