After a short stint of not understanding what the heck people were moaning about on twitter (re @jesterxl's comments about cuddling), and thanks to him, I came across Grant Skinner's post about curly braces.
I am personally a cuddler. I find the code easier to read, and I am of the school of thought that less lines of code is better. Also, to me logic dictates that if you are starting a block of code, you would emphasize that by showing me on the line that you are declaring the opening of that code, that the code block begins with the curly. In Ruby, there are no curly's for code blocks, so it doesn't bother me there.
But what bothers me, and Grant mentioned it, is how Flashbuilder autogenerates non-cuddled code blocks. And he griped about it, asking that anyone who knows how to fix the problem please let him know. Well, here's my quick fix, using Flashbuilder 4 on Eclipse 3.6 on OSX6.5:
-> Preferences (cmd + ,) -> Flash Builder -> Editors -> Code Templates -> ActionScript
For each of these classes, I manually updated the templates so that the curly braces all were at the end of the opening line for package, class and constructor, i.e.
package com.lordB8r.controller{
public class TestClass{
public function TestClass():{
}
}
}
and methods did the same thing:
private function runTestClass():void{
}
ahhh, breathe deeply, knowing that all auto-magically generated code in AS3 will now conform to my preferences.
And yes, I can export these settings, in case I don't want to manually change all of them for each instance of Eclipse (and then reimport them).
Now, I obviously am not smart enough to be the first person to have come up with this. There is the following resources I found:
InsideRia's article by Greg Owen
FlexFormatter
ActiveTuts by Jesse Freeman
and the best example so far is someone who actually made real templates of what they use in their workflow:
FBB blogpost by Maxim Kachurovskiy
And you can quickly find your own by using lord google.
LordB8r's ramblings, notes, and posts. These are my thoughts and answers to my own expirements on Ruby, Rails, Flex, Python, Django, PostgreSQL, MongoDB, Scala, robots, independent contracting, coffee, scotch, beer, and anything that makes me curious (just not tax codes, anything but tax codes).
Tuesday, December 21, 2010
Monday, December 6, 2010
Resizing Dynamically Loaded swfs using swfloader
In my current project, I am using RobotLegs and a parent application to load in "modules". However, I don't use modules, because frankly, I don't quite get why I should. Instead, I have separate swfs that I can load, and pass information to them, if necessary. The biggest frustration that I have is that when I resize the parent application, my child, which is a loaded swf, doesn't know it's stage has been resized, and thus doesn't resize itself. To fix that, I tried a few different options, including resizing the loader, the system manager, the loaded application, the screen, everything!!!
The problem I was running into is that my loaded swf was getting it's size clipped. This was unacceptable.
For example, if I loaded my swf into my app, if the window was sized at 700x400 (w x h), if I resized my window to something smaller, the controls inside the loaded swf would follow accordingly. However when I resized the window larger than 700x400, the controls would get clipped by an auto-assumed max size of the loaded swf's stage.
GRRRRRRR!!!!!!
So I have lost countless hours of sleep, including the time it's taking me to post this incoherent message. But I feel I must share about resizing a loaded swf without scaling. Right now I have some jerkiness in the movement, but it forces a scale and resize of the loaded swf's width and height.
I avoid using the _loadedSwf.scaleContent and _loadedSwf.maintainAspectRatio. These together were fun to figure out, but the end result was that my controls were scaling, and I didn't want that. If I turned off scaleContent, then nothing would resize. If I turned off aspect ration, then things started looking wonky.
because I had added my _loadedSwf to a SkinnableContainer, and that container was getting resized, I wanted my _loadedSwf to update to that container's size. On initialization I do use a method inside _loadedSwf. And to use that, I have something like the following:
var loadedSM:SystemManager = SystemManager(_loadedSwf.content)
loadedSM.application["updateDimensions"](container.width, container.height);
This worked great for the initial setup, but resizing still didn't work. I won't recount the countless hours I've tried to make it work. Needless to say, and the reward for reading this post is to see that to make this work, I did the following on the resizeMyApp(), called by the parent application whenever an EVENT.RESIZE_EVENT is dispatched:
_loadedSwf.content.width = container.width;
_loadedSwf.content.height = container.height;
Object(_loadedSwf.content).setActualSize(container.width, container.height);
loadedSM.application["updateDimensions"] (container.width, container.height);
I got the idea on page 48 of this manual (Thank you Matt Horn!!!)
http://livedocs.adobe.com/flex/3/loading_applications.pdf
These last 2 lines seem a bit hazy to me, but if I remove one of them, then the resizing doesn't work. I do have some jerkiness that I need to work out, but the overall resizing now commits correctly. I think there is something in the updateDisplayList() that I've missed, but somehow this makes the call work.
The problem I was running into is that my loaded swf was getting it's size clipped. This was unacceptable.
For example, if I loaded my swf into my app, if the window was sized at 700x400 (w x h), if I resized my window to something smaller, the controls inside the loaded swf would follow accordingly. However when I resized the window larger than 700x400, the controls would get clipped by an auto-assumed max size of the loaded swf's stage.
GRRRRRRR!!!!!!
So I have lost countless hours of sleep, including the time it's taking me to post this incoherent message. But I feel I must share about resizing a loaded swf without scaling. Right now I have some jerkiness in the movement, but it forces a scale and resize of the loaded swf's width and height.
I avoid using the _loadedSwf.scaleContent and _loadedSwf.maintainAspectRatio. These together were fun to figure out, but the end result was that my controls were scaling, and I didn't want that. If I turned off scaleContent, then nothing would resize. If I turned off aspect ration, then things started looking wonky.
because I had added my _loadedSwf to a SkinnableContainer, and that container was getting resized, I wanted my _loadedSwf to update to that container's size. On initialization I do use a method inside _loadedSwf. And to use that, I have something like the following:
var loadedSM:SystemManager = SystemManager(_loadedSwf.content)
loadedSM.application["updateDimensions"](container.width, container.height);
This worked great for the initial setup, but resizing still didn't work. I won't recount the countless hours I've tried to make it work. Needless to say, and the reward for reading this post is to see that to make this work, I did the following on the resizeMyApp(), called by the parent application whenever an EVENT.RESIZE_EVENT is dispatched:
_loadedSwf.content.width = container.width;
_loadedSwf.content.height = container.height;
Object(_loadedSwf.content).setActualSize(container.width, container.height);
loadedSM.application["updateDimensions"] (container.width, container.height);
I got the idea on page 48 of this manual (Thank you Matt Horn!!!)
http://livedocs.adobe.com/flex/3/loading_applications.pdf
These last 2 lines seem a bit hazy to me, but if I remove one of them, then the resizing doesn't work. I do have some jerkiness that I need to work out, but the overall resizing now commits correctly. I think there is something in the updateDisplayList() that I've missed, but somehow this makes the call work.
Monday, June 7, 2010
the iPhone, development, and Hedonism
Sorry, should’ve clarified...some emails were going around amongst my colleagues, and we were discussing the newest iPhone. While Apple is the king of cool right now, they're still stuck with a crappy cell phone provider that is worthless if you want your phone conversation to last longer than 30 seconds (about the average amount of time before an average call drops - with full signal strength, mind you).
For me, Flash happens to be a medium I work in, but I’m a Rich Internet Application developer, and HTML5 + javascript, or Flash + javascript, or Silverlight + javascript all can achieve the same thing (eventually)...My job is to make shit look cool (kinda like bouncing gradient balls using gravity to propel themselves through millions of particles of pixie dust (optimized by apparat, of course), all while synthetically growing and teaching you something about polymorphism, or something like that)
I don’t think the hedonistic value of owning an iPhone would actually improve my life in the least, aside from earning the respect and envy of toy collectors...I know I’m a luddite, because I don’t want a phone that surfs the web on a shoddy little screen (high res or not).
Smart phone or not, I hate surfing the web on tiny screens...watching a movie, or playing a game is ok, and getting some quick information distilled down to a quick blurb on twitter-like basis would be useful, but reading entire sites, surfing through the Nytimes, or even going to craigslist suck on these little screens (at least for someone like me with big fat fingers). The iPad comes closer for casual users, or people who don’t need a professional development environment, and just some connectedness...the iPhone (compared to the Incredible) is ok, but I’m not losing sleep.
I’ve got to get back to making cool shit happen on the screen (whichever size screen that may be).
Oh, and Hedonism is an amazing scotch by Compass Box. I really love their bottle of Peat monster, and they've got some yummy other bottles. Try them out if you can.
For me, Flash happens to be a medium I work in, but I’m a Rich Internet Application developer, and HTML5 + javascript, or Flash + javascript, or Silverlight + javascript all can achieve the same thing (eventually)...My job is to make shit look cool (kinda like bouncing gradient balls using gravity to propel themselves through millions of particles of pixie dust (optimized by apparat, of course), all while synthetically growing and teaching you something about polymorphism, or something like that)
I don’t think the hedonistic value of owning an iPhone would actually improve my life in the least, aside from earning the respect and envy of toy collectors...I know I’m a luddite, because I don’t want a phone that surfs the web on a shoddy little screen (high res or not).
Smart phone or not, I hate surfing the web on tiny screens...watching a movie, or playing a game is ok, and getting some quick information distilled down to a quick blurb on twitter-like basis would be useful, but reading entire sites, surfing through the Nytimes, or even going to craigslist suck on these little screens (at least for someone like me with big fat fingers). The iPad comes closer for casual users, or people who don’t need a professional development environment, and just some connectedness...the iPhone (compared to the Incredible) is ok, but I’m not losing sleep.
I’ve got to get back to making cool shit happen on the screen (whichever size screen that may be).
Oh, and Hedonism is an amazing scotch by Compass Box. I really love their bottle of Peat monster, and they've got some yummy other bottles. Try them out if you can.
Thursday, April 22, 2010
Getting Flex 3.6 SDK, Flashbuilder 4, Tomcat, and BlazeDS to all play nice?
Ok, I'll be honest, I haven't gotten Blaze to play nicely yet, but I haven't had anything to setup w/ it yet. I'm connecting to a previous setup that used Tomcat to connect to OLAP, and I'm recreating it in FB4 instead of Spring Suite tools. Much of my team prefers STS, but I am comfortable right now in my efficiency in FB3/4, so I blogged yesterday about wiring up the Flex 3.6 SDK
Connecting to a Tomcat server was the last hurdle before I get to a BlazeDS, and so I found this nice little plugin that I couldn't get from any other source. For some reason, Tomcat isn't supported easily on Eclipse 3.5, and I'm not a fan of the standalone Flash Builder. I prefer the Eclipse plugins, and found this would help me stay within the Eclipse.
http://www.eclipsetotale.com/tomcatPlugin.html#A3
This was a very nice find. I simply put the package in my eclipse plugin folder, and immediately when I restarted Eclipse, I had a Tomcat option on my toolbar. In the preferences pane (Command+,) I could point the plugin at my Tomcat install, and away I go.
Now I can setup keyboard shortcuts (like Command+shift+t) to start/restart, or stop Tomcat. The information from eclipsetotale is quite helpful, and I'm glad I came across it.
Now to get down to some hardcore devving
:)
Connecting to a Tomcat server was the last hurdle before I get to a BlazeDS, and so I found this nice little plugin that I couldn't get from any other source. For some reason, Tomcat isn't supported easily on Eclipse 3.5, and I'm not a fan of the standalone Flash Builder. I prefer the Eclipse plugins, and found this would help me stay within the Eclipse.
http://www.eclipsetotale.com/tomcatPlugin.html#A3
This was a very nice find. I simply put the package in my eclipse plugin folder, and immediately when I restarted Eclipse, I had a Tomcat option on my toolbar. In the preferences pane (Command+,) I could point the plugin at my Tomcat install, and away I go.
Now I can setup keyboard shortcuts (like Command+shift+t) to start/restart, or stop Tomcat. The information from eclipsetotale is quite helpful, and I'm glad I came across it.
Now to get down to some hardcore devving
:)
Wednesday, April 21, 2010
Getting up to speed on the latest Flex 3 SDK’s
This is not assuming you already have Flex 3 installed on your machine (eclipse plug-in or stand alone).
In order to do this and avoid buggy errors, the latest nightly build of Flex SDK 3.6 is what I’ve used successfully. I found one of many a bug which are annoying as all get out regarding comboboxes (which is why I prefer/recommend 3.6).
In order to get up and running quickly, download either the latest or 2nd to latest nightly build of SDK 3.6, found here from Adobe.
Inside your Flexbuilder sdk folder, create a folder for 3.6.0, something like this:
for Windows: C:\Program Files\Adobe\Flex Builder 3\sdks
for Mac: [I use eclipse w/ the plugin, but it’s probably something similar] /Applications/Adobe Flex Builder 3 Plug-in/sdks
Now install (or copy over) the newest SDK to this folder from the download.
Next you’ll need to download the data visualization package (and unit testing if you use that). While the latest build is for 3.5, you can use the package for 3.6 as well.
And instructions for where to copy the files from/to:
This helped me get the environment up and running quickly in 3.6. This can also apply to anyone developing using Flashbuilder 4 and working with SDK 3.x (for previous projects).
In order to do this and avoid buggy errors, the latest nightly build of Flex SDK 3.6 is what I’ve used successfully. I found one of many a bug which are annoying as all get out regarding comboboxes (which is why I prefer/recommend 3.6).
In order to get up and running quickly, download either the latest or 2nd to latest nightly build of SDK 3.6, found here from Adobe.
Inside your Flexbuilder sdk folder, create a folder for 3.6.0, something like this:
for Windows: C:\Program Files\Adobe\Flex Builder 3\sdks
for Mac: [I use eclipse w/ the plugin, but it’s probably something similar] /Applications/Adobe Flex Builder 3 Plug-in/sdks
Now install (or copy over) the newest SDK to this folder from the download.
Next you’ll need to download the data visualization package (and unit testing if you use that). While the latest build is for 3.5, you can use the package for 3.6 as well.
And instructions for where to copy the files from/to:
This helped me get the environment up and running quickly in 3.6. This can also apply to anyone developing using Flashbuilder 4 and working with SDK 3.x (for previous projects).
Monday, April 12, 2010
Creating an AIR Installer badge for Flex Devs
In building a recent app, the customer asked me to also make a flash badge for their installer. This way they could deploy the app installer, yet control the download of the AIR app. For me, the badge allows two things, control of the app's image, and some nice SEO. If you can get other sites to deploy your badge (which is a simple group of files), then you can get some nice cross linkage SEO (not to mention and SEO linking/MetaData you might have in the SWF that runs the installer), and also some good data.
So to create a Badge, use Adobe's sample badge which I found here (on my Mac):
/Applications/Adobe Flex Builder 3 Plug-in/sdks/3.6.0/samples.
After you copy it into your project's folder (or wherever you'll most effectively work with it), you'll need to open it in Flash to manipulate some of it. Now, I am not a Flash IDE user. It takes me quite some time to figure out what the heck timelines are, and what layers are doing where, but in all honesty, if I could just figure this out, I'm sure I could do some killer stuff in Flash that would help out my enterprise apps. Anyways, inside the group of items are .js, .html, .as, .swf, .jpg, and .fla. The .fla allows me some room for designing, creating, and manipulating my text area. Following Lee Brimelow's (http://www.gotoandlearn.com/play?id=56) example of making a tooltip in Flash (something I enjoy taking for granted in Flex), I built a hover over tooltip in my installer badge, as well as added some SEO in the metadata of the swf, and inside the jsp/html page.
It took me a few minutes to realize that the badge itself was generated from Flash, so once I got inside of Flash, and started tooling around, I found out I could easily automate, or graphically change around, things on my installer badge. And by using my own customized image, I could adjust inside the .fla what the image was to be shown, and could now use an animated .gif, or a .png, or (using the awesomeness of alchemy and ZaalLabs) 40+ image types.
Also, because the fla incorporates the as file, I adjusted a few settings there for some more seo, and used that to compile and push out my swf. bada-boom, bedaubing, I now have a kick-a$$ installer badge, with a custom logo, and I can mess around and adjust anything about the badge I want (including animation, or generative art, or what not). And the installer file is tiny (in comparison to a flex app, this thing was only about 6k when I was done). 6 friggin K. That's ridiculously small…I need to learn to make Flex apps that small.
Anyways, please enjoy hopefully these step by steps will help you make a better AIR app installer badge.
So to create a Badge, use Adobe's sample badge which I found here (on my Mac):
/Applications/Adobe Flex Builder 3 Plug-in/sdks/3.6.0/samples.
After you copy it into your project's folder (or wherever you'll most effectively work with it), you'll need to open it in Flash to manipulate some of it. Now, I am not a Flash IDE user. It takes me quite some time to figure out what the heck timelines are, and what layers are doing where, but in all honesty, if I could just figure this out, I'm sure I could do some killer stuff in Flash that would help out my enterprise apps. Anyways, inside the group of items are .js, .html, .as, .swf, .jpg, and .fla. The .fla allows me some room for designing, creating, and manipulating my text area. Following Lee Brimelow's (http://www.gotoandlearn.com/play?id=56) example of making a tooltip in Flash (something I enjoy taking for granted in Flex), I built a hover over tooltip in my installer badge, as well as added some SEO in the metadata of the swf, and inside the jsp/html page.
It took me a few minutes to realize that the badge itself was generated from Flash, so once I got inside of Flash, and started tooling around, I found out I could easily automate, or graphically change around, things on my installer badge. And by using my own customized image, I could adjust inside the .fla what the image was to be shown, and could now use an animated .gif, or a .png, or (using the awesomeness of alchemy and ZaalLabs) 40+ image types.
Also, because the fla incorporates the as file, I adjusted a few settings there for some more seo, and used that to compile and push out my swf. bada-boom, bedaubing, I now have a kick-a$$ installer badge, with a custom logo, and I can mess around and adjust anything about the badge I want (including animation, or generative art, or what not). And the installer file is tiny (in comparison to a flex app, this thing was only about 6k when I was done). 6 friggin K. That's ridiculously small…I need to learn to make Flex apps that small.
Anyways, please enjoy hopefully these step by steps will help you make a better AIR app installer badge.
Friday, March 19, 2010
Working w/ Global settings in Flash to get around Sandbox Security issue
I am working on an app that needs local resources and network resources. I was getting very frustrated during my development because I couldn't read the local setup file. Unfortunately, after a lot of digging around, the only reason I could find that the app wouldn't load was because the global settings for flash had been changed. Because these settings are only available by going online here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager02.html
or here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager03.html
or here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html
or here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager06.html
or here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager07.html
The following isn't a tab, but allow you to view set your player updates:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager05.html
Anyways, the annoyance for me is a couple of things:
1) why is this remote (aka why do I have to keep reloading a page to look at flash player settings inside of a flash swf?)
2) What is the garbage that Charles is recording going back and forth, and
3) where is this swf object located on my machine so that I may have some more control over it.
It's amazing to see what sites (intentionally visited or not - which includes pop-ups) that are stored in the global settings…I need to understand this more if I'm going to want more security for my machine.
Anyways, the point I had about this post was that the global security settings were causing me some problems in connecting my app to the intertubes. Once I made a checkmark on the Global Security Settings, I could actually see content and it resolved my problems (and all of this started as a search into possible cross domain issues, and not just my own irrational fears that someone might actually want to track all the websites I've been to and store private information about it without letting me know/delete/erase this stuff, manage my own security, etc…).
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager02.html
or here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager03.html
or here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html
or here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager06.html
or here:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager07.html
The following isn't a tab, but allow you to view set your player updates:
http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager05.html
Anyways, the annoyance for me is a couple of things:
1) why is this remote (aka why do I have to keep reloading a page to look at flash player settings inside of a flash swf?)
2) What is the garbage that Charles is recording going back and forth, and
3) where is this swf object located on my machine so that I may have some more control over it.
It's amazing to see what sites (intentionally visited or not - which includes pop-ups) that are stored in the global settings…I need to understand this more if I'm going to want more security for my machine.
Anyways, the point I had about this post was that the global security settings were causing me some problems in connecting my app to the intertubes. Once I made a checkmark on the Global Security Settings, I could actually see content and it resolved my problems (and all of this started as a search into possible cross domain issues, and not just my own irrational fears that someone might actually want to track all the websites I've been to and store private information about it without letting me know/delete/erase this stuff, manage my own security, etc…).
Sunday, February 14, 2010
Compiling Release Build in Flex - non-alerted memory error:
I use Eclipse with FB3 plug-in for all my development, and often can become the case with opportunistic applications, Eclipse will grab more and more memory. If I'm working on 2-3 apps at once, compiling and changing objects, I quickly lose up to 500MB to Eclipse. Garbage collection and heap status size are determined by the .ini file. When working on projects that have to embed a couple of fonts, I've had to increase the size, so that the compiler doesn't give me an out of memory error and ask me to close my workbench.
Well, to keep Eclipse from becoming a memory hog, I changed the runtime and max perm size to 128 respectively. This normally keeps Eclipse happy, running pretty quickly, and about as close to 300MB at runtime as I can keep it. Well, recently while building out a project, I tried to export my final build, and the application kept crashing or bombing out. The problem was that it wasn't telling me what was going on. It just kept stopping, and not giving me a reason why. I knew something was wrong because the release-bin folder remained empty.
Switching over to Eclipse's plug-in development, I checked the error logs (very, very important resource when Flex and Eclipse fail without giving you warning…). The error:
java.lang.reflect.InvocationTargetException
.
.
.
Caused by: java.lang.OutOfMemoryError: Java heap space
Root exception:
java.lang.OutOfMemoryError: Java heap space
Aha! Eureka - my answer lay in the fact that I had changed my workbench max and permanent size to something smaller than it could use, but it wouldn't tell me that. Why Eclipse, is there now message? Well, glad I know how to find the error log in Eclipse.
Hope this helps anyone else who's Release Build fails, and no answer/reason is given…
Well, to keep Eclipse from becoming a memory hog, I changed the runtime and max perm size to 128 respectively. This normally keeps Eclipse happy, running pretty quickly, and about as close to 300MB at runtime as I can keep it. Well, recently while building out a project, I tried to export my final build, and the application kept crashing or bombing out. The problem was that it wasn't telling me what was going on. It just kept stopping, and not giving me a reason why. I knew something was wrong because the release-bin folder remained empty.
Switching over to Eclipse's plug-in development, I checked the error logs (very, very important resource when Flex and Eclipse fail without giving you warning…). The error:
java.lang.reflect.InvocationTargetException
.
.
.
Caused by: java.lang.OutOfMemoryError: Java heap space
Root exception:
java.lang.OutOfMemoryError: Java heap space
Aha! Eureka - my answer lay in the fact that I had changed my workbench max and permanent size to something smaller than it could use, but it wouldn't tell me that. Why Eclipse, is there now message? Well, glad I know how to find the error log in Eclipse.
Hope this helps anyone else who's Release Build fails, and no answer/reason is given…
Thursday, February 4, 2010
Dynamically Showing Embedded Images in Flex
Dynamically Showing Embedded Images
Several resources will show how easy it is to embed an Image in Flex. You can embed inline, via meta tag, and another way (which I forgot right now). Regardless of any of these ways, they assume you always know when you are going to be using your embedded image, and don't have much flexibility if you want to dynamically change the image for a component based on something as arbitrary as mouseOver.
If you look at the profuse examples when googling, you come across many that show you how to embed inline:
<
<mx:Image id="img" source="{@Embed(source=assets/img.jpg)}" />
Or you can embed an image via metatag inside your class, and then call it explicitly in your component:
<mx:Metadata>
[Embed(source="assets/icons/myImg.png")]
public static const myImg:Class;
</mx:Metadata>
…
<mx:Image id="img" source="{myImg}" />
Or you can embed the object in another class, foo, and then reference it in your Image:
import location.for.assetClass.foo;
...
<mx:Image id="img" source="{foo.myImg}" />
More often than not, I like to go the third route, mainly because I want to be able to access the images from another class, or from multiple components. Now knowing how to embed images is great, but my quandary was, "What do I do if I have 30 or 100 small icons/images that I want to embed, and the component that is using the image doesn't know the embedded image to use until runtime, i.e. itemRenderer, or dynamically generated object using static icons (recycled buttons…)?"
For this example, I am using a simple list, with a custom itemRenderer. The list's dataprovider has an id and some other information for each record. In my customItemRenderer, I can get the data.id and use that to determine the picture I wanted to use. The only problem was, I have know idea how to call foo.myImg dynamically. I tried getClassByName(data.id), but it refused to cast my object to a class or would return null.
I really thought that because I had embedded my image, then cast it as a class, I'd be able to call it by name. Bummer!
Next I setup an array and a method inside of class foo. The array, called myAssets, is an array of all the classes inside of foo. The function was called from the itemRenderer, in init() to get the class for the image to assign it, as a ByteAsset, to the source for the image. Inside of foo, I have the following:
public function getClass(str:String):Class{
var s:String = "[class IconAssets_" + str + "]";
for (var i:int = 0; i < myAssets.length; i++){
var t:String = myAssets[i].toString();
trace(t);
if(s == t){
return myAssets[i];
}
}
return null;
}
I would pass in the data.id to the getClass(), and the return would be the class I needed. This actually worked, but seemed quite cumbersome, especially because now I was not only responsible for creating the embedded image, but also adding and maintaining an array for all objects. This seemed a bit extraneous, so I finally hit on a solution that let's me do this quickly and easily.
The most annoying part of all of this is either not knowing the correct syntax (because I'm a music major and am learning coding on my own), wording to search the world of Flex development blogs, or something else involving the continual error between seat and keyboard…
Anyways, the ultimate solution was actually quite easy.
Keeping the foo class with all my embedded images is fine, and in my itemRenderer, for the image, I just need to put the following for the source:
<mx:Image id="img" source="{foo[data.id]}" />
That's it! Probably too much time spent trying to figure this out, but in the end, the class is acting like an object, and I can get any of my "properties" out of the class pretty easily now. I struggled w/ this concept on an earlier project, but now that I have the quick fix to dynamically change the source of an image with an embedded image without having to hard code any values in the component is much, much better. Ok, so lesson learned, the answer wasn't that hard, but I needed to futz with the other possibilities before I could finally get it right. Now that I got it right, I promise I shouldn't get it wrong again*.
*I might, but that's all part of my slow learning.
Several resources will show how easy it is to embed an Image in Flex. You can embed inline, via meta tag, and another way (which I forgot right now). Regardless of any of these ways, they assume you always know when you are going to be using your embedded image, and don't have much flexibility if you want to dynamically change the image for a component based on something as arbitrary as mouseOver.
If you look at the profuse examples when googling, you come across many that show you how to embed inline:
<
<mx:Image id="img" source="{@Embed(source=assets/img.jpg)}" />
Or you can embed an image via metatag inside your class, and then call it explicitly in your component:
<mx:Metadata>
[Embed(source="assets/icons/myImg.png")]
public static const myImg:Class;
</mx:Metadata>
…
<mx:Image id="img" source="{myImg}" />
Or you can embed the object in another class, foo, and then reference it in your Image:
import location.for.assetClass.foo;
...
<mx:Image id="img" source="{foo.myImg}" />
More often than not, I like to go the third route, mainly because I want to be able to access the images from another class, or from multiple components. Now knowing how to embed images is great, but my quandary was, "What do I do if I have 30 or 100 small icons/images that I want to embed, and the component that is using the image doesn't know the embedded image to use until runtime, i.e. itemRenderer, or dynamically generated object using static icons (recycled buttons…)?"
For this example, I am using a simple list, with a custom itemRenderer. The list's dataprovider has an id and some other information for each record. In my customItemRenderer, I can get the data.id and use that to determine the picture I wanted to use. The only problem was, I have know idea how to call foo.myImg dynamically. I tried getClassByName(data.id), but it refused to cast my object to a class or would return null.
I really thought that because I had embedded my image, then cast it as a class, I'd be able to call it by name. Bummer!
Next I setup an array and a method inside of class foo. The array, called myAssets, is an array of all the classes inside of foo. The function was called from the itemRenderer, in init() to get the class for the image to assign it, as a ByteAsset, to the source for the image. Inside of foo, I have the following:
public function getClass(str:String):Class{
var s:String = "[class IconAssets_" + str + "]";
for (var i:int = 0; i < myAssets.length; i++){
var t:String = myAssets[i].toString();
trace(t);
if(s == t){
return myAssets[i];
}
}
return null;
}
I would pass in the data.id to the getClass(), and the return would be the class I needed. This actually worked, but seemed quite cumbersome, especially because now I was not only responsible for creating the embedded image, but also adding and maintaining an array for all objects. This seemed a bit extraneous, so I finally hit on a solution that let's me do this quickly and easily.
The most annoying part of all of this is either not knowing the correct syntax (because I'm a music major and am learning coding on my own), wording to search the world of Flex development blogs, or something else involving the continual error between seat and keyboard…
Anyways, the ultimate solution was actually quite easy.
Keeping the foo class with all my embedded images is fine, and in my itemRenderer, for the image, I just need to put the following for the source:
<mx:Image id="img" source="{foo[data.id]}" />
That's it! Probably too much time spent trying to figure this out, but in the end, the class is acting like an object, and I can get any of my "properties" out of the class pretty easily now. I struggled w/ this concept on an earlier project, but now that I have the quick fix to dynamically change the source of an image with an embedded image without having to hard code any values in the component is much, much better. Ok, so lesson learned, the answer wasn't that hard, but I needed to futz with the other possibilities before I could finally get it right. Now that I got it right, I promise I shouldn't get it wrong again*.
*I might, but that's all part of my slow learning.
Monday, January 25, 2010
Custom Buttons In Flex - Drop Shadow on Text
Here's some code:
In the class itself, I have to override the rollover and rollout so I can remove the drop shadow to give a different dynamic effect. Also, I have to override the updateDisplayList because the disabled buttons shouldn't have a drop shadow (again, just for fun).
/**Class**/
package com.studioNorth.skins{
import flash.display.DisplayObject;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import mx.controls.Button;
import mx.core.IUITextField;
import mx.core.UITextField;
public class CustomButtonTextDropShadow extends Button{
private var ds:DropShadowFilter; //This could be public so users could access and change it or any other variable
public function CustomButtonTextDropShadow(){
super();
ds = new DropShadowFilter(1);
}
override protected function rollOverHandler(event:MouseEvent):void{
textField.filters = null;
super.rollOverHandler(event);
}
override protected function rollOutHandler(event:MouseEvent):void{
super.rollOutHandler(event);
if(enabled)
textField.filters = [ds];
}
override protected function createChildren():void{
if (!textField){
textField = IUITextField(createInFontContext(UITextField));
textField.filters = [ds];
textField.styleName = this;
addChild(DisplayObject(textField));
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(!this.enabled){
textField.filters = null;
}
}
}
}
/**Main App**/
before mouse over:
during mouse over:
that simple!
Thursday, January 21, 2010
drawRoundRect in Flex is nice, but what about non-straight rectangular borders
rounded rectangles are nice, but...
Everyone wants at least one rounded rectangle corner these days in Flex…well, it's easy to do if you just want to define the corner radius for each corner. However, what do you do if you want to notch a side, extend another side, and still have the corners? Well, just drawing a rounded rectangle doesn't work, because you're now changing the shape of the object. Now I've gotta use the graphics.curveTo, moveTo, and lineTo methods to give me a cooler rectangular border (this might even work well for tabNavigatorButtons)
Because I'm big into programmatic skinning (it mainly just makes sense to me not to have to hardcode a project to specific images imported/exported from Flash or Illustrator or whatnot. I'd like my skins to be able to redraw themselves quickly and efficiently. For my project, I wanted to create rounded rectangles, but also have the notch. Using the drawRoundRectangle was a start, but I couldn't change anything else in the border. I searched and came across this guys article about dynamically creating shapes based on where you click on the canvas. Amazing idea which would be really neat to extend to the use of manipulating images or cutting anything on the canvas (think lasso or scissor tool in any image editing software by Adobe)
Anyways, to create the rectangle with rounded corners and non-straight borders, I abused the example from Adobe and added my own flair. You need the plotPoints part to make the rectangle draw everything, including the corners. In addition, I had to adjust for my 3 rounded corners, which include curveTo functionality. That was the trickier part, but in the end, got me a programmatic skin with notches…yippee!!!
package your.package
{
import flash.filters.BitmapFilterQuality;
import flash.filters.DropShadowFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import mx.graphics.RectangularDropShadow;
import mx.skins.RectangularBorder;
public class CustomContainerBorderSkin extends RectangularBorder {
private var dropShadow:RectangularDropShadow;
private var _points:Array = [];
private var rect:Rectangle;
// Constructor.
public function CustomContainerBorderSkin() {
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
var cornerRadius:Number = getStyle("cornerRadius");
var backgroundColor:int = getStyle("backgroundColor");
var backgroundAlpha:Number = getStyle("backgroundAlpha");
graphics.clear();
var indent:Number = 10;
plotPoints(indent);
graphics.beginFill(backgroundColor,1);
graphics.moveTo(_points[0].x, _points[0].y);
for (var i:int = 0; i < _points.length; i++) {
if(i == 2 || i == 7 || i == 9){
switch(i){
case(2):
graphics.curveTo(x + width, y, _points[i].x, _points[i].y);
break;
case(7):
graphics.curveTo(x + width, y + height, _points[i].x, _points[i].y);
break;
case(9):
graphics.curveTo(x, y + height, _points[i].x, _points[i].y);
break;
}
}else{
graphics.lineTo(_points[i].x, _points[i].y);
}
}
graphics.lineTo(_points[0].x, _points[0].y);
graphics.endFill();
parentObj = null;
}
private function plotPoints(n:Number):void {
_points = [];
_points.push(new Point(x, y)); //0 topLeft
_points.push(new Point(x + width - 10 , y)); //1 topRight curve from
_points.push(new Point(x + width , y + 10)); //2 topRight curve to
_points.push(new Point(x + width , y + height - 45)); //3 indent begin
_points.push(new Point(x + width - n , y + height - 35)); //4 indent point
_points.push(new Point(x + width , y + height - 25)); //5 indent end
_points.push(new Point(x + width , y + height - 10)); //6 bottomRight curve from
_points.push(new Point(x + width - 10 , y + height)); //7 bottomRight curve to
_points.push(new Point(x + 10 , y + height)); //8 bottomLeft curve from
_points.push(new Point(x , y + height - 10)); //9 bottomLeft curve to
}
private function getBitmapFilter():DropShadowFilter {
var distance:Number = 2;
var angle:Number = 45;
var color:Number = 0x000000;
var alpha:Number = .5;
var blurX:Number = 8;
var blurY:Number = 8;
var strength:Number = 0.65;
var quality:Number = BitmapFilterQuality.LOW;
var inner:Boolean = false;
var knockout:Boolean = false;
return new DropShadowFilter(distance, angle, color, alpha,
blurX, blurY, strength, quality, inner, knockout);
}
}
}
Everyone wants at least one rounded rectangle corner these days in Flex…well, it's easy to do if you just want to define the corner radius for each corner. However, what do you do if you want to notch a side, extend another side, and still have the corners? Well, just drawing a rounded rectangle doesn't work, because you're now changing the shape of the object. Now I've gotta use the graphics.curveTo, moveTo, and lineTo methods to give me a cooler rectangular border (this might even work well for tabNavigatorButtons)
Because I'm big into programmatic skinning (it mainly just makes sense to me not to have to hardcode a project to specific images imported/exported from Flash or Illustrator or whatnot. I'd like my skins to be able to redraw themselves quickly and efficiently. For my project, I wanted to create rounded rectangles, but also have the notch. Using the drawRoundRectangle was a start, but I couldn't change anything else in the border. I searched and came across this guys article about dynamically creating shapes based on where you click on the canvas. Amazing idea which would be really neat to extend to the use of manipulating images or cutting anything on the canvas (think lasso or scissor tool in any image editing software by Adobe)
Anyways, to create the rectangle with rounded corners and non-straight borders, I abused the example from Adobe and added my own flair. You need the plotPoints part to make the rectangle draw everything, including the corners. In addition, I had to adjust for my 3 rounded corners, which include curveTo functionality. That was the trickier part, but in the end, got me a programmatic skin with notches…yippee!!!
package your.package
{
import flash.filters.BitmapFilterQuality;
import flash.filters.DropShadowFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import mx.graphics.RectangularDropShadow;
import mx.skins.RectangularBorder;
public class CustomContainerBorderSkin extends RectangularBorder {
private var dropShadow:RectangularDropShadow;
private var _points:Array = [];
private var rect:Rectangle;
// Constructor.
public function CustomContainerBorderSkin() {
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
var cornerRadius:Number = getStyle("cornerRadius");
var backgroundColor:int = getStyle("backgroundColor");
var backgroundAlpha:Number = getStyle("backgroundAlpha");
graphics.clear();
var indent:Number = 10;
plotPoints(indent);
graphics.beginFill(backgroundColor,1);
graphics.moveTo(_points[0].x, _points[0].y);
for (var i:int = 0; i < _points.length; i++) {
if(i == 2 || i == 7 || i == 9){
switch(i){
case(2):
graphics.curveTo(x + width, y, _points[i].x, _points[i].y);
break;
case(7):
graphics.curveTo(x + width, y + height, _points[i].x, _points[i].y);
break;
case(9):
graphics.curveTo(x, y + height, _points[i].x, _points[i].y);
break;
}
}else{
graphics.lineTo(_points[i].x, _points[i].y);
}
}
graphics.lineTo(_points[0].x, _points[0].y);
graphics.endFill();
parentObj = null;
}
private function plotPoints(n:Number):void {
_points = [];
_points.push(new Point(x, y)); //0 topLeft
_points.push(new Point(x + width - 10 , y)); //1 topRight curve from
_points.push(new Point(x + width , y + 10)); //2 topRight curve to
_points.push(new Point(x + width , y + height - 45)); //3 indent begin
_points.push(new Point(x + width - n , y + height - 35)); //4 indent point
_points.push(new Point(x + width , y + height - 25)); //5 indent end
_points.push(new Point(x + width , y + height - 10)); //6 bottomRight curve from
_points.push(new Point(x + width - 10 , y + height)); //7 bottomRight curve to
_points.push(new Point(x + 10 , y + height)); //8 bottomLeft curve from
_points.push(new Point(x , y + height - 10)); //9 bottomLeft curve to
}
private function getBitmapFilter():DropShadowFilter {
var distance:Number = 2;
var angle:Number = 45;
var color:Number = 0x000000;
var alpha:Number = .5;
var blurX:Number = 8;
var blurY:Number = 8;
var strength:Number = 0.65;
var quality:Number = BitmapFilterQuality.LOW;
var inner:Boolean = false;
var knockout:Boolean = false;
return new DropShadowFilter(distance, angle, color, alpha,
blurX, blurY, strength, quality, inner, knockout);
}
}
}
Friday, January 15, 2010
Eclipse Navigator Link with Editor
This as a small setting that I made about 6 months ago, forgot where I did it, and about 2 days later, regretted ever making this change. I hate having my navigator bounce around all the time every time I change a tab, so this was annoying as all get out. Stoopid me, I didn't find it again until my co-worker showed me this link. It was for something completely different (i.e. hiding .svn folders, but on a Windows machine, however on my mac svn files are hidden in Eclipse). Needless to say, I saw that example image, with the term 'Link with Editor'. My eyes misted and I got very smiley, as my co-worker accidentally solved my problem (and he just wanted to help me hide the hidden .svn folders). Oh well. Glad I'm back on a more efficient route!
Wednesday, January 13, 2010
Flex Builder error: The project properties files could not be read.
My recent flex adventure almost came to a crashing end when I shut down and restarted Eclipse, only to find that my file's project properties could no longer be read?!?! I got very angry trying to figure out what happened, thinking to myself that I recently tried committing my project to SVN via subclipse (which is another story on its own). One thing I'm very happy I did was create a backup before trying to commit. Pretty much every time I tried to open my project I got the project properties files could not be read. I looked at the .actionScript and .project files, and couldn't see anything missing. I looked high and low, and ran a -diff on my project and the backup copy. Turns out, I was missing the .flexProperties file. How that got deleted from the project I don't know, but it was horrifyingly maddening to only get a mystic message saying the project properties files could not be read. Which files?!? A better message would be preferred, but alas, I copied the old over to the project folder, and I'm back in shape. Lesson learned, if you get this error, make sure you have all three project files in the correct location (aka CYA).
Thanks to Ben Clinkenbeard and Eric Hélier for getting me in the right direction!
Thanks to Ben Clinkenbeard and Eric Hélier for getting me in the right direction!
Monday, January 11, 2010
Massive amounts of memory consumption via image swapping in Flex
On my project, I was using De MonsterDebugger (DMD) (great tool, easy to implement, but can get heavy if you don't have a lot of RAM - peaks at about 150MB for me, which can hurt because I'm running on only 2 GB). In my project, I am rolling over canvases, and on each rollover, the background of the application should have its images change. My initial development had me doing this by changing the style of the Application (application.setStyle("backgroundImage",assets/myNewImg)). And to make the transition smooth, I had a second Image that I was using on top of the background, but underneath all the other components (z level = lowest possible).
The problem quickly became clear (even more so w/ DMD because I could see why my computer would stop responding when debugging, i.e. my RAM usage was spiking). In the last several days I have been reading about garbage collection (GC) and how it seems to act on its own accord. It was happening w/ my app, which would always return to about 40MB in runtime, but could (and often did) spike upwards of 250MB!!! All that for a single swf file running in Safari. I checked my objects, commented out different things (including custom turtle border graphics), and went through item by item that could've ran up so much RAM.
Finally it came back to my images being swapped in and out. I thought the image class could handle changing sources quickly, but it turns out, that was eating huge resources to render the image (all while doing some lightweight tweening). I tried my best to build this application to follow OOP and reusability as best as I could. The data source (an xml config file) is what drives the layout and information of the app, so I wanted to avoid embedding anything that needed to be called up explicitly w/ a case/if. But alas, I could only do so much before I had to make some exceptions in my class and embed the background images, and use a case statement to assign it correctly on hover. Once here, and once I realized that changing two background images (one stacked on the other to allow me to transition smoothly - read fade - meant I needed two images).
My app now only spikes at about 68MB, no matter how many transitions I make, and I don't have to try to force GC (which eventually happens during idle time). The last thing I think I'd like to try is possibly improving the cpu performance and keeping the fan from getting hot by adjusting frame rate, but for now, I'm happy that my app doesn't spike so much anymore.
The problem quickly became clear (even more so w/ DMD because I could see why my computer would stop responding when debugging, i.e. my RAM usage was spiking). In the last several days I have been reading about garbage collection (GC) and how it seems to act on its own accord. It was happening w/ my app, which would always return to about 40MB in runtime, but could (and often did) spike upwards of 250MB!!! All that for a single swf file running in Safari. I checked my objects, commented out different things (including custom turtle border graphics), and went through item by item that could've ran up so much RAM.
Finally it came back to my images being swapped in and out. I thought the image class could handle changing sources quickly, but it turns out, that was eating huge resources to render the image (all while doing some lightweight tweening). I tried my best to build this application to follow OOP and reusability as best as I could. The data source (an xml config file) is what drives the layout and information of the app, so I wanted to avoid embedding anything that needed to be called up explicitly w/ a case/if. But alas, I could only do so much before I had to make some exceptions in my class and embed the background images, and use a case statement to assign it correctly on hover. Once here, and once I realized that changing two background images (one stacked on the other to allow me to transition smoothly - read fade - meant I needed two images).
My app now only spikes at about 68MB, no matter how many transitions I make, and I don't have to try to force GC (which eventually happens during idle time). The last thing I think I'd like to try is possibly improving the cpu performance and keeping the fan from getting hot by adjusting frame rate, but for now, I'm happy that my app doesn't spike so much anymore.
Thursday, January 7, 2010
Smooth scrolling of a horizontallist
So I tried various makes of horizontal scrolling a horizontallist. I followed these examples, yet either my canvas never added the hlist (because the canvas initialized after I added the hlist, so the hlist was garbage collected before it's parent was initialized), or the scroll bar never moved the list (although I came close to rewriting the scrollhandler function. Suffice it to say, finally my hack involved adding the hlist to my canvas through a calllater(addHList), and then having external buttons be able to scroll my hlist left and right a designated amount based not on the scroll bar of the parent canvas, but on the x coordinate of my hlist. Simple enough! I don't need to worry about overriding the location of the scroll bar, and now i can use something like tweenmax to handle the transitioning of the horizontal lists position, so i get scrolling, and external buttons to move my hlist, and i get all the benefits of an hlist (which has as many columns as i need because i set its columncount = dataprovider.length. if anyone wants to see code, let me know and i'll post an update.
private function scrollHorizontalList(e:Event):void{
var dir:String = e.currentTarget.name;
var end:int;
var pos:int = hList.x;
var max:int = hList.dataProvider.length;
var myTween:TweenMax;
trace(dir);
if(dir == "rButton"){
end = pos + colWidth;
if(!TweenMax.isTweening(hList)){
//if(hList.x-colWidth*colsToScroll)
myTween = new TweenMax(hList,1,{x: hList.x - colWidth*colsToScroll, ease:Cubic.easeInOut});
myTween.play();
hListScroll+=colsToScroll;
}
} else if (dir == "lButton") {
end = pos - colWidth;
if(!TweenMax.isTweening(hList)){
myTween = new TweenMax(hList,1,{x: hList.x + colWidth*colsToScroll, ease:Cubic.easeInOut});
myTween.play();
hListScroll-=colsToScroll;
}
}
lButton.enabled = (hListScroll > 0)?true:false;
rButton.enabled = (hListScroll < max-colsToScroll)?true:false;
}
private function scrollHorizontalList(e:Event):void{
var dir:String = e.currentTarget.name;
var end:int;
var pos:int = hList.x;
var max:int = hList.dataProvider.length;
var myTween:TweenMax;
trace(dir);
if(dir == "rButton"){
end = pos + colWidth;
if(!TweenMax.isTweening(hList)){
//if(hList.x-colWidth*colsToScroll)
myTween = new TweenMax(hList,1,{x: hList.x - colWidth*colsToScroll, ease:Cubic.easeInOut});
myTween.play();
hListScroll+=colsToScroll;
}
} else if (dir == "lButton") {
end = pos - colWidth;
if(!TweenMax.isTweening(hList)){
myTween = new TweenMax(hList,1,{x: hList.x + colWidth*colsToScroll, ease:Cubic.easeInOut});
myTween.play();
hListScroll-=colsToScroll;
}
}
lButton.enabled = (hListScroll > 0)?true:false;
rButton.enabled = (hListScroll < max-colsToScroll)?true:false;
}
Tuesday, January 5, 2010
Eclipse .ini changes
FB3 breaks then fixes, all because I forgot an 'm' in my init file. Actually, I was trying to change the min, max, and permanent sizes of my eclipse runtime, and I accidentally deleted one of the 'm's, and then eclipse never started or worked for me again. I got really angry, wasted 30 minutes trying to figure out what happened, including trying to read the logs and see where it went wrong, and finally decided to skip ahead and reinstall eclipse (3.4.2 of course, as FB3 won't work on 3.5, although some have figured it out…) So long story short, I reinstalled, did the software update to re-attach FB3 plugin (the new 3.5 sdk rocks!), and then couldn't get SVN to attach via subclipse. Another half hour later, and I returned to my .ini file, checked it against my old install, found the missing 'm', almost kicked myself, fixed the 'm', and now I have everything back in order…how annoying! Although, now Aptana makes things a bit slower...anyone else having that problem?
Subscribe to:
Posts (Atom)