Rambling Developer

Recent Posts


Archives


Rambling Developer

Examples

Flex Halo Accordion resizeToContent Attribute

I spent a bunch of time today trying to get a mx:Accordion to respect my width=”100%” and height=”100%” parameters. Little did I know that I needed to set the resizeToContent attribute to ‘true’ in order for the Accordion to update its sizing when content is added to it.

Here’s what the definition would look like this:

I hope this saves someone just a little bit of time when trying to get their Accordion to resize properly.

adminadmin

Flex Spark Radar Chart Cookbook

I think I’ll take a stab at creating a radar chart to fulfil the request at Adobe Cookbooks asking for a simple radar chart example.

I imagine that this will have very little to do with Flex libraries and Spark components and more to do with just drawing graphics.

Look for a follow up post in the coming days.

adminadmin

Spark DataGroup of RadioButtons from XML

There was a request, after my checkbox cookbook, to have a similar list where only one checkbox was selectable at a time. I didn’t think it was a good idea to write the logic to have only one selectable checkbox when the RadioButton and RadioButtonGroup provide that functonality out of the box. So, without further ado, here is an example of a DataGroup of RadioButtons.

The first thing you need to have is data to populate the data provider. For this example, we’ll reuse the XML from the checkbox cookbook:

<fx:XML format="e4x" id="namesXML">
  <people>
    <person name="Leon"/>
    <person name="Mathilda"/>
    <person name="Stansfield"/>
    <person name="Benny"/>
  </people>
</fx:XML>

In our declarations section, we’ll also need to define a RadioButtonGroup so that we can eventually make all of our RadioButton components be part of that. The definition of a RadioButtonGroup is simple:

 <s:RadioButtonGroup id="myButtonGroup"/>

It’s important that we give the RadioButtonGroup an ‘id” since we’ll be using that later to make our RadioButtons part of the “myButtonGroup” group.

The rest of this example is rather self contained in a single DataGroup definition.  Inside our datagroup we’ll need to define a few things:

  1. A RadioButton ItemRenderer that makes itself part of our RadioButtonGroup from above
  2. A Vertical Layout so that the ItemRenderers are laid out similar to a List.
  3. The dataProvider which is set as an XMLListCollection constructed from our “namesXML” from above.

Here is the implementation of all of those points:

<s:DataGroup width="100%" height="100%" x="200">
  <s:itemRenderer>
    <fx:Component>
      <s:ItemRenderer>
        <s:RadioButton label="{data.@name}"
            group="{outerDocument.myButtonGroup}"/>
      </s:ItemRenderer>
    </fx:Component>
  </s:itemRenderer>
  <s:layout>
    <s:VerticalLayout verticalAlign="middle"/>
  </s:layout>
  <s:dataProvider>
    <s:XMLListCollection source="{namesXML.children()}"/>
  </s:dataProvider>
</s:DataGroup>

As you can see, we achieved all of the points we set out to accomplish. Let’s look at the most important part though: The RadioButton ItemRenderer.

We see that we set the label of each RadioButton to data.@name. This simply means that for each XML node which is assigned to this ItemRenderer, we want to display the name attribute from that XML.

We also, see that we set the group of each RadioButton to the myButtonGroup which is found in the ‘outerDocument’. outerDocument simply means that we are attempting to access a variable that is not in the ItemRenderer Component definition, but in the outer surrounding document (geeze, the name makes sense, huh?).

And, that’s it. Now we have a fully functional DataGroup that is constructed out of single select RadioButtons!

Below you can see a running example and full source (right click -> View Source):

adminadmin

Skinning A Flex Spark DataGrid Header

Creating a custom background color or a custom skin for a DataGrid in Spark is not as simple as it was for Halo components. To create a custom skin for all headers in a DataGrid is accomplished by extending the DataGridSkin class as a new MXML component. Here is a simple example of a “RedDataGridSkin” class where we will just be worrying about the “headerRenderer”:

<spark:DataGridSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
                              xmlns:s="library://ns.adobe.com/flex/spark"
                              xmlns:mx="library://ns.adobe.com/flex/mx"<br>                              xmlns:spark="spark.skins.spark.*"
                              xmlns:local="*"
  <fx:Declarations>
    <fx:Component id="headerRenderer">
      <local:RedGridHeaderRenderer />
    </fx:Component>
  </fx:Declarations
</spark:DataGridSkin>

Notice, that the only custom component we declared in our skin is the RedGridHeaderRenderer. All of the other default skin components will remain since we are extending the base DataGridSkin.

So what does the RedGridHeaderRenderer do? The RedGridHeaderRenderer extends the SDK’s DefaultGridHeaderRenderer and reimplements it’s visual skinning components. Since the full implementation of the renderer is lengthy I will only post a small portion in line (see the code demo/source at the bottom of this post for the full example). Here is a code snippet from a GridItemRenderer called “RedGridHeaderRenderer”:

<!-- layer 2: fill -->
 <!--- @private -->
 <s:Rect id="fill" left="0" right="0" top="0" bottom="0">
   <s:fill>
     <s:LinearGradient rotation="90">
       <s:GradientEntry color="0xFFFFFF"
                        color.hovered="0xBBBDBD"
                        color.down="0xAAAAAA"
                        alpha="0.85" />
       <s:GradientEntry color="0xFF030D"
                        color.hovered="0x9FA0A1"
                        color.down="0x929496"
                        alpha="0.85" />
     </s:LinearGradient>
   </s:fill>
</s:Rect>

The only thing I changed here from the default implementation of this renderer is the second GradientEntry’s color. I changed the color to a red hex code (0xFF030D) which will give all of my DataGrid’s that use the skin and renderer a red gradient.

To use our new skin and renderer we need to set our DataGrid’s skinClass to “RedDataGridSkin” and all of the DataGrid headers will use the new skin/renderer. A simple example:

<s:DataGrid skinClass="RedDataGridSkin">

If we want to get more fancy, we can also alter column header renderers on a column by column basis. I have also created a “BlueGridHeaderRenderer” (see the code demo/source at the bottom of this post for the full example). Here we will use the “BlueGridHeaderRenderer” to create a single blue column header while the rest of the coumns are using the “RedGridHeaderRenderer” defined in “RedDataGridSkin”:

<s:DataGrid skinClass="RedDataGridSkin">
  <s:columns>
    <s:ArrayCollection>
      <s:GridColumn headerText="Header 1" width="200"/>
      <s:GridColumn headerText="Header 2" width="200"/>
      <s:GridColumn headerText="Header 3" width="200"
            headerRenderer="{new ClassFactory(BlueGridHeaderRenderer)}"/>
    </s:ArrayCollection>
  </s:columns>
</s:DataGrid>

The full code of this example (right click ->view source) inside of a running demo can be viewed HERE.

adminadmin

Simple Flex Count Down Timer

There was a request in the Adobe Cookbooks for an example of how to create a countdown timer in Flex. I thought I would post the example here too.

Creating a countdown timer involves using the Timer class along with the Date class. The Timer will be used to trigger a method periodically so that the Date class can be polled for the current time. Before we get into the logic, first we need to define some input and display components for this example. We’ll need an input for the user to select how many seconds to countdown, a label to describe what is required for the input, a ‘Start’ button, and a label to show the count down. Those 4 components are shown below:

<mx:TextInput id="secondsInput" restrict="0-9"/>
<mx:Label text="Enter time in seconds for count down"/>
<mx:Button id="startButton" label="Start Count Down" click="onStartTimer()"/>
<mx:Label id="countDownTimerDisplay"/>

Notice, that we use a restrict=”0-9″ attribute so that the user ca only enter number is the input since we are looking for a number of seconds to be entered.  Also, notice, that we have a listener on the startButton click event to trigger a onStartTimer() method.

In our onStartTimer() method we’ll need to do a several things:

  1. Disable the start button and input so the user cannot edit anything while we are counting down.
  2. Store the start time by storing a new Date Object.
  3. Store an end time which will be the current time plus the amount of seconds the user entered.
  4. Display the starting count down value in our countDownTimerDisplay.
  5. Start a timer which will go off in half a second (500 milliseconds) so that the countDownTimerDisplay can be updated.

The code implementing the above points is shown here:


private var timer:Timer;
private var startTime:Number;
private var endTime:Number;
 
private function onStartTimer():void{
  startButton.enabled = secondsInput.enabled = false;
  startButton.label = "Counting Down!";
  startTime = new Date().time;
  endTime = new Date().time + Number(secondsInput.text) * 1000;
  countDownTimerDisplay.text = secondsInput.text;
  if(timer==null)
    timer = new Timer(500);
  timer.addEventListener(TimerEvent.TIMER, onTimerInterval);
  timer.start();
}

We see in the above code example that we add a listener on the timer which has a callback timer called onTimerInterval().  This method will need to do a few things:

  1. Check if the current time is past the endTime we stored above.
  2. If the countdown is complete, change the countDownTimerDisplay to “Count Down Completed” and renable all the inputs for the user.
  3. If the countdown isn’t complete, update the countDownTimerDisplay to show the current amount of time left and restart the half second timer.

The code implementing the above points is shown below:


private function onTimerInterval(event:Event):void{
  var now:Number = new Date().time;
  if(endTime <= now){
    countDownTimerDisplay.text = "Count Down Completed";
    startButton.enabled = secondsInput.enabled = true;
    startButton.label = "Start Count Down";
  }else{
    countDownTimerDisplay.text = Math.round((endTime - now)/1000).toString();
    timer.start();
  }
}

That's it! You should now have a fully functional example of a count down timer.

A running demo of this code and the full source (right click -> view source) can be viewed below:

adminadmin