Tuesday, December 13, 2011

Flex a Spoon, Flash some AIR, and stick around for a while


Hoyt’s last Chicago Flex preso and Labriola’s SpoonProject

Kevin Hoyt and Michael Labriola both were the guest speakers at our CFUG meetup (www.chicagoflex.org).  The great news is that this was the first time either of them had spoken together in the same room at the same time.  The sad news is, this will be the last time both of them will be together at CFUG to ever talk about Flex again.

If you are interested in watching the near 2-hour discussion, please go here: https://experts.adobeconnect.com/_a204547676/p7xqmnpakcd/?launcher=false&fcsContent=true&pbMode=normal

Otherwise:

First off, I want to discuss a few things that I feel will help clarify where I am coming from.  Often times I have discussions with multiple clients about what Flash is, how Flex fits in, and we can accomplish with AIR.  For this post (which is long – way too long perhaps, but long enough to see the point), I am going to just quickly reference and review, then I will discuss: Adobe’s PR (the reason for this meetup and me asking Michael and Kevin to come and talk); Adobe’s strengths, position, and vision for the future; The Spoon Project; Spoons opportunities and dilemmas; and my own 2 cents.

What is Flash?

Plain-speak: A plugin.  Want more information, check here: http://en.wikipedia.org/wiki/Flashplayer.  It is Adobe’s bread and butter when it comes to content management regarding video and video games.  More on that later.  For now, know that it is a highly evolved virtual machine (VM) that can execute code (AS3) for a rich and interactive experience.

What is Flex?

Plain-speak: A framework built on top of Actionscript 3.  It is a powerful tool for building applications, especially enterprise apps.  It has a terrific life cycle, amazing APIs, and is several years ahead of any other technology for delivering secure, robust, and data-driven applications

What is AIR?

Plain-speak: A desktop version of the web browser version of the flashplayer.  It has some much cooler APIs than the standard flashplayer, and because it isn’t sandboxed by the browser, you get a few other neat things.  Still, it’s mainly a desktop version of the browser version.

So?

Adobe’s PR (fubarred, snafu, or intended)

Adobe is great at one thing, making tools for creative people to create things.  In my experience as a developer, consultant, analyst, and everything else, I’ve learned that when it comes to businesses and software development, you get one of two things: an agency approach, or an enterprise approach.

As a quick definition, and agency approach is the short term.  These are products that don’t have much shelf life, are short lived in the wild, and even if they win an award will fade into obscurity soon.  The enterprise approach is the opposite.  While enterprise apps are notoriously slow to come to fruition, they last (what seems) forever.  Normally they are a 5-10 year package that sells for a large amount, and comes with upgrades, new features, and snazzy options as the life of the product wears on.

In the world of Adobe, Adobe has no clue how to deal with the enterprise.  They can only see one thing, and that is the bleeding edge.  As a four-plus billion dollar ($4,000,000,000+) a year company, Adobe makes most of it’s money on creative tools.  This means Creative Suite, Photoshop, and a few other choice applications is where Adobe makes its money.  It does it by selling tools, or packages of tools, to companies and users.  Since the inception of Flex, Adobe has never really figured out how to make money off of it.  Flex uses the flashplayer and AIR, but AIR and the flashplayer don’t need Flex.  In fact, one of the biggest complaints of Flex is the bloat it brings with its myriad libraries, download times can be severely impacted. Not to mention the speed of an application because it is using the Flex messaging framework.  These have been, and will be, hotly contested for some time to come. 

Regardless, Adobe never made (“real”) money by creating the framework.  It did make some money by consulting on projects, but the 25+ team members it has allocated to the sdk never generated revenue (unlike the large group of folks who work on Photoshop or AfterEffects, whose products do make money).  Flashbuilder does generate some revenue, but not at the same volume as the other products.  Adobe looks to start projects that can generate at least a hundred million dollars ($100,000,000) a year, and Flex never even came close.  Sure it might be a multi-million dollar venture, but is that worth the resources when those resources could be dedicated to a larger project and make more money somewhere else?  Adobe says, “Nope.”

So Adobe made the bold move and told the world it is no longer interested in developing Flash for mobile (completely unrelated to Flex), and making Flex completely open source, giving it, and its support to the Apache Foundation (http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html).  Make no mistake about it, Adobe will support the flash player, especially for the desktop, and it WILL support AIR.  AIR makes the flashplayer available everywhere that isn’t a browser, so video content and games have a way to live on.  And Adobe keeps its cash cow.

And don’t worry, Flex isn’t going anywhere too quickly, but we’ll get there in a bit.

The message from Adobe is messy, sloppy, poorly handled, but think of it like teenage angst, where the person has lost control of their emotions, and finally just said, “Enough! Enough! We can’t have it our way, we don’t want it any way!”  Adobe has not been able to capitalize on innovations that are not tools “creative” people need. 

Adobe’s position (including Natobi/PhoneGap)

So what does Adobe want to do going forward?  For starters, they have their Interactive Developer Evangelist team spearheading a PR campaign to tell all developers that HTML is the future.  Their message has become pretty consistent, with their twitter feeds basically dropping any mention of Flex.  They seem to ignore everything Flex, and stick with the standards of the future.  Let’s not get caught u p in rhetoric. Adobe is not interested in maintaining Flex any longer than it has to.  Flex is a dead weight to the hipster, creative, entrepreneurial type.  And Adobe cannot wait to release itself from that death grip.  To prove that it is over Flex, it bought Natobi, Typekit (http://blog.typekit.com/2011/10/03/adobe-acquires-typekit/), Efficient Frontier (), and a few other online real estate properties, pointing towards a desire to enter and again dominate the tool making process for online advertising (because the flashplayer hasn’t been there for the last decade).  From the 8/18/11 anouncement, Adobe is building up to be the leader of “…Content Authoring and Digital Marketing.” 

Enterprise applications are not either of those.

Adobe bought Natobi because Natobi created PhoneGap.  PhoneGap is a software application that essentially turns any application you create into an HTML5/JS/CSS application, wraps it in a pseudo-browser, and deploys like a native app.  So, for example, on iOS this is a standalone instance of Safari running on your device, and it appears to be a standalone, native app, but you are only seeing Safari rendering web pages that are considered the app.  The library works quite well, and for all intents and purposes, it acts just as good as a native application.  Adobe supports it and suggests you use it as well.  For them, this is the bleeding edge of technology, pushing mobile application development.

There is no Spoon?

During the 2011 Flex|360 conference in Denver, it was announced that the Spoon Project was taking off.  If you don’t know what Spoon is, read here: http://www.spoon.as/
Short take – it’s meant to help the Flex development team fix bugs faster.  It’s got an architecture of people and processes to resolve conflicts and promote fixes faster than Adobe’s Jira and engineers could handle. Spoon has PR, it has volunteers, it has a lot!

Spoon’s dilemma

It might actually conflict with the Apache Software Foundation (ASF).  This is not detailed out yet, and Spoon, Adobe, and ASF have some work to do to hammer out the details.  There are a lot of license agreements, IP rights, and whatever else a lawyer wants to earn fees to help disentangle Adobe from the Flex framework.  Spoon might be a problem only because it is a separate entity ready to run and fix problems, and Adobe is saying, “Actually, let’s let the big boys handle this.  We’re gonna give it to ASF, and see that they take good care.”  Nothing is set in stone yet, and Spoon may or may not be involved.  That is to be determined.

Future

If there’s anything that is certain right now, the Flash player and AIR are going to continuously be improved upon, upgraded, and pushed out to be as ubiquitous, easy to use, easy to get, and easy to update.  Adobe has a lot at stake to make sure these tools remain potent sources of DRM content providers, and will keep them up to date.  But Adobe also wants users to buy their products if they are making cutting edge products.  The amazing thing about HTML advertising is that you can’t disable it without disabling your browser.  With Flash, there were plugin disablers galore that allow users the ability to block any flash-related medium trying to load on your computer.  However, now with the advent of video and canvas in HTML5, unless you disable javascript on your browser, you can’t stop the ads from coming.  It is a marketers wet dream to know that’s where we’re going.  And guess what, Adobe is looking to blaze the trail by providing you with the latest and greatest tools to make them.  Adobe is not promising Apps, they are promising rich web pages, rich ads, rich user experiences.  It is cutting edge, but not anything with a long tail.  Flex is a long-tailed beast.

And just for a quick summation, here's Peter Elst's post about the exact same subject:

http://www.peterelst.com/blog/2011/12/13/flex-summit-updates-on-the-open-source-strategy-and-runtimes/

The Flex Summit has had some interesting notes and should help provide information about the future of this industry!

Monday, November 21, 2011

Balanced decision on the future of Flex

Essentially, Adobe has come to the realization that the world does not
want plug-ins on mobile devices.  Unfortunately Adobe has done a
terrible job communicating what their intention is, and the initial
feeling many Flash/Flex users and developers had bordered on
pandemonium.  But this announcement is actually great news.  Adobe did
a poor PR job, so here's a post that really clarifies the good from
the bad: http://david.realeyes.com/?p=214.  And Adobe about their
strategy: http://www.adobe.com/devnet/flashplatform/articles/recent-updates.html

These are long posts, so if you don't have time, here's my summary:

First and foremost, Flash was never really viable on mobile devices.
The actual Flash player has always been clunky, resource intensive,
and just buggy on mobile.  It was created for a world of users that
had a mouse and could interact with the screen via a cursor.  On
mobile devices this is different, and the rules of
human-computer-interaction have changed.  That said, Adobe won't put
resources into something that isn't meant for mobile.

Second, Adobe is finally giving us (developers) the ability to fix
Flex faster than Adobe could.  Since Flex 1.0, Adobe has controlled
the entire update and release process of Flex, often times ignoring
blatant problems and publishing updates with a strange sense of
priority.  As an open source technology, the community of developers
gets to enhance it, much like Sun made Java open source, and aids
development, but doesn't control where it goes.  The community gets to
enhance a mature technology and improve on it, with resources from
Adobe and the rest of the world.  Adobe is finally making good on its
original promise from years ago to make Flex truly open source.

Third, the Flash player for the desktop will continue development
because it is viable, extremely robust, ubiquitous, and provides a
uniform experience regardless of which platform you are on.

Fourth, for mobile development, Adobe stands behind AIR and the
continued improvement and development of this tool.

I am not urging anyone to simply take the path of one technology over
another.  HTML5 is definitely here to stay, but its tools, frameworks,
and community are very immature compared to the Flash platform.
Conversely, native development is expensive in time and resources, and
both paths cost a lot in regards to testing every browser on every
device and OS.

There are arguments for why companies should begin acquiring and/or
developing talent in native and web-based technologies, but these are
bets being made for a future that might pan out one direction or
another.  I think it is beneficial to all companies that have used
Flash in the past to realize that not much has changed or will change.
 Flex is an awesome enterprise development tool that can be used to
rapidly build projects.  Flash and AIR are great resources with an
excellent community.  Adobe just needed to openly realize that Flash
on a mobile device wasn't realistic, and that the community will
benefit more by having Flex be truly open sourced.

For the future of your projects, I truly believe Flex is very strong,
secure, and viable.  The wariness of Adobe's commitment is
understandable.  Regardless, Flex isn't going anywhere, and will be
here (specifically in the enterprise) for many years to come.

Thursday, October 27, 2011

Dynamically loading audio from different locations in ApplicationStorageDirectory

Similar to my last post about getting data from different locations, this time, instead of trying to load images, i'm trying to load audio clips.  It took a little bit of finagling, but I finally have it.  Just a quick bit of back story, I am downloading a zip file and unzipping contents into my app storage directory in folders.  If I reference the directory, I need to adjust the file.nativePath for that.  Enough talk, here's the code:

_file.nativePath     = _file.nativePath + _audio;
                req                 = new URLRequest(_file.url);
                s                     = new Sound(req,context);

over and over I tried to just make the URLRequest be the _file.nativePath + _audio and kept getting the most awful Error #2032 Stream Error (which explains nothing and is not helpful).  Finally I came across a forum post that explained that the URLRequest needs the _file.url, otherwise it appends this app:/ to my string, which bombs out.  So i can adjust the nativepath, and then use the url.  ta-da!!!

Loading images from applicationStorageDirectory in Flex Mobile

I have to say, without a doubt, this was one of the most confounding things I've worked on in a long, long, long time. In a project for my client, I have to be able to store zip files filled w/ media assets, then be able to load audio or pictures at runtime.

 Sounds easy, right? Wrong :(

 Loading a picture has never been this painful in my life. It turns out, I can add the image to the stage (which for some reason is not respecting my skin, contentgroup, or vertical layout settings). Regardless, I can finally load any stored image via this "not-so" simple routine.  One caveat I have is, I am downloading images in zip format, and using a utility to unpackage them into the storage directory in folders.  originally I though that would be a problem, but it turns out, because I can update the file.nativePath with the new folder, this works just fine.


var fl:File = File.applicationStorageDirectory;
fl.nativePath = fl.nativePath + _image;
var bytes:ByteArray = new ByteArray();
var filestream:FileStream = new FileStream();
try{
filestream.open(fl, FileMode.READ);
filestream.readBytes(bytes, 0, filestream.bytesAvailable);
filestream.close();
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, showPic);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
loader.loadBytes(bytes);
}catch (e){
trace("xml badly formed");
}



and in my showPic method:

loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, showPic);
var bitmapData:BitmapData = new BitmapData(loader.content.width,loader.content.height, true, 0x000000);
bitmapData.draw(loader.content, new Matrix(),null,null,null,true);
img.source = new Bitmap(bitmapData);

Honestly, painful, but it gets the job done.  Now to load audio dynamically from saved files is another story for another post:)



Tuesday, May 10, 2011

Datefields before Flex 4.5

So I wanted to take advantage of the custom skinning I had already done for a datechooser, and apply that to my new datefield without making a copy of all the skin classes.  Turns out, this is relatively easy, if you know what to look for.  Code below:

  1. Extend datefield
  2. set the dropdownFactory in the constructor to an IFactory var
  3. then in css, set your custom datefielddatechooser's settings (which may be identical or different to your own datechooser custom skins)
  4. and finally, in css (or wherever else you set your styles), for the extended datefield, set the dateChooserStyleName to null...i.e. ClassReference(null)
You do these steps, and you'll have your custom skins show up on the drop down of the datefield...a PITA and Flex 4.0/4.1 problem, so maybe it's no longer mx in 4.5 (but I can't find it anywhere in spark, so maybe it's still stuck in MX hell?).  Anyways, as promised, here are some code examples, if my sytnaxhighlighter doesn't eat them.

DateFieldBase.as


package com.lordB8r.view.component.controls.datefield{

import flash.events.Event;
import mx.controls.DateField;
import mx.core.ClassFactory;
import mx.core.IFactory;

public class DateFieldBase extends DateField{
private _dateChooser:IFactory = new ClassFactory(DateFieldDateChooserBase);

public function DateFieldBase(){
super();
this.dropdownFactory = _dateChooser;
}
}

DateFieldDateChooserBase.as:
package view.component.datefield.datechooser{
 import mx.controls.DateChooser;
 
 import view.component.datechooser.skins.CommonsDateChooserNextMonthSkin;
 import view.component.datechooser.skins.CommonsDateChooserPrevMonthSkin;
 import view.component.datechooser.skins.CommonsDateChooserRollOverIndicatorSkin;
 import view.component.datechooser.skins.CommonsDateChooserSelectionIndicatorSkin;
 import view.component.datechooser.skins.CommonsDateChooserTodayIndicatorSkin;
 
 [Style(name="highlightFillColors",  type="Array", arrayType="uint")]

 public class DateFieldDateChooserBase extends DateChooser{
  public function DateFieldDateChooserBase(){
   super();
   setStyle("nextMonthSkin",    nextMonthSkin);
   setStyle("prevMonthSkin",    prevMonthSkin);
   setStyle("rollOverIndicatorSkin",  rollOverIndicatorSkin);
   setStyle("selectionIndicatorSkin",  selectionIndicatorSkin);
   setStyle("todayIndicatorSkin",   todayIndicatorSkin);
  }
  
  protected function get nextMonthSkin():Class{
   return CommonsDateChooserNextMonthSkin;
  }
  protected function get prevMonthSkin():Class{
   return CommonsDateChooserPrevMonthSkin;
  }
  protected function get rollOverIndicatorSkin():Class{
   return CommonsDateChooserRollOverIndicatorSkin;
  }
  protected function get selectionIndicatorSkin():Class{
   return CommonsDateChooserSelectionIndicatorSkin;
  }
  protected function get todayIndicatorSkin():Class{
   return CommonsDateChooserTodayIndicatorSkin;
  }
 }
}


CSS:
datefield|DateFieldBase{
date-chooser-style-name: ClassReference(null);
}

datechooser|DateFieldDateChooserBase{ headerColors: #e2e6eb, #f4f5f7; todayColor: #818181; rollOverColor: #b2e1ff; selectionColor: #7fceff; color: #373830; borderColor: #b7babc; headerStyleName:"mydateChooserHeaderStyle"; weekDayStyleName:"mydateChooserWeekDayStyle"; todayStyleName:"mydateChooserTodayStyle"; } .mydateChooserHeaderStyle { color: #373830; font-weight: bold; } .mydateChooserWeekDayStyle { color: #373830; font-weight: bold; } .mydateChooserTodayStyle { color: #ffffff; fontWeight: normal; fontStyle: normal; textDecoration: none; border-visible: false; }
DateChooser

Monday, May 9, 2011

Adding Rollover/rollout halos to Flex 4 skins





So in my current project, I'm working on skinning several controls in Flex 4. One of the issues that I'm coming across is the desire to have the rollover halo effect that used to be in Flex 3. I was getting css styles from the Flex Style Explorer developed several years ago by the Adobe Consulting team.  Now, don't get me wrong, that explorer has saved me many sleepless nights. However those styles no longer apply in Flex 4.  The main reason is that some components no longer extend from button that used to normally extend from button.

ButtonBase.as is fascinating, and a great place to read up and understand the most basic principles of skinning and the skin UIComponent that is attached to the Button.  Flex 4 is wonderful, and I really, really, really enjoy the maintainability of skinning components in this framework much more than the previous framework.

Anyways, the point of this post is to quickly show you how you can take advantage of skin parts, and pre-existing components, to extend your components and get effects that you thought were lost in the transition to Flex 4.

Anyways, if you haven't seen, I think (but can't remember right now) I did a post on passing CSS styles into Flex 4 skins via custom components.  Regardless, you can easily add rollover effects to standard components with a few steps.


  1. Create a new component that extends skinnableComponent


public class ComboBoxBase extends SkinnableComponent{


In that component, add a skinPart.  For more information about skin parts, see Ryan Stewarts quick blog about it here.  That got me going further



[SkinPart(required="true")]
public var cbo:ComboBox;

Create a new skin that extends from skinnableComponent



<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009
xmlns:s="library://ns.adobe.com/flex/spark
xmlns:mx="library://ns.adobe.com/flex/mx">
<!-- host component -->
<fx:Metadata>
[HostComponent("spark.components.supportClasses.SkinnableComponent")]
</fx:Metadata>

Add the states you want (mine were hover, hoverNormal, normal)



<s:states>
<s:State name="normal"/>
<s:State name="hover"/>
<s:State name="hoverNormal"/>
</s:states>

Add to the skin the control you want to have a halo around



<s:ComboBox id="cbo" width="100%" height="100%"/>


notice that the combobox here has the exact same ID as in the component class (that is important!)

Add a rect before (or after - depending on the effect you want) with a solidStroke.



<s:Rect left="-1" right="-1" top="-1" bottom="-1" radiusX="3" > 
<s:stroke>
<s:SolidColorStroke color="0x0000ff" alpha.normal="0" alpha="1"/>
</s:stroke>
</s:Rect>


I put my rectangle afterwards, and you can specify radiusX and many other items using script or CSS.

In the custom component, override the partAdded and add some eventlisteners for mouseEvent.ROLL_OVER/ROLL_OUT. (and don't forget to remove them, otherwise some other person might get angry).



override protected function partAdded(partName:String, instance:Object):void{
super.partAdded(partName, instance);
if(instance == cbo){
cbo.addEventListener(MouseEvent.ROLL_OUT, haloEffect);
cbo.addEventListener(MouseEvent.ROLL_OVER, haloEffect);
}
}
override protected function partRemoved(partName:String, instance:Object):void{
super.partRemoved(partName, instance);
if(instance == cbo){
cbo.removeEventListener(MouseEvent.ROLL_OUT, haloEffect);
cbo.removeEventListener(MouseEvent.ROLL_OVER, haloEffect);
}
}


In your event handler, change the skin.currentState to the new state that you setup in your skin.



protected function haloEffect(me:MouseEvent):void{
if(me.type == MouseEvent.ROLL_OVER){
//stateChanged('normal','hoverNormal',false);
this.skin.currentState = 'hoverNormal';
}
else{
//stateChanged('hoverNormal', 'normal', false);
this.skin.currentState = 'normal'
}
}


And finally, don't forget to add your skin to your component via setStyle('skinClass', skinClass):


public function ComboBoxBase(){
super();
setStyle('skinClass', skinClass);
}
protected function get skinClass():Class{
return ComboboxSkin;
}


And there you have it, a fully haloed Flex 4 component, that you dind't have to do a lot to get...if enough folks want to see the code files, I'll try to find a way to get Blogger to let me post those as well.  Hope this helps someone else

(ps - i apologize for any code syntaxHighlighting formatting problems...I've spent too much time trying to figure out how to do this right now, but if it is really causing someone headaches, please let me know, and I'll spend some more time cleaning it up.  Thanks!)

Sunday, April 24, 2011

Custom skinning mx tabnavigator tabbars in Flex 4.1 (pre-4.5 mx style)

For anyone who doesn't care about my explanation and just wants code, please see the bottom of the post.

The annoying part about this post is that it probably won't matter for anyone using Flex 4.5 or later, but if you are using Flex SDK 4.0 or 4.1, this might just help you.  I've been working on skinning a tab navigator, and in the process, kept running into roadblocks, especially when I wanted the skin to respect a new state.  Long story short, skinstates in MX components were not behaving correctly, and skinning a Flex 3 component with a flex 4 mxml skin, expecting states to help me change views, wasn't working.

I tried to invalidateSkinState, but that's not a feature of Flex 3, and I tried to overwrite the Tabbar and Tab, but that become a bloody mess because of all the needed inheritance.  The best answer to solve the riddle came here from Ivan Latysh, who succinctly says, "doc's are lying".  Hellz yes they are.  The docs only tell me to use the css (it doesn't mention that the framework actually comes with two).  The biggest problem I was having was just getting the skinning rectangles to respect their selected/non-selected states.  They wouldn't.  The couldn't. because when I traced down to it, tab navigator doesn't fire off a StateChangeEvent for anything other than "up" (*disclaimer: myriad reasons might be at fault, including my own customizations of my setup, but for sake of argument, I couldn't skin a tabbar as part of a tabnavigator [separate components wouldn't work because by the time I was brought in on the project, the logic was heavily embedded for the tab navigator]).

Because I can't have the tabnavigator separated, I needed to figure out how to skin it appropriately to recognize the events and the actions.  Justin, aka Saturnboy has an amazing post on pushing component events into skins here.  So did WebDevGirl and James Whitakker.  And this stackoverflow post helped, but still, I still find the right info.  The tabbar refused to accept anything for mouse over events, and the only thing I could eventually figure out was that the component wasn't applying state events to the tabbar.

If this is the case, then it's a bug in 4.1.

But here's my solution, because I wanted to set everything in my library to respect the classes, and then styles could be overwritten in later CSS files (this tabnavigator was actually part of my core library, and I needed it to have the default skins to be adjusted by later users.


up-skin: ClassReference("lordB8r.view.component.navigableContainer.skin.CustomTabNavigatorSkin");
over-skin: ClassReference("lordB8r.view.component.navigableContainer.skin.CustomTabNavigatorSkin");
down-skin: ClassReference("lordB8r.view.component.navigableContainer.skin.CustomTabNavigatorSkin");
selected-over-skin: ClassReference("lordB8r.view.component.navigableContainer.skin.CustomTabNavigatorSkinSelectedTab");
selected-down-skin: ClassReference("lordB8r.view.component.navigableContainer.skin.CustomTabNavigatorSkinSelectedTab");
selected-up-skin:   ClassReference("lordB8r.view.component.navigableContainer.skin.CustomTabNavigatorSkinSelectedTab");

However, if I want the original skins from the mx component, and have those skins and their faculties recognized, use this to override the default skins that I was trying to set styles to:

skin: ClassReference("mx.skins.halo.TabSkin");
border-skin: ClassReference("mx.skins.halo.HaloBorder");
border-side: "left, top, bottom";

The main purpose of this blog post is to point out that even though the styling that I wanted to use in Flex 4.1 on an MX component should have allowed me to create a custom skin (albeit in AS3 or MXML), and apply to the class, I couldn't do it because the component was reverting everything back to 1 class and not passing state events into the component (the only event I could capture was "UP", which was not very helpful.

Anyways, I do believe the tabnavigator is now a Spark component, and this headhache should evaporate with Flex 4.5, however, if you are stuck on a 4.0 or 4.1 project, and need to apply skins to the tabbar, this should at least show you that the skins themselves aren't very good for listening for events, so either override them completely, or use the original skin, and use original stylings for mx components (and just override in the css - apparently doing so at the component creation point doesn't seem to help ;p )


Monday, February 21, 2011

FizzBuzz in AS3


I'm not sure why this didn't seem hard, but in 10 minutes I came up w/ this solution to fizzBuzz:

private function fizzBuzz():void{
  for (var i:int = 1; i <= 100; i++){
    var str:String = String(i) + " " ;
    if(i%3==0){
      str += "Fizz";
    }
    if(i%5==0){
      str += "Buzz";
    }
    trace(str);
  }
}

Was there an easier way to do this?  Could I refactor this down further in AS3?  I tried overcomplicating it for reuse, but then said, "why?"  I just need it to spit out Fizz, Buzz or FizzBuzz, and the value of i...so that's it for now...Go AS3, modulo, and procrastineering...

edit: After reviewing the code, I decided to expand it (yes, I wasted another 10 minutes on this), but now I can pass in to fizzBuzz any values so that I don't have to have my modulo hardcoded.  Here it is, eat your heart out :)


public function fizzBuzz(starter:int, ender:int, fizzer:int, buzzer:int):void{
for(var i:int = starter; i<=ender; i++){
var str:String = i + " ";
if(i % fizzer == 0){ str += "Fizz";}
if(i % buzzer == 0){ str += "Buzz";}
trace(str);
}
}

Wednesday, February 2, 2011

Hacking an iOS app from an existing Flex app


To make an iPhone application work from an existing Flex/AS3 app, you have to jump through a few hoops.  The first and foremost are getting a few certificates, png's and licenses out of the way.  Before going any further, you need the following:

1) Provisioning profile
2) PKCS12
3) icons
4) an app (not necessary before you start, but indeed necessary for the end result)
5) PFI (Packager For IPhone)
6) AIR SDK (2.0.2 or later)

Ok, the provisioning profile is the hardest bastard to deal with.  If you are like me, and just want to put together a proof of concept, you don't (nor shouldn't) have to pay a company $99 just to try it out.  However that's not how it works for iOS applications.  Apple wants your money any way they can get it, and even if you want to write just a simple app, they'll try and get it however they may.  After asking Lord Google the best way to get past paying money, I found this one link with a hacked provisioning profile...success!!!  Actually, I need to learn the mechanics of this profile to understand what's really in there.  But for my POC, I just grabbed one from here.

Next, I needed a PKCS12 (or more short-handedly known as a .p12) certficate.  This wasn't easy because I've never created one before.  After much searching and trying, I came across Flat Mountain's awesome posts on how to do it.  Always looking to improve my shell skills, I followed his post and finally got some certs built.  I could've used Apple's developer site, but that seemed to obtuse.  and this is for OSX.4, so it might not be relevant, but it's also a start.  On a Mac you can even use Keychain Access, but I didn't go the "easy" route until Flex Builder started complaining that my cert wasn't a "code-signing" cert...  I spent another few minutes trying (However, now that I'd gone through the process of making the cert manually, I understood a lot more about what keychain access wanted to do).  In less than 3 minutes I had created a CA and a cert…but dangit! I couldn't export those as code signing certs (at least not right off the bat, even though I had created them as code signing certs).  About 2 minutes later, i figured I had to evaluate the cert.  I changed the viewing and evaluation to Code signing and voila! I could export the cert as a .p12!  WOOT!

OK, fine, I should also post that exporting the final release will also give you the option of creating your own .p12 right there on the spot, but I felt like that is just way too easy to do, and you don't actually have a clue what's going on in the black magic voodoo of Flex Builder's sneaky background (maybe a post is required about how FB builds keys…but not right now).

Armed with my cert and profile, I just needed a quick default icon, so I used some Photoshop (which isn't necessary, but can help), then Apple's Icon Composer (part of the xCode package: /Developer/Applications/Utilities/Icon Composer).  This guy's blog post helped, but I wasn't interested in paying for CandyBar, so I skipped that step .  It's also about 4 years old, so unless you're still running just Leopard or Tiger, and CS3 or CS4, then you have to use a little imagination.

Ok, icons and certs down, now to getting my AIR app to work.  I used FB4's converter to change the project from Flex to AIR.  A few errors (read: Flex 3.5 SDK custom preloader doesn't like AIR applications because of the addedToStage event.  With a workaround in my custom preloader, I have a functioning AIR app that works on my desktop.)

Now, command line is cool, but sometimes we just need functional.  I got the steps from Kevin Cantrell's post to start with, but I didn't like figuring out all the paths, tabbing through and hopefully not messing up the spelling of anything (I'm lazy, not a hipster).  Even after making it all, putting it into a text editor so I could copy and paste for later use seemed trite.  So I used FB's export tool with my custom signed certs to at least build my app's swf (it exports as a .air, but that's just code for .zip/.tar/.air/.whatever).  I un-tarred it to have the swf, but there's also a copy in my bin folder by default.  I also want to be lazy, so I used this post from Ivan to update the ant build process so I could remain lazy.  Now I have everything in place, so let's let it run, and tada!!!

I've got a functioning Flex app converted from Flex 3.5 to iOS (with some hefty mods). and it runs!  Ok, it isn't native, but as a POC, it doesn't matter.  The point is the point.

This was for me a POC as well as an aggregation of different user's experiences.  If you have any questions, please ping me or the other guys who put this together.

Tuesday, February 1, 2011

Debugging Flex and Java on Glassfish on OSX6

Just a short post about debugging apps.  If you are using OSX and Glassfish, if you want to debug a remote java application, you need to do the following on the glassfish (there are 2 ways to do this)

The first is going through the admin screen -> application server -> JVM Settings -> JVM Options -> and add the following to JVM Option:


-XX:+UseParallelGC




Save your options and you'll need to restart your server.

Make sure you only add that here, otherwise your server won't start up correctly and you'll be forced to do what I learned the hard way (proceed to step two if you added it to the General tab's Debug Options)

Open the following file:

~/glassfish/domains/domain1/config/domain.xml

Add a child to the with the same parameters:


-XX:+UseParallelGC



Then restart your server and you're all set!  I hope this helps anyone else trying to get eclipse breakpoints to actually catch on debug mode using glassfish!

Friday, January 7, 2011

Sending an email from your Flex app just got easier (short post)

I want to send an email from my Flex app.  Well, if I don't have a backend mailserver setup, and I want my user to send me a message about, say, the app's service crashing, the easiest way to do this is through URLRequest!

Quick demonstration - 

1) Create the url request: 

var u:URLRequest = new URLRequest("mailto:"+EMAIL_ADDRESS);

2) Create a variable for the subject and body:

var v:URLVariables = new URLVariables(); //interestingly, you can put all the variables into a string and pass that in, but here we're just going to append them as properties to the object

3) Assign those properties:

v.subject = "Application crashed";
v.body = TEXT_OF_CRASH_MESSAGE;

4) Pass those variable properties into the URLRequest:

u.data = v;

5) Navigate to the URL:

navigateToURL(u, "_self"); //the _self is .js and not required

This is an easy way to pass any valuable info from your flex app into your user's default email program (Entourage/Outlook, Thunderbird, Mail, etc.)

Thursday, January 6, 2011

Error #2173: Unable to read object in stream


I've been working on building up async tests (which I should have a different post for shortly), and came across this annoying error:

ArgumentError: Error #2173: Unable to read object in stream.  The class com.lordB8r.model.Control does not implement flash.utils.IExternalizable but is aliased to an externalizable class.
at ObjectInput/readObject()
at mx.collections::ArrayList/readExternal()
at mx.collections::ArrayCollection/readExternal()


Finding FlashSecret's comment helped, but didn't get me all the way there.  While I could put the path inside an array, I wasn't assigning the return value to an array, or Control.  Instead, I needed to import a/the class(es) needed by IExternalizable in my test.  So, simply putting this in my test class made it work:

import com.lordB8r.model.Control;


Is this correct for testing?  I'm not sure, but it helped me get my async test to retrieve data from a Spring RESTful service.  Test passed because I got data, but only once I told my test what data type it should be expecting.

I've dealt with this when bootstrapping an application, also when requesting data back from the server.  Often times, my service class (or service recipient) doesn't know the type I just asked for, so I need to import it into that class.