wtorek, 18 sierpnia 2009

Adobe AIR and Flex SDK dirty secrets part 1

Well there was a while since Adobe put their AIR(Adobe Integrated Runtime) to the public. The newest one is AIR 1.5.2 so there was 1.5.1, 1.5, 1.1 and 1.0 version. Adobe AIR 1.0 was released something like year ago and there are already 5 versions of this runtime each got some bug fixed.
All you should see here in release notes:
http://www.adobe.com/support/documentation/en/air/releasenotes.html
I unfortunately can't. This is only blank page for me for each version but not the last one.

So shortly, we get installer languages support in AIR, it supports 3 platforms Windows, Mac OS X and Linux.

The installer looks different and there are some more, less important enhancements like ex. check disk space available, or check transparency support.

Well when AIR was released the special flex sdk components get released too for programmers to make their life easier.

O RLY ?

I don't want to blame anybody and talk that air is bad , or the flex sdk code is sloppy. I'm also not the best programmer in the world. But since I use adobe technology I want to share what is bad and what is good for me and what you are dealing with while working with that technology.

Well Adobe want to release Flex SDK 4 but I got one fresh on my drive directly form svn and as far as I know nothing has changed what I'm writing about. That's public beta so don't wait for that changes I will make here for you.

The posts will be specially for You, that want to make glamurous applications and don't want to tear one's hair out.

Something easy for the start then:
mx.core.WindowedApplication have got showFlexChrome parameter that can be true or false. It's important for not with system chrome fancy applications.

Flexbuilder shows that this param it's style property so you can set it in style sheet. Well not exactly since it's not obvious how to use that style and since it's buggy one.

The positive part of the story is that Flex SDK is some kind of open source now so you can view the WindowedApplication component source, Thank You Adobe we need fix some stuff ;)

Let's back to the code.

Well we need to find showFlexChrome param. The first one is at 1768 line (WTF?) in createChildren() method. We are some kind of experienced Flex SDK users so we know what the method do cause we can do AS3 custom component's. It's obvious one that's creating all children of the component based on parameters you pass. so there is code:

/**
* @private
*/
override protected function createChildren():void
{
super.createChildren();

if (getStyle("showFlexChrome") == false ||
getStyle("showFlexChrome") == "false")
{
setStyle("borderStyle", "none");
setStyle("backgroundAlpha", 0);
return;
}

if (!_statusBar)
{
_statusBar = statusBarFactory.newInstance();
_statusBar.styleName = new StyleProxy(this, statusBarStyleFilters);
rawChildren.addChild(DisplayObject(_statusBar));
showStatusBarChanged = true;
}

if (systemManager.stage.nativeWindow.systemChrome != "none")
{
setStyle("borderStyle", "none");
return;
}

if (!_titleBar)
{
_titleBar = titleBarFactory.newInstance();
_titleBar.styleName = new StyleProxy(this, titleBarStyleFilters);
rawChildren.addChild(DisplayObject(titleBar));
showTitleBarChanged = true;
titleBarFactoryChanged = false;
}

if (!gripper)
{
gripper = new Button();
var gripSkin:String = getStyle("gripperStyleName");
if (gripSkin)
{
var tmp:CSSStyleDeclaration =
StyleManager.getStyleDeclaration("." + gripSkin);
gripper.styleName = gripSkin;
}
rawChildren.addChild(gripper);

gripperHit = new Sprite();
gripperHit.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
rawChildren.addChild(gripperHit);
}
}

Let's save the whole class in our project first to make sure the changes will take part.

Well just make structure mx.core, make class WindowedApplication.as, copy all source to it and also copy Version.as source to our mx/core structure and that's it we now got custom WindowedApplication but get back to main part for a second and we got 3 options how to set our style:
1. in component tag - it's working





2. in component in style tag - it's working again




WindowedApplication {
showFlexChrome: false;
}



3. in external style main.css - it's working again wow







/* CSS file */
WindowedApplication {
showFlexChrome: false;
}



So what's about ? Well let's do something like set showFlexChrome=false and then by calling setStyle() set it true. Also set our background color to red.


applicationComplete="appCompleteHandler()">

WindowedApplication {
showFlexChrome: false;
background-color: #ff0000;
}


private function appCompleteHandler():void {
setStyle('showFlexChrome', 'true');
}
]]>



It's not working now, the background is not red, why ?
That's why http://bugs.adobe.com/jira/browse/SDK-11107
Cause of the createChildren() method. There is a condition:

if (getStyle("showFlexChrome") == false ||
getStyle("showFlexChrome") == "false")
{
setStyle("borderStyle", "none");
setStyle("backgroundAlpha", 0);
return;
}

and that sets our backgroundAlpha to 0. If we set our showFlexChrome to false the background will not be showed cause alpha is 0. Wtf and why somebody is deciding for us? Also somebody decided that the borders style now will be none.
Well... the best part is third line return;
The children won't be created so the flex chrome will never be showed.


I don't really know why the showFlexChrome style is existing and why it's not a simple method cause we can loose the chrome just by doing this:


applicationComplete="appCompleteHandler()">

WindowedApplication {
background-color: #ff0000;
}


private function appCompleteHandler():void {
showGripper = showStatusBar = showTitleBar = false;
}
]]>



So it could be simple a getter / setter in WindowedApplication and it will be much simple for us.

//----------------------------------
// showFlexChrome
//----------------------------------

public function set showFlexChrome(value:Boolean):void {
showGripper = showStatusBar = showTitleBar = value;
}

public function get showFlexChrome():Boolean {
return _showGripper && _showStatusBar && _showTitleBar;
}

Let's make it in WindowedApplication.as - remove all showFlexChrome style, make some modifications to keep the code clear and what ? It's working as expected and now you can make some demo like this:


applicationComplete="appCompleteHandler()">

WindowedApplication {
background-color: #ff0000;
}


import flash.utils.setInterval;

private function appCompleteHandler():void {
setInterval(changeChrome, 2000);
}

private function changeChrome():void {
showFlexChrome = !showFlexChrome;
}
]]>



or more practical like this:


applicationComplete="appCompleteHandler()"
showFlexChrome="false">

WindowedApplication {
background-color: #ff0000;
}


import flash.utils.setTimeout;
import flash.utils.setInterval;

private var _mouseIsOver:Boolean;

private function appCompleteHandler():void {
addEventListener(MouseEvent.MOUSE_OVER, mouseRollOverHandler);
addEventListener(MouseEvent.MOUSE_OUT, mouseRollOutHandler);
}

private function mouseRollOverHandler(event:Event):void {
_mouseIsOver = showFlexChrome = true;
}

private function mouseRollOutHandler(event:Event):void {
setTimeout(hideFlexChrome, 1000);
_mouseIsOver = false;
}

private function hideFlexChrome():void {
showFlexChrome = _mouseIsOver;
}
]]>




happy codding

download sample with mx.core.WindowedApplication modifications

Brak komentarzy:

Publikowanie komentarza