« April 17, 2008 | Main | April 29, 2008 »

April 28, 2008 Archives

April 28, 2008

Back and Flexing

Apologies to regular readers may be wondering where I have been. I took a week off after OAUG to sit on a San Diego beach to get toasted to a crisp and to avoid any sharks. We were on that same beach the day before it happened! Needless to say my wife was constantly telling me to watch the kids in the surf, checking for any big gray fins in the water and if seen to run or swim like hell!


While I was away, Noelle has been working on some Flex template goodies. We got a requirement a while back to produce a report similar to this:


FlexReport1:


Its nothing to 'write home about' standard table stuff but the interesting feature is the 'percentage bar' embedded in the table. Two issues to solve here:


1. Building the 'bar' component - its not an out of the box feature.
2. Getting the bar to render inside the table


Noelle, being very cunning, solved both!


FlexReport2:


Its not exactly the same look and feel but we were after the functionality - the look can be tweaked quite easily.


Tackling the 'bar' component first, Noelle first needed to build the 'percentage bar'. To do this, Noelle used an ActionScript class to create and render the bar. It basically takes a label object and extends it to render the text value and a rectangle shape, calculates the percentage fill to be used based on the data.


Here's the script


// ActionScript file


package {


// Need these packages for rendering and drawing


import flash.display.*;
import flash.geom.*;
import flash.text.TextField;
import mx.controls.Label;


// We are going to extend the label object


public class PercentageBar extends Label {
 override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void


 {
 
super.updateDisplayList(unscaledWidth, unscaledHeight);


  // Create rectangle shape and width


  var rndedRect:Shape = new Shape();
  
var rectWidth:Number=100;
 
var rectHeight:Number=15;
 
// Fill for the rectangle is derived from value in the main.mxml ie the parent application


  var rectFill:Number=this.parentApplication.percentCalculated;


  //Set the fill type, colors, alphas and ratios


  var fillType:String = GradientType.LINEAR;
  
var colors:Array = [0xFF0000,0xFFFFFF];
  
var alphas:Array = [1, 1];
  
var ratios:Array = [0, 255];

  
// matrix - not required but allows you to specify the fill
 
var matr:Matrix = new Matrix();
  matr.createGradientBox(rectFill, rectHeight, 0, 0, 0);
 
var spreadMethod:String = SpreadMethod.PAD;
  //Start rendering the rectangle
  rndedRect.graphics.beginGradientFill(fillType,colors,alphas,ratios,matr,spreadMethod);
  rndedRect.graphics.lineStyle(1,0x000000,1,
false);
  rndedRect.graphics.drawRoundRect(2, 0, rectWidth, rectHeight, 10, 20);
  rndedRect.graphics.endFill();
  
  // Add the rectangle to the label object
 
this.addChild(rndedRect);


  //Create the label for the rectangle
  // Value drawn from the percentCalculated value in the main.mxml


  var label:TextField = new TextField;
  label.width = 26;
  label.text = (
this.parentApplication.percentCalculated+ "%");
  label.x = 105;
  label.y = 0;
  //Add the text field to the label
 
this.addChild(label);
    }
  }
}


Those familiar with java should not be too scared of the code - if you spend some time with it its not that tough to understand. Its code yes! but it adds a huge layer of flexibility to the flex reports.


Thats the 'bar' component, so how to bring it into the main table layout. Thats pretty easy too ...


Remember that the bar component needed the 'percentCalculated' value from the parent application ie the main flex template? Well, we need a function to calculate that:


[Bindable] public var percentCalculated:Number;



// determine the percent of the target number - round before passing back
private function calcPercent(row:Object, column:DataGridColumn ):void
{
 
 var a:Number;
  var t:Number;
  a = row.actual;
  t = row.target;
  percentCalculated = Math.round((a/t) * 100);
}


Notice we need to declare the 'percentCalculated' variable as public and bindable so the action script class can access it. Its a simple calculation to get the percentage based on the rendered table data.

To get the 'bar' to render we just need to set the last column to use its own renderer ie the PercentageBar AS class that was created.


<mx:DataGrid id="myDatagrid" width="500" height="300" dataProvider="{dataXML.product}" editable="false" enabled="false">
 
<mx:columns>
  <mx:Array>
   <mx:DataGridColumn dataField="name" headerText="Product Category"/>
   <mx:DataGridColumn dataField="actual" headerText="Units Sold Actual" id="actual"/>
   <mx:DataGridColumn dataField="target" headerText="Units Sold Planned" id="target"/>
   <mx:DataGridColumn itemRenderer="PercentageBar" width="135" headerText="% of Target" labelFunction="calcPercent"/>
  </mx:Array>
 </mx:columns>
</mx:DataGrid>


You can get the complete source to the flex project here. Thanks again to Noelle for the research and code.


So, a little effort but hopefully you get an idea of how you can take existing Flex objects and extend them to create your own visualizations of the data. You can now tell your users that the 'world is their oyster' when it comes to reporting ... or may be not!   

About April 2008

This page contains all entries posted to Oracle BI Publisher Blog in April 2008. They are listed from oldest to newest.

April 17, 2008 is the previous archive.

April 29, 2008 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type and Oracle