Showing posts with label flex. Show all posts
Showing posts with label flex. Show all posts

Tuesday, 20 November 2007

How to color Datagrid cells/rows in flex 2

I have been looking for a easy and neat way to color a single cell or a complete row in flex 2.

Google brought me two interesting links:

1. How opaqueBackground can be used to color the background of a label itemRenderer
The comment posted by Dallas at 11/10/06 8:01, shows a way of highlighting a cell. Very simple implementation - the only problem is that the background color won't react on mouseover after the opaqueBackground is set.

2. How do you change the background cell color in a DataGrid?
Shows how to implement a colored background that react upon mouseover and selection. The implementation extends a label and overrides the 'updateDisplayList' method to draw some graphics as the background.
The last solution seems to be the one I preferred - because of the ability to see mouse effects applied to the cell. But still I liked the cleen implementation of the first one.

I couldn't resist of bringing combined solution, where I extends a Label, but listens for a Event.RENDER events instead of overriding the updateDisplayList method.

Sample Application


Sourcecode
Demonstrates how to use the renderer as a drop-in and inline itemRenderer.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" verticalAlign="middle" xmlns:tmp="component.dashboard.*"
creationComplete="init()">

<mx:Script>
private function init() : void {
myGrid.setFocus();
}
</mx:Script>
<mx:XML id="itemsXML">
<items>
<item name="Item 1" state="1" />
<item name="Item 2" state="0" />
<item name="Item 3" state="0" />
<item name="Item 4" state="1" />
<item name="Item 5" state="0" />
</items>
</mx:XML>

<mx:Style>
.centered {
text-align: center;
}
</mx:Style>

<mx:DataGrid id="myGrid" dataProvider="{itemsXML.item}" editable="true">
<mx:columns>
<mx:DataGridColumn dataField="@name" headerText="Name"
headerStyleName="centered"
itemRenderer="component.dashboard.TestItemRenderer"/>

<mx:DataGridColumn dataField="@state" headerText="Price"
textAlign="right" headerStyleName="centered">
<mx:itemRenderer>
<mx:Component>
<tmp:TestItemRenderer/>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>

</mx:Application>


CustomItemRenderer.as
Following is a CustomItemRenderer that can be extended to apply logic to decide if a cell is to be styled.

package dk.jacobve {

import mx.controls.Label;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.*;
import mx.events.FlexEvent;
import flash.events.Event;

public class CustomItemRenderer extends Label {

public function CustomItemRenderer {
//listen for render events
addEventListener(Event.RENDER, renderListener);
}

public function styleIt() : Boolean {
return false;
}

public function styleTrue() : void {
}

public function styleFalse() : void {
}

protected function renderListener(event:Event) : void {
if (listData != null) {
var grid:DataGrid = DataGrid(DataGridListData(listData).owner);
if (!grid.isItemHighlighted(data) && grid.selectedItem != data) {
if (styleIt()) {
styleTrue();
} else {
styleFalse();
}
} else {
styleFalse();
}
}
}
}
}


CustomItemRenderer extension
Shows an implementation using E4X on a xml data element to deside if the cell is to be colored red.

package dk.jacobve {

import mx.controls.Label;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.*;
import mx.events.FlexEvent;
import flash.events.Event;

public class TestItemRenderer extends CustomItemRenderer {
public override function styleIt() : Boolean {
return data.@state == "0";
}

public override function styleTrue() : void {
this.opaqueBackground = 0x33CC33;
}

public override function styleFalse() : void {
this.opaqueBackground = null;
}
}
}

Thursday, 1 November 2007

Quickstart flex development with this maven archetype

Have you considered starting some flex development, but haven´t found out where to start? Or are you already flex'ing but could use some easy way to quickstart new flex projects in java?

I have created a maven archetype called maven-archetype-flex and distributed it to ibiblio for all to use.
It will quickly get you up and running.

Here is how you do it:

1. Download flex sdk
Download the flex sdk from adobe, if you haven't got it already.

1b. Minor change to flex-config.xml
You have to uncomment the following in your flex-config.xml located in:

${flex.home}/frameworks/flex-config.xml
<local-fonts-snapshot>localFonts.ser<local-fonts-snapshot>
Otherwise the compiler will complain as Matt mentions in his comment.

2. Create flex project
Running the following maven command will create a flex project called my-flex having groupId my.group. Feel free you change these to what ever you like:
mvn archetype:create
-DarchetypeArtifactId=maven-archetype-flex
-DarchetypeVersion=1.0
-DarchetypeGroupId=dk.jacobve.maven.archetypes
-DgroupId=my.group
-DartifactId=my-flex
-DpackageName=
Note: it is important that you remember the -DpackageName= as the Main.mxml flex file in the archetype is to be kept in the root of your source dir and not in some subpackage.

3. Set flex.home property
In the newly created project pom.xml you should change the flex.home property to fit your flex.home path.

4. Build flex project
Now you are ready to build the flex project:
mvn install
Running this command inside your project will build the project and create a swf file in the target directory.

Viola! You have just created a simple flash application ready to use.

Where to go from here
To see the result of the work you can do one of the following things:
  • Open the flash file with your favorite browser.
  • Download the standalone player for your operating system ().
  • Deploy the swf file to a webserver. Maybe you can get inspiration on how to do it from this maven flex template.

Tuesday, 30 October 2007

Flex maven template - getting started

In Per´s lession 1 of his flex development tutorial he showed us a build setup - it is a bit outdated by now as the israfil plugin moved to google code and the sateh repository doesn't exist anymore. It also only contained the flex module and no war sample showing how easy it is to deploy the flex application.

I took the liberty to create my own template consisting of a multimodule build:

  • Flex module - looking prettymuch the same as Per´s.
  • War module - depending on the flex module wrapping the swf file into a war ready to deploy.
I would have created a maven archetype, but considering mavens lack of support for archetypes containing multimodules I just created a zip.

I find the template useful when starting a flexproject from scratch and maybe you will too?

Download
Download the flex-template

For more information about the israfil plugin click here

Sunday, 28 October 2007

Sharing flex code examples

Developing flash front ends with flex is really getting to me.
I don't have Flex Builder but find no problem with developing using another IDE combined with maven and the israfil mojo.

From time to time I blog about some nifty actionscript 3/flex code but I am missing a simple way to distribute the sourcecode.
Unfortunately my IDE - Intellij IDEA - doesn't contain a feature making it easy to distribute the flex sample code, neither have I found a maven plugin capable of packaging the sourcecode for distribution.

Adobe added the ViewSource capable of linking to some arbitrary URL where the source is located.

import com.adobe.viewsource.ViewSource;
...
ViewSource.addMeneuItem(this,"srcview/index.html");
But then again you have to have the source code distributed :-)

I am considering developing a maven plugin that can do the job, but it would be waste of time if a solution is somewhere "out there".

So please let me know!

Thursday, 25 October 2007

Advanced inputfiltering with flex

All the time I have been developing web applications in Java I have build my UI upon some framework like Struts, Tapestry or JSF. All of these frameworks encourage serverside validation and to some extend clientside validation.
I haven't seen a web framework facilitating a prober way to do input filtering. The few times I have implemented an inputfilter I have cooked up some javascript to do the job - normally not that reusable.
I don´t see filtering as a substitution of server side validation, but more as an extension of the user experience where the user gets immediate feedback on her use of an application.

At my current project we build the UI on the flash runtime in flex - and the flex framework really brings some interesting opportunities.

Basic
For basic filtering a restrict property can be set on the TextInput component only allowing a subset of characters as input.
But as soon as your inputfilter depends on already entered text the filtering gets a bit more sophisticated :-)

Advanced
On the TextInput you can listen for a TextEvent that contains the data the user is entering as input but react upon it before it actually hits the input field. That gives you the opportunity to prevent the input from reaching the Textinput component by calling the preventDefault() method on the event if the data isn't allowed for some business rule that you apply.

public class FilterTextInput extends TextInput {

public function FilterTextInput() {
addEventListener(TextEvent.TEXT_INPUT, validateInput);
}

private function validateInput(event : TextEvent) : void {
var actualInput : String = EventUtil.getActualText(event);
trace(actualInput);
//sample filtering securing that all input characters are unique
if (! StringUtil.containsUniqueChars(actualInput)) {
event.preventDefault();
}
}
}

Unfortunately the event only contains the data the user is about to enter. So if you would like to validate the entire input as it would be after when the input is combined with the already entered text, you have to do some work yourself.


EventUtil
I implemented an EventUtil class capable of extracting the actual input as it would look like when the already entered text is combined with the incoming input (the method used in the sample above). The tricky part is to take notice of where in the existing text the new input is about to be entered. The input could replace some existing text and at the same time be pasted into the middle of an existing text.

My utility method looks like this:
public static function getActualText(event : TextEvent) : String {
var input : TextInput = TextInput(event.currentTarget);
var text : String = input.text;
var b : int = input.selectionBeginIndex;
var e : int = input.selectionEndIndex;

var before : String = "";
var after : String = "";
if (e > 0) {
before = text.substring(0, b);
}
if (b < text.length) {
after = text.substring(e, text.length);
}
return before + event.text + after;
}

A simple example illustrating the use of function getActualInput(). The filter prevents the user from entering the same character twice:

Thursday, 14 June 2007

Flex/flash could learn from Java and Maven

Yesterday I told my colleague how much I loved the tight integration between flex components and XML.
Pretty much any UI flex component can use a xml document as a dataprovider and you can dynamically use attributes or nodes in your component.
That really brings your application up to speed in a hurry.

Just as I had declared my affection for the integration I ran into a bug best demonstrated by this small example:

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.*;
import flash.events.*;

private var work:String = "<tmps><tmp att=\"abc\"><dummy/></tmp></tmps>";
private var wontWork:String = "<tmps><tmp att=\"abc\" /></tmps>";

private function init() : void {
result.text = work;
}

private function clickHandler(event:ItemClickEvent):void {
if (event.label == "OK") {
result.text = work;
} else {
result.text = wontWork;
}
}

private function printResult(event:MouseEvent):void {
var list :XMLList = XML(result.text).tmp;
Alert.show(list[0]); // should print first element in the list - the tmp element
}
]]>
</mx:Script>
<mx:Panel title="Flex bug example" height="100%" width="100%">
<mx:ButtonBar itemClick="clickHandler(event);">
<mx:dataProvider>
<mx:Array>
<mx:String>OK</mx:String>
<mx:String>not OK</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ButtonBar>
<mx:TextArea id="result" editable="false" height="100" width="100%"/>
<mx:Button id="evaluate" label="evaluate result" click="printResult(event)"/>
</mx:Panel>
</mx:Application>
The compiled version:








I want to get the first element of my "tmps" xml document. Casting the string to a XML document and work on it as a XMLList prevents me from getting the first element in the XMLList as long as the element doesn't contain a child! That simply must be a bug.

I admit it is not the largest bug in the world, but the consequence of a bug like this seems larger than I first thought.
As the xml and ui components both are a part of the platform, the solution seems to be an upgrade of the flashplayer as Adobe fixes the bug. Upgrading the flashplayer is something the enduser as to do.

As I am working on a internal flash/flex application that has to run in a closed environment, where ugrades of the flashplayer are something that is out of the hands of the enduser, an upgrade of the flashplayer may not be a trivial process.

A "watercooler talk" led to a interesting suggestion to how Adobe could structure the platform to lower the impact on the end user.
What if the xml api was some kind of versioned module that your flex application dependend on?
Then you (as a developer) just had to change your internal dependencies as bugfixes and new features was available.
Adobe could have something like a centralized repository existing of original (signed) modules.

The local machine running the flex application could have some local repository for downloaded dependencies. Each dependency could be resolved at runtime and downloaded as needed.
That would lower the time it takes for adobe to release a bugfix, as it doesn't involve a complete new flashplayer release and the issue where endusers doesn't have the privilege to upgrade a plugin is gone as well.

If the idea looks like the java/maven dependency architecture it's not a coincidence :-) Maybe flex /flash could learn from the java world in this case.

Thursday, 7 June 2007

Flex: ISO-8859-1 vs. UTF-8

Hint:
In a flex/flash project we encoded our files using iso-8859-1 encoding resulting in the danish characters like æ, ø etc. not being encoded correct.

The adobe flex compiler seems to interpret all files not containing a Byte Order Mark (BOM) as utf-8 even though we specified the -compiler.actionscript-file-encoding option.
Changing our files to utf-8 encoding solved the problem and no -compiler.actionscript-file-encoding option was needed.

And luckily for that as the israfil maven flex plugin that we use doesn't support the -compiler.actionscript-file-encoding option in the latest available version (1.0).