Flex/Flash/Actionscript

Using hitTestPoint or hitTest on Transparent PNG images

On a previous unrelated blog post, someone posted a comment that had to do with using the hitTestPoint() method with transparent images. I was about to respond by saying I don’t have any experience playing with hitTestPoint, I’m not sure why that question was posted to my unrelated post, and I don’t have an answer. While I was formulating my response in my head, I read up a bit on hitTestPoint (in the DisplayObject class) and hitTest (in BitmapData). And before I got done figuring out how to phrase “I don’t know, go ask someone else,” I thought that maybe I actually did know and figured it would be interesting to investigate a solution.

So here’s my take on DisplayObject.hitTestPoint() and BitmapData.hitTest(). At the end of the post is an example that does some hit testing on two images, one is saved as a transparent PNG and one as a SWF.

hitTestPoint


DisplayObject.hitTestPoint(x:Number, y:Number, shapeFlag:Boolean = false)

This method returns true if the point is over a transparent area of a bitmap image. Using the shapeFlag boolean makes it so the method returns false over an area of a vector image that has no shape. This is not the same thing as a transparent pixel of a bitmap image. It might be a little confusing in the documentation, but I think it makes sense (maybe it needs a sentence or two of clarification). Basically in a vector image you have no data in transparent areas. In a bitmap image there is a pixel there, and that pixel has an alpha value of 0. But that’s actually different than not having anything taking up that x,y coordinate. So the term “shapeFlag” does in fact only refer to shapes in vector images. Thank god they didn’t call it “transparentFlag” or something like that since that would make it even more confusing. It’s not about transparent pixels versus opaque pixels. It’s about “is there something there or not,” and a transparent pixel is still a pixel.

hitTest


BitmapData.hitTest(firstPoint:Point, firstAlphaThreshold:uint, 
         secondObject:Object, secondBitmapDataPoint:Point = null, 
         secondAlphaThreshold:uint = 1):Boolean

This function is confusing as hell, and I strongly suggest Adobe write some further documentation with a few examples on how to use this. This is a powerful function because you can test for a hit between a BitmapData object and multiple other types of objects (a Point, Rectangle, or another BitmapData). But it’s hard to figure out how to use it. Like, wtf does the first parameter mean (firstPoint)? I think it’s only used if you’re testing between one BitmapData and a second BitmapData. I was interested in testing a BitmapData against a point, so I just passed a point of 0,0 and it seemed to work right.

But anyway, griping about documentation aside, these two methods are different. If you’re interested in testing for a hit on a bitmap image and you don’t want to count the transparent areas, then you must use BitmapData.hitTest. You cannot use DisplayObject.hitTestPoint because that will return true for transparent pixels.

So I’ve made a simple utility class that solves this problem. I called it HitTester and what it does is it first checks for a hit using DisplayObject.hitTestPoint. If that returns true it means we’re at least within the bounding box of the image. Then it checks using BitmapData.hitTest. To do this it creates a temporary BitmapData object for the Image and runs the hitTest method.

To use the class you do something like this:

HitTester.realHitTest(image1, new Point(event.stageX, event.stageY));

The example below shows using the DisplayObject.hitTestPoint versus using my HitTester utility class. Move your mouse over the images and you can see the hit test results. Both images are basically the same, but I saved the left one as a transparent PNG and the right one is a SWF. You’ll see that the normal hitTest Point method works to accurately test for opaque areas of the SWF, but not for the PNG. The HitTest class basically just makes the hit testing of the PNG work like it does for the SWF.

View the source.

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

Building a Gantt Chart Component in Flex

Here’s my intial attempt at making something that resembles a Gantt chart. There’s been some good discussion about this recently on flexcoders. People have suggested a few different ways of making a Gantt chart. Here I’ll outline the main ideas that have been thrown around and then I’ll go over the example that I came up with.

Option 1: Use the DataGrid as the base. This was the approach that Andrew Trice used. This is also the approach that I took, see the example below. The idea here is that each row of the DataGrid will serve as each item of the Gantt chart, and all we need to do is specify a custom itemRenderer to display it.

Option 2: Use the charting classes as the base. Ely Greenfield’s got an example of making a chart similar to a Gantt chart (follow the link and find: Series Type >> Columns and Bars >> Floating Bars). The basic idea here is that you use the chart classes and extend them to turn them into a Gantt chart. I decided against this because 1) I haven’t investigated custom charting and reading Ely’s blog makes it seem fairly complicated (Ely, I know you try to make it easy for us 🙂 ) and 2) I liked the itemRenderer and itemEditor approach that a DataGrid takes, which would allow me to have editable controls in there.

Option 3: Use the scheduling framework from Adobe Consulting as the base. I really like this idea. It was mentioned on flexcoders after I started working on a solution using DataGrid, but I think this way is definitely worth exploring. I haven’t played with the scheduling framework yet, but at first glance it seems like much of the work they did for that would carry over very well for a Gantt chart.

So like I said, I went with the DataGrid option. The basic idea is the same as on Andrew Trice’s post, I just went a little further. In my example you can manipulate the data in the chart. Each item is represented by a slider that allows you to adjust the starting point, the end point, and the percent complete for each task. To try this in the example just click on one of the items and the slider thumbs should appear.

Another cool thing this shows is some skinning and customization of the Slider component. To get these sliders looking like they do I had to make the Slider apply different skins to the first, second, and third thumbs. I also needed different highlighting skins for the two portions of the slider track. And you can drag the entire region (that’s something that came from a previous post about draggable sliders). Deep down those are just Slider components, but they look and act fairly differently.

So I’m not going to go into heavy duty explanation of how this works. And I didn’t comment the code up very much (if at all). It’s not complete by any means, no axis is shown, etc. This is sort of my first draft and if you want to download the source and figure it out for yourself, go for it.

The example below shows a gantt chart with my plans for world domination. There are two charts here with the same data, but they show different skinning options.

View the source.

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

Problem with Transparent PNGs in Flex using @Embed

This was posted to flexcoders today. Here’s the problem: we’ve got a transparent PNG that is loaded into a <mx:Image /> control. Normally this control handles PNG transparency just fine. However, someone posted an example of a problematic PNG. If you set the source of the Image control to use the URL for the PNG on the server, then the image loads fine with transparency. But if you try to embed the image using the @Embed syntax, then the transparency is ignored and an ugly background color shows up.

I don’t know really exactly where the problem lies. The Image component (which is really just a glorified SWFLoader) should load the exact same image whether it’s loading from a URL or an embedded asset. But it doesn’t, and the test case posted on flexcoders proves this. Now, whether there’s something weird about the image I have no idea. But the fact is that it should have transparency and using @Embed within an Image component breaks the transparency.

So here’s a solution. Basically what I did was extend the SWFLoader class and change part of the loadContent() method. To do this I had to make a copy of the SWFLoader class (I called it BaseSWFLoader) and change the needed methods to protected instead of private. Once I did that I was able to create a subclass that could override loadContent and act differently for embedded assets.

The approach I took was to get the ByteArray of the embedded asset, then load that ByteArray using the loadBytes method of the Loader class. When I tried loading the problematic embedded PNG using loadBytes, it magically loaded fine with the transparency.

There’s a trick here, which is to set the mimeType of the embedded asset. If you set the mimeType to application/octet-stream, then when it gets handled by the custom ByteArraySwfLoader class I created we can get access to the raw ByteArray of the embedded asset. This means we can pass the ByteArray to a Loader component, which will be able to handle it using the loadBytes() method. If you don’t set the mimeType of the embedded asset then you don’t get the ByteArray of the asset, instead you just get a Bitmap object.

The small example below shows the problematic PNG loaded using both the <Image /> control and my custom class. Both work fine if we’re loading via a URL. But if we’re loading by using the @Embed syntax then the normal Image component messes up the transparency.

View the source.

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

Horizontal Accordion Component for Flex

People have asked for an Accordion component that lays itself out horizontally instead of vertically. Looks like Scott Barnes had put one together back in 2005 that worked for Flex 1.5. Seeing as he’s now as Microsoft I’d say the chances of him porting it to Flex 2 are zip. Others seem to be trying to make this component as well. Well, here it is, an accordion component that cascades horizontally for Flex 2.

You use it just like the normal accordion component. The only difference is now you can use the “headerWidth” style instead of headerHeight to set the width of the tabs in CSS.

Making the component wasn’t that difficult, but it required a complete copy/paste of the Accordion component. If you look at the source you’ll see that I’ve made a class called AccordionBase. Basically this base class is a straight copy of the Accordion class from the framework but modified to allow it to be extended easier. That means I changed a bunch of properties and methods that were private to protected, so my subclasses could access them. Once I made these changes the only other thing I did to AccordionBase was remove the updateDisplayList and measure methods. These methods are defined in the subclasses, which are HAccordion and VAccordion. Each of those subclasses has slightly different code to do the layout and tweening. Ideally I would have been able to do this without making a new AccordionBase class that duplicated the code of Accordion, but this is another instance where a simple extension of a class doesn’t give you enough access to the parent class.

The one important thing to be aware of is that you MUST embed the font that you’ll be using for the text of the HAccordion’s headers. The component rotates the headers by 90 degrees, and if you rotate a text component then it will only work if you have the font embedded. See the source of the example MXML file to see how I did this, it’s simple, but if you don’t do it you’ll be wondering why the headers are all blank.

I packaged the component as a SWC. You can download the SWC and drop it into a Flex project. Download the SWC here. (281 K)

Here’s the full source of the component. And here’s the source of the example MXML file that makes the example below.

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

Even Better Scrollable Menus for Flex

Here’s an update to the Flex Scrollable Menu controls that I posted earlier today. Josh Tynjala made the point that he would rather have up and down arrows at the top and bottom of the menus to allow you to scroll without using a scrollbar on the side. Well, ok, ok, here you go. Now the menus can have either a vertical scrollbar on the side, rollover arrows on the top and bottom, or both! Yay!

Also, if you don’t specify a maxHeight for the controls, then the menus get sized as high as they can without going off the stage. So if a menu is too big it will size itself to as high as it can, and then start scrolling. If you specify the maxHeight attribute for the controls then the menu will try to size itself that high, but not higher. But again, if there’s not enough room on the stage then the menu won’t grow beyond the visible area. As far as I can figure, this is how menus should work.

So check it out and play with some of the options in the example. You can set both verticalScrollPolicy and a new property: arrowScrollPolicy. Both work the same way as you’d expect. arrowScrollPolicy controls the display of the up/down arrows just like the scrollbar is controlled. So you can set arrowScrollPolicy to ScrollPolicy.ON, ScrollPolicy.AUTO, and ScrollPolicy.OFF. If you turn both the arrows and the scrollbar on then you can scroll using either of them.

And again, full source is here.

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

Scrollable Menu Controls

As I was writing some stuff for the extended TabNavigator component that I’ve been working on (see some previous posts), I came across a need to use a PopUpMenuButton to list all the tabs, similar to how Firefox does this with the drop down list to the right of the tabs. This works great, except when there are a ton of tabs and the list gets really really long. Suddenly I realized that all the Menu controls in Flex have no option of adding a scrollbar to the menus. So if your menu is huge and goes off the stage, there’s nothing you can do about it and the menu items at the bottom are completely inaccessible.

mx.controls.Menu
So the complete inability to scroll a menu seemed a little weird to me, so I investigated and took a look into the mx.controls.Menu class. The answer to why the menus would never scroll is pretty obvious once you look at the code for the Menu control. The getter and setter for verticalScrollPolicy are these:


override public function get verticalScrollPolicy():String {
	return ScrollPolicy.OFF;
}

override public function set verticalScrollPolicy(value:String):void {
}

So if you were to try to set the verticalScrollPolicy of a Menu to ScrollPolicy.ON or ScrollPolicy.AUTO it wouldn’t do anything, and the scrollbars would remain off. There are a few other pieces in the code for Menu that don’t allow scrollbars, particularly in the configureScrollBars() and measure() methods.

So that’s no good if you want to allow scrollbars on your menus. The solution? An extension of mx.controls.Menu that overrides these problematic parts of the code. Basically I re-instituted the normal functionality for the getter and setter for verticalScrollPolicy, changed the configureScrollBars() method to actually configure the scrolling, and then modified measure() to take the scrollbars and new height restriction into account. Then we’ve got a new ScrollableMenu class that will allow you to set the maxHeight property. If the menu goes beyond maxHeight then the scrollbars are added, just like a normal scrolling control.

mx.controls.MenuBar
I also created a class that extended the MenuBar class, so it would use my new ScrollableMenu instead of the normal Menu when it created the Menus for the MenuBar. I was able to keep this extension fairly short, mostly just with an override of getMenuAt() and a private menu event listener.

So com.dougmccune.controls.ScrollableMenuBar lets you use the MenuBar control and specify a maxHeight, which will put a height limitation on the menus that popup when you click a menu item.

mx.controls.PopUpMenuButton
The PopUpMenuButton class was trickier. I initially tried to do a simple extension and get it to use the ScrollableMenu class instead of the normal Menu class, but this didn’t work so well. This was one of those cases (I’ve encountered this quite a bit) where the class you’re extending has private functions and variables that you need access to in order to accomplish your goals. I really didn’t need to make many changes to PopUpMenuButton, but because of the structure of the class I simply wasn’t able to make a clean extension.

So instead of extending PopUpMenuButton I had to copy/paste the entire class into a new class, and make the changes I needed. I’ve had to do this quite a few times to get custom components that I need. It’s obviously not ideal, you end up bloating your code base, but sometimes that’s the only option. But in the end we have a ScrollablePopUpMenuButton class that allows us to specify a maxHeight and that height will apply to all menus and submenus.

I’ve included the full source of all of these classes and the example below. I documented the code pretty well, so hopefully you can figure it out by taking a look. I wasn’t planning on uploading this one to Adobe Exchange, it doesn’t seem quite “componenty” enough. But if someone from Adobe thinks it belongs on the exchange then I’ll upload it, let me know in the comments.

View the source. UPDATE: See the next post for the current source of the component.

Here’s the example:

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

Vertical MenuBar Component

Someone on the Adobe Flex forum asked a question about being able to have vertical menus using a MenuBar component. The response from Peter Ent from Adobe was that no, Flex does not include a MenuBar component that can handle vertical menus, but feel free to make one yourself and post it <hint, hint>.

After I read that it felt like a challenge, so here’s the solution: a Vertical MenuBar component. It extends MenuBar and works the same way, except the Menu items are stacked vertically and the menus open up either to the left or to the right of the menu bar. I’ve included the full source, it uses two classes, one that’s an extension of mx.controls.MenuBar, and another one that’s an extension of mx.controls.menuClasses.MenuItemRenderer. You can specify whether you want the menu to open to the left or the right by using the new direction property of the new component.

I tried to document the code really well, so it should be fairly straightforward if you take a look. I managed to get around needing access to all the private methods of MenuBar by repositioning the menus after they are placed on the stage and are shown. The instant they’re shown they’re moved to the right position. The one caveat is that this breaks the openDuration style of the Menu. If openDuration is set to use a Tween to animate the Menu opening, then I was stuck with showing the Menu during the Tween in the original position, then it would jump to the new correct position after the Tween finished. So you would see the Menu jump around after it opened, which was no good. So now openDuration cannot be used with the Vertical MenuBar, but I figure that’s not a big deal.

View the source.

Here’s the example showing both the normal MenuBar component on the top, and then two versions of the Vertical MenuBar, one that opens to the right and one that opens to the left.

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

The Quest for the Perfect Tab Navigator – Part 2

Here’s my progress on coming up with a TabNavigator component with all the features I’ve heard people talking about.

  1. Drag the tabs to re-order them. An indicator appears showing you where the tabs will be dropped. You can drop tabs before or after any other tab currently in the list
  2. Closable tabs. Click the close icon on each tab to remove it.
  3. List of tabs in a drop-down menu on the right. I’ve changed it now so the menu won’t go off the screen. It adds a scrollbar to the menu if it gets too long.
  4. If you don’t specify a tabWidth, the tabs are all at their own default widths.
  5. If there are too many tabs to fit the component first tries to squeeze the tabs in by making them smaller. You can set minTabWidth, which specifies the smallest that the tabs are allowed to be squeezed down to. If the tabs can’t be squeezed more then scrolling occurs (next point)
  6. Scrollable tabs. If the number of tabs is too many to fit, then arrow icons appear on the left and right side that allow you to scroll through all available tabs.

There are some definite bugs, especially when it comes to trying to set tabWidth and minTabWidth. Once I upload the source in the next day or so maybe someone else can figure it out.

So that’s pretty much where I’m at. Hopefully I’ll post the code tomorrow once I get around to cleaning it up a tiny bit more. Here’s the example of the current component. If you’ve got any more feature requests just post them in the comments and I’ll see if I can include them. Cool.

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

The Quest for the Perfect TabNavigator

[UPDATE: See Part 2 for the current component]

There’s been some discussion on flexcoders about a better TabNavigator component. And a few people have done some good stuff expanding on the original TabNavigator in the Flex framework. I figured I’d play around and try to add a little to the current TabNavigator modifications that are floating around.

First, a few references. Here’s a TabNavigator with draggable tabs that was posted on a blog called code zen. I used this as my starting point (well, actually I started from scratch, then realized this was already out there). The customized TabNavigator component there is pretty good. So I grabbed that, cleaned up a bit of the re-ordering of tabs stuff, made a few other tweaks, and then added some functionality of my own.

The demo’s below. Basically this allows you to add and remove tabs, drag tabs, but the cool part about what I added is the scrolling of the tabs. If the tabs get too long they do sort of what Firefox does, which is put buttons with left and right arrows on the sides of the tabs and allow you to scroll through them. I also added a drop-down button to the right edge that lets you select any of the tabs from a list, again a la Firefox.

I know Jason from Flexible Experiments has said he’s about to release the same component with the source. So his might come out in the next few days and make mine irrelevant.

I’ll release the source of my stuff in a day or two, after I clean it up a bit. Like I said, I used the code off of the code zen blog as my base, and I’m not in any way trying to steal that and claim it as my own. I’ll pubish the source of all my additions, and hopefully everyone can work together to make a TabNavigator that finally meets everyone’s demands. I figure between what’s already out there, whatever’s coming from Flexible Experiments, and anything that I included that’s not in the others, we’ll be able to get a pretty solid TabNavigator.

So here’s the demo. Try adding a bunch of tabs and see what happens when you add too many to display at once. Try re-ordering the tabs by dragging them. See the pretty little indicator arrow? ooh aah…

This movie requires Flash Player 9.

Standard
Flex/Flash/Actionscript

Draggable Slider Component for Flex

This is a Flex component that adds a draggable bar between two slider thumbs. This is very similar to the “Dual Slider Component” developed by Brendan Meutzner that has been on Flex Exchange for a while now. I’m posting my version because 1) I created it a while ago without realizing there was a similar one out there already and 2) mine works differently by placing the draggable portion directly between the thumbs of the slider on the track.

It’s a simple component, basically nothing more than the VSlider or HSlider that’s included in the Flex Framework, slightly modified for my purposes. If you look at the source you’ll see that the bulk of the component is Slider.as, which is a direct copy of the mx.controls.sliderClasses.Slider class that was included in the framework (upgraded to use the 2.0.1 version). Slider.as was copied completely, and then I added a few things to make it draw an invisible draggable region between the two thumbs. This is an example of something that ideally should have been done by extending the Slider class, but since I needed to access some of the private drawing and child creation methods, I had to copy/paste all the code and make a duplicate class.

Usage is simple, just use it as you would the VSlider or HSlider components. You need to specify a skin for drawing the highlight track. The default halo skin doesn’t work very well (it draws a line around the border of the draggable region). I’ve included two skins for the draggable part, each are shown below in the example and are included in the source code.

View the source.

This movie requires Flash Player 9.

You can download the source by using the link above, or you can also download the compiled SWC and drop it into your Flex project. This has the benefit that it will give you nice icons in the Components panel and it will show the previews of the components on the stage in Flex Builder.

Download the SWC: SliderComponent.swc (289 K)

Standard