Using DataGrid headerRenderer

November 1st, 2008 by Biro Barna

I helped a friend of mine with a project of his recently and we were having some problems with the DataGridColumn’s headerRenderer property. We finally got it working but I thought that I’ll post the solution so that others won’t waste hours with this.

One more thing that I’d like to mention before I post the source files and a simple example to demonstrate the final result: DON’T USE FLEX 2 !!! UPGRADE TO FLEX 3 !!! During this project, I was using Flex 3 and my friend was using Flex 2… All that I can say is that the experience was horrible !!! I got the thing working in Flex 3 in no time but Flex 2… huh, now that was a pain in the butt. I finally ended up redoing the whole thing in Flex 2 so I can sort out the stupid errors Flex 2 was throwing at us about “you can’t use Binding for static variables” ( which I couldn’t remember being so… but it seems that my memory was playing tricks on me ) and other really annoying bugs ( example: the area beneath the arrow was a “dead spot”, so we ended up wrapping the Image and Label in a second HBox component which we have set as the hitArea for the main HBox component… really weird. ).

Again, DON’T USE FLEX 2, sell your car, your socks or whatever and get your hands on FLEX 3 ( It’s totally worth it ) !!! The example itself is simple, we replaced the header with a HBox custom component which has an Image component inside of it and a Label to display some text. The goal was to change the arrow from UP to DOWN on each header click, simple but it turned out to be quite frustrating .

Ok, enough of that, source files can be found here: DataGrid Header Rendering

And here’s the final result too ( obviously, I “scaled it down” because the project itself was way bigger and we obviously wasn’t allowed to use it for other purposes or post it’s source code ):


EDIT: This method only works for the simple DataGrid component. If you want it to work with multiple sorting and you go with the AdvancedDataGrid component then you must rethink the solution, otherwise all your headers will always display the same UP or DOWN arrow ( due to the static counter variable I’ve used to alternate between the UP and DOWN arrow ).

Posted in Flex Builder 3 Professional | No Comments »

Advanced Flex 3 Contact Form

October 26th, 2008 by Biro Barna

To make things a bit different, I decided to create a Flex 3 Contact form just to show all the “anti-Flex” people out there that Flex is not only for hardcore development and ugly graphics. With a bit of effort and time, anyone can produce really good looking applications in Flex Builder too ( and I didn’t even bother using graphics with this example, I only edited the look of the component and I think that the results is quite good ).

Final result ( sneak peek ):

I didn’t want to complicate stuff to badly with this example, my goal was to create a good looking and clean Flex 3 contact form ( I’m sure that many of you guys out there are really bored of all those simple Flash contact forms ) and obviously, to add more “advanced” features. To spice things up a bit, I played around with Shared Objects too. Once the user sends the E-mail he’ll be provided with an option “Save personal information or Not”. Ok, what does this do ? Well, it simply creates a shared object and stores your personal information on your computer for later use. This way, whenever you open your PC and visit this site, you’ll always have certain fields filled out, saving you time.

Obviously, this can be done more complexly too, shared objects aren’t really hard to use but it’s a decent example on how to use them and once you understand how they work then you can experiment with your own stuff ( for example: create a shared object for your games so that when users revisit the game then they’ll already have the Name filled out… or any other features ), it’s really up to everyone’s imagination.

The working example can be viewed here: Working Example
You can download the source files from here: Advanced Flex 3 Contact Form

Of course, the source files contain both .mxml and .php files that were used when I created the example. I really hate downloading examples that are only partially working ( although they have their ups and down ) so I decided to always provide all my files when posting an example so that anyone can easily play around with it and hopefully learn something from my examples.

Enjoy.

Posted in Flex Builder 3 Professional | No Comments »

Simple Flex 3 File Downloader

October 26th, 2008 by Biro Barna

The title kinda says it all. Here’s a simple example on how to track the progress of a downloading file with Flex 3. The cool thing about this example is that it can be easily reproduced to work in CS3 ( or CS4 ) too. The code part is essentially the same just that in CS3 you can create your own progress bar and update that instead of the progress bar component ( that I’ve used with Flex 3 ).

This little file downloader can come really handy when your visitors are downloading larger files. You can keep your visitor busy with some interactive animations while the file is downloading and at the same time you’ll have a progress bar telling your visitor how long must he wait until the download is complete.

The working example can be viewed here: Working Example
You can download the source code from here: Flex 3 File Downloader

Simply copy-paste the code into a new Flex 3 Project and make sure that you have a folder called “assets” in your source folder and inside your “assets” folder, you have an mp.3 file called “example.mp3″. Simple as that.

Enjoy.

Posted in Flex Builder 3 Professional | No Comments »

Ease and Blur in AS 3.0

October 26th, 2008 by Biro Barna

This is a simple example on how to apply easing and blur to an object.

The code is fairly simple, I just created a container that will hold our text field ( I don’t like working on object directly so I usually add each and every object into a container ), I defined a simple TextFormat to format our text and added everything to the stage. Once all this was done, I simply added an ENTER_FRAME event listener to the stage that will handle all the easing and blurring ( this is the essential part since this function has all the math that handles the easing ).

The example can be downloaded from here: Ease And Blur

The source code looks like this ( obviously, the MainClass class is set as a Document Class ):

package
{
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	import flash.text.AntiAliasType;
	import flash.filters.BlurFilter;
 
	public class MainClass extends Sprite
	{
		private var container:Sprite;			// container that holds the text field
		private var tf:TextField;
		private var easeFactor:Number = .2;		// amount of easing
 
		public function MainClass()
		{
			// set stage properties
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.showDefaultContextMenu = false;
			stage.align = StageAlign.LEFT;
 
			init();
		}
 
		private function init():void
		{
			// create a text format for your text field
			var tFormat:TextFormat = new TextFormat();
			tFormat.font = "Arial";
			tFormat.bold = true;
			tFormat.color = 0x000000;
			tFormat.size = 36;
			tFormat.align = TextFormatAlign.LEFT;
 
			// create the text field
			this.tf = new TextField();
			this.tf.autoSize = TextFieldAutoSize.LEFT;
			this.tf.selectable = false;
			this.tf.multiline = false;
			this.tf.text = "Wisebisoft";
			this.tf.antiAliasType = AntiAliasType.ADVANCED;
			this.tf.sharpness = -400;
			this.tf.setTextFormat(tFormat);
			this.tf.x = -Math.round(this.tf.width / 2);
			this.tf.y = -Math.round(this.tf.height / 2);
 
			// create a container that will hold the text field
			// and add an ENTER_FRAME event listener that 
			// will handle the easing and blurring
			this.container = new Sprite();
			this.container.mouseChildren = false;
			addChild(this.container);
			this.container.addChild(this.tf);
 
			stage.addEventListener(Event.ENTER_FRAME, eventFrameHandler);
		}
 
		private function eventFrameHandler(event:Event):void
		{
			if (mouseX != 0 && mouseY != 0)
			{
				var mouse_xpos:Number = mouseX;
				var mouse_ypos:Number = mouseY;
 
				// calculate new position
				mouse_xpos = this.container.x;
				mouse_xpos -= (mouse_xpos - mouseX) * this.easeFactor;
				mouse_ypos = this.container.y;
				mouse_ypos -= (mouse_ypos - mouseY) * this.easeFactor;
 
				// update positions and apply a blur filter
				this.container.x = mouse_xpos;
				this.container.y = mouse_ypos;
				this.tf.filters = [new BlurFilter(Math.abs(mouse_xpos - mouseX), Math.abs(mouse_ypos - mouseY), 1)];
			}
			else
			{
				this.container.x = Math.round(stage.stageWidth / 2);
				this.container.y = Math.round(stage.stageHeight / 2);
			}
		}
	}
}

Here’s the final result ( working example ):

Posted in ActionScript 3.0 | No Comments »

Simple Drag in AS 3.0

October 25th, 2008 by Biro Barna

Here’s a really simple and fast example on how to use Drag in ActionScript 3.0. Not much has changed since ActionScript 2.0 when it comes to dragging objects around, just that now, things are much easier to use and we can write much more organized code when taking advantage of ActionScript 3.0’s OOP features.

MainClass.as which is set as a Document Class:

package
{
	import com.wisebisoft.CustomCircle;
 
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.MouseEvent;
 
	public class MainClass extends Sprite
	{
		public function MainClass()
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.showDefaultContextMenu = false;
			stage.align = StageAlign.LEFT;
 
			init();
		}
 
		private function init():void
		{			
			var circle:CustomCircle = new CustomCircle(100, 0x000000);
			circle.buttonMode = true;
			circle.x = 280; circle.y = 200;
			circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragHandler);
			circle.addEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
			addChild(circle);
		}
 
		private function startDragHandler(event:MouseEvent):void
		{
			event.target.startDrag();
		}
 
		private function stopDragHandler(event:MouseEvent):void
		{
			event.target.stopDrag();
		}
	}
}

CustomCircle.as which is just a simple class that draws our custom circle which we’ll be interacting with:

package com.wisebisoft
{
	import flash.display.Sprite;
 
	public class CustomCircle extends Sprite
	{
		public function CustomCircle(radius:Number, color:uint)
		{
			drawCircle(radius, color);
		}
 
		private function drawCircle(radius:Number, color:uint):void
		{
			this.graphics.beginFill(color, 1);
			this.graphics.drawCircle(0, 0, radius);
			this.graphics.endFill();
		}
	}
}

Of course, you can download the example from here: Simple Drag

Posted in ActionScript 3.0 | No Comments »

Reusable AS 3.0 ScrollBar Class

October 25th, 2008 by Biro Barna

Hi everyone and welcome to the newly launched Wisebisoft WebLog.

If you have been visiting the old blog then you know that I had a reusable ActionScript 3.0 scrollbar class there which was a kinda out of date. Although I created a new version, I decided not to upload it there but wait until this new WebLog is launched.

I didn’t bother adding fancy graphics to it but of course it can be done. The scrollbar has additional features too that can be disabled or enabled, one such feature is the “blurring feature” which will blur the content on scroll. You can play around with these features yourself and even add new ones if you like.

You can download the working example from here: Custom ScrollBar

Here’s the source code of the class:

package com.wisebisoft.widgets
{
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventPhase;
	import flash.events.MouseEvent;
	import flash.filters.BitmapFilterQuality;
	import flash.filters.BlurFilter;
	import flash.geom.Rectangle;
 
	/**
	 * 
	 * Author: Biro Barna ( http://www.wisebisoft.com/ )
	 * Created on: Wednesday, September 03, 2008, 4:22 AM (GTM +2:00) Minsk
	 * Description: Reusable ActionScript 3.0 ScrollBar class
	 * Usage: Simply instantiate the class and pass all the 5 required arguments ( and you can set 6 additional properties too ).
	 * Example: new CustomScrollBar(stage, content_mc, content_mask, scroll_track, scroll_btn, true, true, true, true, .2, 5);
	 * 
	 * ---------------- ONLY 5 PARAMETERS ARE REQUIRED FOR THE CLASS TO FUNCTION ----------------------
	 * 
	 * -- stage -- is your Stage object, it will help you prevent people from messing up certain features
	 * -- content_mc -- is the movie clip holding the content that you want to scroll
	 * -- content_mask -- is the movie clip that you'll use to mask content_mc movie clip
	 * -- scroll_track -- is the movie clip that plays the role of a track for the scroll_btn
	 * -- scroll_btn -- is the button that you can click + hold and drag to scroll your content_mc movie clip
	 * 
	 * -- -------------- ALL THE PARAMETERS AFTER THE 5TH PARAMETER ARE OPTIONAL ---------------------------------------
	 * 
	 * -- the following 4 parameters in the line enable or disable certain features like mouse wheel scrolling or blurring
	 * -- .3 -- is the easing that will be added to the content_mc movie clip; the lower the value is the more easing is applied
	 * -- 10 -- is the number of pixels the scroll_btn will move on the Y axis each time you scroll with the mouse wheel
	 * 
	 * */
 
	public class CustomScrollBar
	{
		private var content:MovieClip;
		private var contentMask:MovieClip;
		private var scrollTrack:MovieClip;
		private var scrollButton:MovieClip;
		private var useMouseWheel:Boolean;			// helps you enable or disable the mouse wheel scrolling feature
		private var enableJumping:Boolean;			// helps you enable or disable the "jumping feature"
		private var buttonModeEnabled:Boolean;		// helps you enable or disable the scroll button's buttonMode property
		private var easing:Number;
		private var scrollSpeed:Number;
		private var moveValue:Number;				// helps calculate the final moveSpeed value
		private var moveSpeed:Number;				// the speed with which the content will be scrolled
		private var currentContentY:Number;			// stores the current position of the content movie clip
		private var scrollTrackScaleY:Number;
		private var contentHeight:Number;
		private var scrollTrackHeight:Number;
		private var scrollButtonHeight:Number;
		private var contentMaskHeight:Number;
		private var movieStage:Stage;
		private var enterFrameActive:Boolean;		// it "signals" if the ENTER_FRAME event has been triggered or not
		private var allowRemove:Boolean;			// helps your function know when it is allowed to remove the ENTER_FRAME event
		private var blurEnabled:Boolean;			// enables or disables content blur on scroll
 
		// CLASS CONSTRUCTOR //
 
		public function CustomScrollBar(
 
							movieStage:Stage,
							content:MovieClip,
							contentMask:MovieClip, 
							scrollTrack:MovieClip,
							scrollButton:MovieClip,
							useMouseWheel:Boolean = true,		// mouse wheel scrolling is by default: ENABLED
							enableJumping:Boolean = true,		// the "jumping feature" is by default: ENABLED
							buttonModeEnabled:Boolean = true,	// scroll button's buttonMode property is by default: ENABLED
							blurEnabled:Boolean = false,		// content blurring on scroll event is by default: DISABLED
							easing:Number = .15,				// easing speed is by default set to: .15
							scrollSpeed:Number = 5				// scrolling speed is be default set to: 5
 
						   )
		{
			// store certain properties of the objects passed to the class constructor
			// in specific variables, increasing performance at the same time
 
			this.content = content;
			this.contentMask = contentMask;
			this.scrollTrack = scrollTrack;
			this.scrollButton = scrollButton;
			this.useMouseWheel = useMouseWheel;
			this.enableJumping = enableJumping;
			this.buttonModeEnabled = buttonModeEnabled;
			this.blurEnabled = blurEnabled;
			this.easing = easing;
			this.scrollSpeed = scrollSpeed;
			this.movieStage = movieStage;
 
			setHeights();
			setButtonMode();
			setContentMask();
			storeTrackScaleY();
			repositionObjects();
			addListeners();
		}
 
		// store the height of your objects
		private function setHeights():void
		{
			contentHeight = content.height;
			contentMaskHeight = contentMask.height;
			scrollTrackHeight = scrollTrack.height;
			scrollButtonHeight = scrollButton.height;
		}
 
		// enable or disable the buttonMode property of your scroll button
		private function setButtonMode():void
		{
			scrollButton.buttonMode = buttonModeEnabled;
		}
 
		// apply the mask movie clip to the content movie clip
		private function setContentMask():void
		{
			// cache both the content and content mask so that you'll
			// be able to apply masks that container an alpha channel too
 
			content.cacheAsBitmap = true;
			contentMask.cacheAsBitmap = true;
			content.mask = contentMask;
		}
 
		// reposition your objects so that everything will scroll correctly
		private function repositionObjects():void
		{
			contentMask.x = content.x;
			scrollButton.x = scrollTrack.x;
			content.y = contentMask.y = scrollTrack.y = scrollButton.y = 0;
		}
 
		// store the scaleY property of the scroll track movie clip
		private function storeTrackScaleY():void
		{
			scrollTrackScaleY = scrollTrack.scaleY;
		}
 
		// add all the event listeners that will be handling the scrolling
		private function addListeners():void
		{
			enterFrameActive = false;
 
			// check to see if the actual height of the content is more than the
			// height of the content mask; if the content height is less, that means that there
			// is no use for a scroll track and nor for a scroll button, so we'll make them invisible
			// ... otherwise, add all the required listeners that will handle the scrolling
 
			if (contentHeight <= contentMaskHeight)
			{
				scrollTrack.visible = false;
				scrollButton.visible = false;
			}
			else
			{
				scrollTrack.visible = true;
				scrollButton.visible = true;
 
				if (useMouseWheel == true)
				{
					content.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
				}
 
				if (enableJumping == true)
				{
					scrollTrack.addEventListener(MouseEvent.MOUSE_DOWN, scrollTrackMouseHandler);
				}
 
				scrollButton.addEventListener(MouseEvent.MOUSE_DOWN, startDragHandler);
				scrollButton.addEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
				movieStage.addEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
			}
		}
 
		// the moveContentHandler function is responsible for moving the content movie clip
		// some easing is added too ( just to make it look better ) and an optional blur filter
		private function moveContentHandler(event:Event):void
		{
			// store the current Y position of the content movie clip
			currentContentY = content.y;
 
			moveValue = (contentHeight - contentMaskHeight) / (scrollTrackHeight - scrollButtonHeight);
			moveSpeed = (scrollButton.y * (-moveValue) - content.y) * easing;
			content.y += moveSpeed;
 
			// if blurEnabled is set to "true" then it will apply a blur filter to the movie clip that is holding the content;
			// you can edit the filter parameters so that it will fit your needs; I tried keeping the blurring feature as
			// simple as possible, this feature was intended to be a "fun feature" than something advanced
 
			if (blurEnabled == true)
			{
				content.filters = [new BlurFilter(Math.abs(moveSpeed / 8), Math.abs(moveSpeed), BitmapFilterQuality.MEDIUM)];
			}
 
			removeContentEnterFrame();
		}
 
		// function responsible for moving the scroll button movie clip if the
		// visitor uses the mouse wheel to scroll the content movie clip
		private function mouseWheelHandler(event:MouseEvent):void
		{
			allowRemove = true;
			addContentEnterFrame();
 
			scrollButton.y += event.delta * (-scrollSpeed);
 
			if (scrollButton.y <= 0)
			{
				scrollButton.y = 0;
			}
			else if (scrollButton.y >= (scrollTrackHeight - scrollButtonHeight))
			{
				scrollButton.y = scrollTrackHeight - scrollButtonHeight;
			}
		}
 
		// function responsible for the "jumping feature", meaning that you can click any point on
		// the scroll track movie clip and the scroll button will be moved to that certain point, updating
		// the content movie clip's positions at the same time
		private function scrollTrackMouseHandler(event:MouseEvent):void
		{
			if (event.eventPhase == EventPhase.AT_TARGET)
			{
				addContentEnterFrame();
 
				// check for the coordinates of the visitor's CLICK event on the scroll track movie clip, if the coordinates are
				// close to the top of the scroll track then the scroll button will be moved to the top of the track...
				// ...else if the click event had place close to the bottom of the track then the scroll button will be placed at 
				// the bottom of the track... else, it will be moved to the exact point from where the visitor has fired the CLICK event
 
				if (event.target.mouseY * scrollTrackScaleY <= (scrollTrackHeight - scrollButtonHeight / 2) &&
					event.target.mouseY * scrollTrackScaleY >= (scrollButtonHeight / 2))
				{
					scrollButton.y = event.target.mouseY * scrollTrackScaleY  - scrollButtonHeight / 2;
				}
				else if (event.target.mouseY * scrollTrackScaleY <= (scrollButtonHeight / 2))
				{
					scrollButton.y = 0;
				}
				else if (event.target.mouseY * scrollTrackScaleY >= (scrollTrackHeight - scrollButtonHeight / 2))
				{
					scrollButton.y = scrollTrackHeight - scrollButtonHeight;
				}
			}
		}
 
		// function responsible for the drag feature of the scroll button
		private function startDragHandler(event:MouseEvent):void
		{
			allowRemove = false;
			addContentEnterFrame();
			scrollButton.startDrag(false, new Rectangle(scrollTrack.x, scrollTrack.y, 0,(scrollTrackHeight - scrollButtonHeight)));
		}
 
		// function responsible for stopping the scroll button from dragging once the visitor releases it
		private function stopDragHandler(event:MouseEvent):void
		{
			scrollButton.stopDrag();
			allowRemove = true;
		}
 
		// function responsible for adding the ENTER_FRAME event that is responsible
		// for moving ( positioning ) the content movie clip
		private function addContentEnterFrame():void
		{
			if (enterFrameActive == false)
			{
				enterFrameActive = true;
				content.addEventListener(Event.ENTER_FRAME, moveContentHandler);
			}
		}
 
		// this function will remove the ENTER_FRAME event once the content movie clip stops scrolling
		private function removeContentEnterFrame():void
		{
			if (currentContentY == content.y && allowRemove == true)
			{
				content.removeEventListener(Event.ENTER_FRAME, moveContentHandler);
				enterFrameActive = false;
				allowRemove = false;
			}
		}
 
		// this is a simple function that removes all the listeners from all the objects
		// essentially, this function will be of much help if you want to use the same scrollbar instance
		// for all the content that will be displayed in your project
		public function kill():void
		{
			content.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			scrollTrack.removeEventListener(MouseEvent.MOUSE_DOWN, scrollTrackMouseHandler);
			content.removeEventListener(Event.ENTER_FRAME, moveContentHandler);
			scrollButton.removeEventListener(MouseEvent.MOUSE_DOWN, startDragHandler);
			scrollButton.removeEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
			movieStage.removeEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
		}
 
		// a public function responsible for updating the scrollbar, adding the event listeners again to each object,
		// repositioning all the objects, storing new values and enabling or disabling certain scrollbar features; 
		// all this is done ONLY after we remove the current event listeners with the help of the kill(); function
		public function update():void
		{
			kill();			
			setHeights();
			setButtonMode();
			storeTrackScaleY();
			repositionObjects();
			addListeners();
		}
 
		// public setter methods that will help you update the scrollbar, enable of disable features and add new values
 
		public function set setEasing(value:Number):void { easing = value };
		public function set setScrollSpeed(value:Number):void { scrollSpeed = value };
		public function set setMouseWheel(value:Boolean):void { useMouseWheel = value };
		public function set setJumping(value:Boolean):void { enableJumping = value };
		public function set setScrollButtonMode(value:Boolean):void { buttonModeEnabled = value };
 
		// public getter methods that you'll most likely not use very often but it's good to have them there;
		// if you run into problems / bugs then you can try debugging your application with the help of these getter
		// methods ( but if you are more familiar with the built-in Flash / Flex debugger then it's much better to use that instead )
 
		public function get getEasing():Number { return easing };
		public function get getScrollSpeed():Number { return scrollSpeed };
		public function get getMouseWheel():Boolean { return useMouseWheel };
		public function get getJumping():Boolean { return enableJumping };
		public function get getScrollButtonMode():Boolean { return buttonModeEnabled };
	}
}

It’s as efficient as it can get and certain features can be changed at runtime too ( with the help of the defined setter functions ).

Enjoy and don’t forget to report the bugs you find.

Posted in ActionScript 3.0 | 4 Comments »