Here are two custom components that extend the CheckBox and RadioButton classes to render an image in between the checkbox/radiobutton icon and label.
The main property to set is imageSource which acts just like the Image.source property.
The image position depends on the labelPlacement property (left, right, top, bottom) and the horizontalGap style.
You can also set the imageWidth and imageHeight properties to scale the image down. If you only set one of those properties then the other one is calculated to keep the image's width and height ratio the same.
Note that the ImageCheckBox actually extends my flex.utils.ui.CheckBox class and not the expected mx.controls.CheckBox class.
The flex.utils.ui.CheckBox class supports backgroundColor and backgroundAlpha styles, and as a result the background is always painted. But the default alpha value is 0, so usually you won't see the background unless you set the background color and alpha. The reason for this is that the default mx.controls.CheckBox class has a gap between the checkbox icon and the label (which is the horizontalGap style). This gap causes mouse out events to fire when your cursor moves from the icon or label into this gap. As a result the checkbox tooltip will disappear, and the checkbox will not have the rollover styles. So by painting an invisible background color over the whole area of the checkbox this problem doesn't occur. Same thing applies with the RadioButton class.
Thursday, February 4, 2010
Friday, January 29, 2010
Drawing Dashed Lines, Arcs, and Cubic Curves
The ActionScript Graphics class supports drawing solid lines and quadratic curves. But there isn't native support for dashed lines or cubic (Bezier) curves.
I've created a sample application that shows the three line types: straight, quadratic curve and cubic curve. It also lets you choose between showing a solid line, a dashed line, or both. The line thickness can also be adjusted.
I also got a little carried away and added the quadratic and cubic control points as buttons that you can drag around the canvas to change the curve.
Most of the drawing functionality for these examples is in the GraphicsUtils.as class that contains the following static functions:
The equations used to calculate the values at any point along the line for the three cases were found on the Wikipedia entry for Bézier curves.
I've created a sample application that shows the three line types: straight, quadratic curve and cubic curve. It also lets you choose between showing a solid line, a dashed line, or both. The line thickness can also be adjusted.
I also got a little carried away and added the quadratic and cubic control points as buttons that you can drag around the canvas to change the curve.
Most of the drawing functionality for these examples is in the GraphicsUtils.as class that contains the following static functions:
- drawLine() - draws a straight line, either solid (using Graphics.lineTo() function) or dashed
- drawQuadCurve() - draws a quadratic curve, either solid (using Graphics.curveTo() function) or dashed
- drawCubicCurve() - draws a cubic curve (two control points), either solid or dashed. The curve is an approximation done by dividing the curve into many small segments and drawing straight lines
- drawCircle() - draws a circle, either solid (using Graphics. drawCircle() function) or dashed
- drawArc() - draws an arc, either solid or dashed
The equations used to calculate the values at any point along the line for the three cases were found on the Wikipedia entry for Bézier curves.
Tuesday, January 26, 2010
Flex Context Menus
I've had some frustration with Flex ContextMenus, so I thought I'd write an entry about the basics of creating context menus, adding items, listening for context menu events, and a few restrictions on context menus.
Every InteractiveObject (e.g. Application, Panel, Button, etc) contains a contextMenu property. For most components it will be null and you'll have to create a new menu and assign it to that property. So you can have different context menus for different components.
Here is a simple example of a context menu set on the application:
Here is a short snippet from the above example showing you have to create a ContextMenu, hide the built-in menu items, and listen for menu events.
There are many restrictions to Flex ContextMenus, some of which will drive you crazy. Read carefully, it will save you time later.
More details about the restrictions can be found on the ContextMenuItem page.
There are a few other solutions for people who want more control over the menus. These usually involve adding right click listeners in JavaScript on top of the Flex application and passing that event into Flex to position and show a custom menu instead of the usual Flex context menu.
Here is one such solution: Custom Context Menu.
These solutions can work quite effectively, but since they depend on the browser they can be quite buggy.
Every InteractiveObject (e.g. Application, Panel, Button, etc) contains a contextMenu property. For most components it will be null and you'll have to create a new menu and assign it to that property. So you can have different context menus for different components.
Here is a simple example of a context menu set on the application:
Here is a short snippet from the above example showing you have to create a ContextMenu, hide the built-in menu items, and listen for menu events.
private function initContextMenu():void { |
There are many restrictions to Flex ContextMenus, some of which will drive you crazy. Read carefully, it will save you time later.
- Maximum of 15 custom menu items in the menu
- No sub-menus allowed
- No icons in menus
- Menu items must be 100 characters or less
- Control characters, newlines, and other white space characters are ignored
- MANY reserved words including (but not limited to):
- Save
- Zoom In
- Zoom Out
- 100%
- Show All
- Quality
- Play
- Loop
- Rewind
- Forward
- Back
- Movie not loaded
- About
- Show Redraw Regions
- Debugger
- Undo
- Cut
- Copy
- Paste
- Delete
- Select All
- Open
- Open in new window
- Copy link
- Copy Link Location
- Del
More details about the restrictions can be found on the ContextMenuItem page.
There are a few other solutions for people who want more control over the menus. These usually involve adding right click listeners in JavaScript on top of the Flex application and passing that event into Flex to position and show a custom menu instead of the usual Flex context menu.
Here is one such solution: Custom Context Menu.
These solutions can work quite effectively, but since they depend on the browser they can be quite buggy.
Labels:
context menu,
flex
Wednesday, November 4, 2009
Pass ...rest as a parameter to another function
I recently needed to have a function that accepted a variable number of parameters. This can easily be accomplished using the
But, then I wanted to pass those same parameters on to another function that also accepted a variable number of parameters (e.g. ExternalInterface.call(jsFunctionName, ...args)). If you simply call the other function and pass in rest as a parameter then it won't work as expected. E.g.
What happens in
So if you made a call like this:
Then the traced output would be 1: ['Hello,World,!'].
Notice that there is only 1 parameter!
The way to get around this is to use Function.apply(null, args) to call the function instead, like this:
So if you made this call now:
Then the traced output would be 3: ['Hello' | 'World' | '!'].
Now there are 3 parameters as expected.
I found some help on this topic from The Joy Of Flex Blog by David Colleta.
function myFunction(...rest) syntax. This way I can pass in no parameters (in which case rest is an empty array), one parameter, or multiple parameters.But, then I wanted to pass those same parameters on to another function that also accepted a variable number of parameters (e.g. ExternalInterface.call(jsFunctionName, ...args)). If you simply call the other function and pass in rest as a parameter then it won't work as expected. E.g.
public function sayHello(...rest):void { |
What happens in
callMe(...rest) is rest is an array that actually contains only one item - another array which has the rest parameters that were originally passed into sayHello(...rest).So if you made a call like this:
sayHello("Hello", "World", "!"); |
Notice that there is only 1 parameter!
The way to get around this is to use Function.apply(null, args) to call the function instead, like this:
public function sayHello2(...rest):void { |
So if you made this call now:
sayHello2("Hello", "World", "!"); |
Now there are 3 parameters as expected.
I found some help on this topic from The Joy Of Flex Blog by David Colleta.
Labels:
function,
parameters,
rest
Friday, October 23, 2009
LineChart with CheckBox Legend (Filter Series)
The following example shows a LineChart with a custom Legend that has CheckBoxes next to each LegendItem which allows you to filter the Chart to only show certain series (in this case lines).
I've created a custom class called CheckBoxLegend which extends Legend. It sets the legendItemClass to be the flex.utils.ui.charts.CheckBoxLegendItem class which extends the default LegendItem to add the CheckBox on the left side of the legend item.
Clicking on the legend item toggles the CheckBox and updates the Chart to show or hide the corresponding series. The series is hidden by setting the alpha value to 0.
Here is a snippet of how you use it in MXML:
Here is the example, right click to view source:
Note that the minimum and maximum values of the vertical axis don't get updated when you uncheck one or more series. The Axis calculates these values but doesn't take into account the visibility of the Series. So I've added a new Update Vertical Axis Min/Max CheckBox that will go through all the y axis number values and calculate the minimum and maximum values for the visible series. I haven't tested this out on complicated datasets or different chart types, but hopefully it will be a good starting point.
Originally I played around with actually removing the series from the chart (instead of hiding it), but that caused more problems because when you remove a series the chart will automatically re-color any of the remaining series (unless you specified the stroke/color/fill styles) and the legend gets re-populated without the unchecked series. So it was easiest to just hide the series.
I've created a custom class called CheckBoxLegend which extends Legend. It sets the legendItemClass to be the flex.utils.ui.charts.CheckBoxLegendItem class which extends the default LegendItem to add the CheckBox on the left side of the legend item.
Clicking on the legend item toggles the CheckBox and updates the Chart to show or hide the corresponding series. The series is hidden by setting the alpha value to 0.
Here is a snippet of how you use it in MXML:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:charts="flex.utils.ui.charts.*">
<mx:LineChart id="linechart" ... />
<charts:CheckBoxLegend dataProvider="{linechart}"
color="#000000" direction="horizontal"/>
</mx:Application>
xmlns:charts="flex.utils.ui.charts.*">
<mx:LineChart id="linechart" ... />
<charts:CheckBoxLegend dataProvider="{linechart}"
color="#000000" direction="horizontal"/>
</mx:Application>
Here is the example, right click to view source:
Note that the minimum and maximum values of the vertical axis don't get updated when you uncheck one or more series. The Axis calculates these values but doesn't take into account the visibility of the Series. So I've added a new Update Vertical Axis Min/Max CheckBox that will go through all the y axis number values and calculate the minimum and maximum values for the visible series. I haven't tested this out on complicated datasets or different chart types, but hopefully it will be a good starting point.
Originally I played around with actually removing the series from the chart (instead of hiding it), but that caused more problems because when you remove a series the chart will automatically re-color any of the remaining series (unless you specified the stroke/color/fill styles) and the legend gets re-populated without the unchecked series. So it was easiest to just hide the series.
Subscribe to:
Posts (Atom)