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.)