highest safe dose of levitralevitra takecompare levitra cialis viagrageneric levitra onlinecheap herbal vardenafillevitra online uklevitra increases sperm countwomen\s vardenafillevitra samplelevitra slide kitmail order levitralevitra prescription onlinesoft levitraPurchase Levitra pillthe buy levitrageneric levitra canadaproduct team levitravardenafil 90 pills Buylevitra sale 32free sample prescription for levitralevitra trial offermedication levitranon prescription vardenafillevitra online shop in uklevitra medicareinformation levitralevitra on line saleslevitra japanqry vardenafilSale vardenafil 20 pillscheap herbal levitraidentify vardenafillevitra alternative lavitraflomax levitraGeneric Levitra 20 mg Salelevitra couponus vardenafilbuy levitra 10mglevitra commercial modelsforum levitraOnline vardenafil Courier shipping10 mg vs 20 mg levitralevitra dosage directionstoo much levitrawhere to puchase vardenafil onlinecheap levitra on linecialis levitra vardenafilhow levitra workqueen levitravardenafil 180 pills orderlevitra beogradlevitra birth control pillslevitra orallow cost alternatives and vardenafilLevitra 120 pills BuyBuy vardenafil Free Airmail shippingordering levitra onlinecialis levitra viagra comparebuy vardenafil online australiaorder levitra cheap pricevardenafil saleanyone tried generic levitravardenafil softabsbuy levitra viagra onlinelevitra user reviewneed for increasing amounts of levitralevitra online purchasewhat is vardenafilvardenafil rrp australia costvardenafil fast shippingvardenafil no prescriptionlevitra online gamblingviva levitrawomen taking levitradiscount vardenafil onlinelevitra sampleslowest price levitra generic onlinelevitra penslevitra and flomaxpurchase levitra 60 pillslevitra side effectorder Levitra 10 mgalternative to levitraby levitra priceBuy vardenafil Courier shippinguk alternative vardenafillevitra sarasota floridaprice on levitralevitra or viagra which is betterlevitra from canadalevitra ad reviewtry levitra for freeacheter du levitrawholesale vardenafillevitra where to buycomparison levitra cialistoo much vardenafilcomparison of levitra and viagradosage for levitrageneric mexican levitrahow to buy levitragenuine vardenafilcialis levitra viagra which is bettervardenafil onlinerelative costs of cialis levitraget vardenafil drug onlinelevitra vs viagra vs cialisorder levitra 30 pillssample of vardenafildiscount cialis levitra online canadanatural equivelant ingredient in levitraorder levitravardenafil 20 pills onlinecialis vardenafilreviews of viagra cialis and levitraeuropean vardenafilcanada in levitraPurchase Generic vardenafil 20 mglevitra 100mglevitra propafenoneinfo levitrauk levitra saleswoman\s levitraOnline Levitra 120 pillspurchase vardenafil 10 mggeneric levitra tab 20mgvardenafil australiacompare viagra to levitravardenafil 6 free samplesvardenafil canadian drugslevitra generikaOnline Levitra 20 mgwhat does vardenafil dovardenafil uterine thicknesslevitra hourslevitra cost of salesGeneric Levitra 10 mg ordervardenafil lengthvardenafil sideviagra cyalis levitra comparedlevitra pictureslevitra for salevardenafil online cheapLevitra 20 pills BuyLevitra Free Airmail shipping onlinebuy levitra online atgeneric levitra manufacturermaximum dosage levitravardenafil Courier shipping SaleSale vardenafil 10 pillswhat is better levitra or viagradifference between cialis levitra viagralevitracialis compare levitramedical drug levitravardenafil patent levitraprice levitralevitra tablevardenafil vs cialisvardenafil 180 pills Buyeffects of levitraget levitra drug onlinedreampharmaceuticals from levitranew erectile drug vardenafilover the counter levitrabuy levitra australiangeneric vardenafil indiacialis dysfunction erectile levitralevitra side effects visiondiscount levitra pillsOnline vardenafil Free Insurancecanadian pharmacy levitralevitra low costlevitra reviewsPurchase Generic Levitranew erectile drug levitravardenafil usevardenafil pricinglevitra herb alternativeOrder Generic vardenafil 20 mgvardenafil max complaintsfree vardenafil sampleslevitra or viagraSale Levitra 10 mglevitra lowest pricecheap vardenafil siproblems with levitralevitra suppliers in the ukwatermelon levitralevitra to buy new zealandmedicine levitralevitra 10 mg tabletbuy levitra online dream pharmaceuticalsoft levitra mastercardlevitra ingredientsvardenafil perscription onlinegeneric levitra cheapcanadian vardenafillevitra and price listvardenafil hcl 20 mgbayer levitra onlinefree trial of vardenafilbuy levitra delived fed exrecreational levitra usekey buy levitra onlinelevitrabuy cheap levitra onlineGeneric vardenafil 10 mg onlineorder cheap levitra faslevitra by bayervardenafil 30 pills onlineship free vardenafil sampleregalis vardenafilbuy levitra usvardenafil super activeLevitra 180 pills Buydrug levitra newvardenafil purchasevardenafil 30 pills orderprofessional levitra627 discount levitra online 903levitra and premature ejaculationpfizer vardenafilcialis levitra or viagralevitra twice a daysnorting levitraorder 50mg levitrabuy Levitra 10mgLevitra pills Buybuy cheap levitra onlinelevitra vs cialis reviewbrand name levitratake levitralevitra pill pricevardenafil optionslevitra cialis for womenhow to get levitravardenafil alternativespharmacy vardenafilbuy levitra ukvardenafil hcl 20mg tab side effectsbuy levitra in ukgeneric levitra professionallevitra efectosgeneric levitra effectiveorder vardenafil 10 mg2buy levitra online viagralevitra worksflomax and levitraSale Levitra Airmail shippingclinical data levitrageneric levitra soft tab fasti have levitrarx levitravardenafil 120 pillsbuy vardenafil meds onlinevardenafil online no prescriptionis vardenafil professional realcheap vardenafil walmartuk levitrabuy levitra in canadavardenafil from indiafree sample pack of levitramature vardenafilhow long is levitra effectivelevitra price comparisonlevitra storyvardenafil effekter biverkningarvardenafil for teenscheapest levitra in ukfda on levitralevitra fedexgeneric vardenafil mexicosample levitralevitra best resultslevitra substitutelevitra generic soft tabsafe maximum levitra dosagelevitra online cheapLevitra pills onlinevardenafil free sampleslevitra dysfunction erectilelevitra rxlevitra from mexicovardenafil drug prescriptionvardenafil discountsOrder vardenafil Free Insurancelevitra precautionsbuy buy cheap cheap levitra levitralevitra v s levitravardenafil sex dominationlevitra success storieslevitra for womanvardenafil 20 mg paypallevitra sverigecheap levitra overnightOrder Levitra Airmail shippingbuy vardenafil 10 pillscounterfeit levitrabuy levitra 30 pillsvardenafil suppliers in the ukvardenafil effective timeLevitra Courier shipping orderorder levitra from canadabuy drug satellite tv levitralevitra 20order vardenafillevitra wholesale onlinelevitra fast overnight delivery usa onlyuser review levitracialis and levitra generic brandgeneric levitralevitracialis generic levitra viagralevitra online usdoes levitra look likebuy levitra lowest pricescompare viagra levitralevitra on linesample of levitraviagra cialis levitra candian pharmacy safecheap vardenafil nzprice of vardenafilbuy online vardenafilnatural levitrageneric levitra pillsnatural equivalent ingredient in vardenafilordering vardenafillevitra free pillsbuy vardenafil in uklevitra order2buy generic levitralevitra pay with paypalvardenafil in uk onlineglaxo levitravardenafil and commercialvardenafil 50 mglevitra with lisinoprilwhat does levitra dobuy levitra medicationlevitra couchcan a woman take levitravardenafil 10mgreal levitralevitra offervardenafil 10 pills Buylowest prices for levitracanada vardenafilfree levitra pillscheapest online cost for levitravardenafil generic pricevardenafil gelvardenafil mexicovardenafil ukon levitralevitra discussiongeneric name of levitrabuy vardenafil 30 pillslevitra price walmartlevitra time effectiveLevitra Free Airmail shipping Salevardenafil wholesale onlinelevitra andacheter levitra francecheap vardenafil 20 mgwoman in levitra commercialpill identification levitrageneric discount levitralevitra 20 mg dosagelevitra interactionsoriginal levitrapurchase vardenafil 10mgbuy levitra online in 24 hoursvardenafil for sale without a prescriptionlevitrabuy levitra onlineLevitra 10 mg onlineviagra medication prescription levitra cialis propecialevitra anwendungviagra cialis levitra vpxlcan woman take levitrabuy levitra upsLevitra 90 pills BuySale vardenafil pillovernight vardenafilvardenafil reviewslevitra drugswatermellon vardenafilbuy levitra without prescriptionquery lowest levitra price onlinebuying levitra onlinelevitra generic priceusing levitralevitra for freegeneric viagra levitra generic cialis pillsvardenafil testimonialGeneric Levitra 20 mg ordervardenafil on linevardenafil Free Airmail shipping onlinehow long will levitra lastq buy levitraorder discount levitraviagra levitra cialis offerslevitra and bayercheap pharmacy viagra cialis levitralevitra vs viagra reviewswomans levitraburing levitra onlinelevitra softbuy cheap levitralevitra drug prescriptionbuy levitra in englandvardenafil Salevardenafil for daily useactress in levitra commercialbuy levitra with pay palcheap vardenafil overnightindia vardenafilvardenafil pill orderbuy levitra online 35008 buylevitra pill cuttervardenafil sizevardenafil uk cost pillvardenafil 60 pills onlinegeneric soft tabs vardenafilkey buy levitra cheaplevitra cheap buy onlinelow price vardenafilcheap vardenafil tabletslevitra onlinevardenafil 20 mg orderblindness cialis levitravardenafil levitra onlinelevitra faqsplitting levitravardenafil in ukvardenafil lowest priceprozac interactions with viagra cialis levitrakeywords cialis levitra sales viagrahow quick does levitra workwhat is levitra productPurchase vardenafil Free Airmail shippingLevitra 20 mgcomparison of cialis levitra and viagraovernight shipping of professional vardenafilbenefits of levitralevitra vs viagra which is better2buy cheap levitra onlinelevitra prices american pharmaciesvardenafil online overnightdiscount levitra cialis viagrabuy cheap levitra xanax xenicalorder levitra onlinecheapest vardenafil substitute vardenafilbuy vardenafil cialasbuy cheap generic levitra pharmacy onlinelevitra soft tablevitra third quarter 2004 saleslevitra bestellenvardenafil fedexviva levitra commercialLevitra Courier shipping Salecheapest vardenafil professionalLevitra 10 pills Buycheap vardenafil canadaOnline Levitra Free Airmail shippingfull information levitradiscounted vardenafillevitra substitutesLevitra 20 mg Buylevitra 20 mg bayerbuy vardenafil delived fed exforeign cialis levitra pillswomen vardenafilvardenafil overnight shippingcan women use levitravardenafil Buyvardenafil propafenonelevitra provardenafil impotence drug eli lilly cobuy levitra viagralevitra web siteship free levitra sampleorder levitra without prescriptionfree levitra onlinesuper levitralevitra in ukcompare viagra 26 levitra2cheap levitra onlineOrder vardenafilvardenafil Courier shipping orderbuy vardenafilvardenafil storieslevitra successdiscount levitra purchasecheapest levitra substitute sildenafillevitra cialis viagra comparebuy vardenafil online in ukLevitra 20 mg onlineordering levitraconnecticut levitra vardenafillevitra productsLevitra Free Airmail shipping BuyGeneric vardenafil 10 mg Sale
intense creativity » Tutorial - Creating a reusable Slider Control / Component

Tutorial - Creating a reusable Slider Control / Component

Hi Everyone,

Today I will cover the subject of creating a reusable slider control which takes two bitmaps as resources. The thumb bitmap will slide on the rail bitmap. It is a very simple concept!

We will basically take this image:
and this one:
and make this (try it, move that knob):


In fact, the code you are about to write will take ANY two images and create a slider with them. Just like magic, as long as your images make some sense ( a track and a button ), it should be golden!

Starting Point
When I started writing this tutorial, I was still using the Flash IDE; but since then I am free!! I now use exclusively FlashDevelop. With that in mind, the package to start the coding, if you want to follow along is here. You will need FlashDevelop & the Flex SDK 3.4 or newer.

In the assets directory, I put the two bitmaps:

  • bar.png -- which contains the background
  • button.png -- which contains the foreground

Then I create a small class, which I called GraphicAssets like so:

Actionscript:
  1. package assets
  2. {
  3.     import flash.display.Bitmap;
  4.     /**
  5.      * ...
  6.      * @author Martin Legris
  7.      */
  8.  
  9.     public class GraphicAssets
  10.     {
  11.         [Embed(source="../../assets/bar.png")]
  12.         public static const BAR:Class;
  13.        
  14.         [Embed(source="../../assets/button.png")]
  15.         public static const BUTTON:Class;
  16.        
  17.         public static function getBitmap(template:Class):Bitmap
  18.         {
  19.             var inst:Object = new template();
  20.             var bitmap:Bitmap = new Bitmap(inst.bitmapData);
  21.             return bitmap;
  22.         }
  23.     }
  24. }

Notice the function getBitmap() which returns a bitmap, it is simply because I don't like overhead, and if you instantiate either GraphicAssets.BAR or GraphicAssets.BUTTON directly you end up with a BitmapAsset, and well, we don't need that.

To use it we'd simply do something like this:

Actionscript:
  1. var button:Bitmap = GraphicAssets.getBitmap(GraphicAssets.BUTTON);
  2. // or
  3. var bar:Bitmap = GraphicAssets.getBitmap(GraphicAssets.BAR);

Startup Properties
I sometimes create a class which contains the modifiable properties of a Component. In this case, I called it SpriteSliderProperties and here is the code:

Actionscript:
  1. package newcommerce.controls
  2. {
  3.     import flash.display.DisplayObject;
  4.     import flash.display.Sprite;
  5.     import flash.events.EventDispatcher;
  6.    
  7.     /**
  8.      * ...
  9.      * @author Martin Legris ( http://blog.martinlegris.com )
  10.      */
  11.    
  12.     public class SpriteSliderProperties
  13.     {
  14.         protected var _bg:DisplayObject;
  15.         protected var _fg:DisplayObject;
  16.        
  17.         protected var _min:Number;
  18.         protected var _max:Number;
  19.         protected var _stepSize:Number;
  20.         protected var _decimals:Number;
  21.         protected var _defaultValue:Number;
  22.        
  23.         public function get fg():DisplayObject { return _fg; }
  24.         public function set fg(value:DisplayObject):void { _fg = value; }
  25.        
  26.         public function get bg():DisplayObject { return _bg; }
  27.         public function set bg(value:DisplayObject):void { _bg = value; }
  28.        
  29.         public function get min():Number { return _min; }
  30.         public function set min(value:Number):void { _min = value; }
  31.        
  32.         public function get max():Number { return _max; }
  33.         public function set max(value:Number):void { _max = value; }
  34.        
  35.         public function get stepSize():Number { return _stepSize; }
  36.         public function set stepSize(value:Number):void { _stepSize = value; }
  37.        
  38.         public function get decimals():Number { return _decimals; }
  39.         public function set decimals(value:Number):void { _decimals = value; }
  40.        
  41.         public function get defaultValue():Number { return _defaultValue; }
  42.         public function set defaultValue(value:Number):void { _defaultValue = value; }
  43.        
  44.         public function SpriteSliderProperties(bg:DisplayObject, fg:DisplayObject, min:Number = 0, max:Number = 100, stepSize:Number = 10, decimals:Number = 0, defaultValue:Number = NaN)
  45.         {
  46.             _bg = bg;
  47.             _fg = fg;
  48.            
  49.             _min = min;
  50.             _max = max;
  51.             _stepSize = stepSize;
  52.            
  53.             _decimals = decimals;
  54.            
  55.             if (isNaN(defaultValue))
  56.                 _defaultValue = min;
  57.             else
  58.                 _defaultValue = defaultValue;
  59.         }
  60.     }
  61. }

As described in the code, we have one DisplayObject which will act as the background of the component, and another that will act as the foreground (movable) object in the component. There is also:

  • A minimum value, defaulted at 0
  • A maximum value, defaulted at 100 -- basically this means the slider will have values ranging from 0 to 100
  • The step size, when clicking besides the button itself. This is not going to be implemented, let's call it your homework!
  • The amount of numbers after the decimal that we want
  • The default value, or starting value; value demonstrated before the user interacts with it

Our usage scenario.. the target!
What we want is to create this slider but passing a SpriteSliderProperties object to the constructor; then add it to the stage. Then position it if we'd like and finally listen to events thrown by the Slider instance. The idea is to have two types of events:

  • ValueEvent.PREVIEW -- called while the user is moving the slider button
  • ValueEvent.CHANGE -- called once the user is done moving the button

Here is sample code, our target:

Actionscript:
  1. var bg:Bitmap = GraphicAssets.getBitmap(GraphicAssets.BAR);
  2. var fg:Bitmap = GraphicAssets.getBitmap(GraphicAssets.BUTTON);
  3.  
  4. var props:SpriteSliderProperties = new SpriteSliderProperties(bg, fg, 0, 100, 10, 1, 0);
  5. var slider:SpriteSlider = new SpriteSlider(props);
  6. addChild(_slider);
  7.  
  8. slider.addEventListener(ValueEvent.PREVIEW, doSliderValuePreview);
  9. slider.addEventListener(ValueEvent.CHANGED, doSliderValueChanged);
  10.  
  11. slider.x = 0;
  12. slider.y = (stage.stageHeight - _slider.height) / 2;

ValueEvent class
This class carries the value inside of it. Here is the source code:

Actionscript:
  1. package newcommerce.events
  2. {
  3.     import flash.events.Event;
  4.    
  5.     /**
  6.      * ...
  7.      * @author Martin Legris
  8.      */
  9.     public class ValueEvent extends Event
  10.     {
  11.         public static const CHANGED:String = "value_changed_event";
  12.         public static const PREVIEW:String = "value_preview_event";
  13.        
  14.         protected var _value:Number = 0;
  15.         public function get value():Number { return _value; }      
  16.        
  17.         public function ValueEvent(type:String, value:Number)
  18.         {
  19.             _value = value;
  20.             super(type);
  21.         }
  22.     }
  23. }

Nothing complicated there.

The meat
Now that the context is well established, lets get down to business. I will follow the methodology I started describing in this post (I promise to finish it sometime in the future). Just to recap.. At creation time the following functions are called:

  • init() -- initialization of member variables like arrays, dictionaries, timers ...
  • createChilds() -- the creation of displayObject used inside of the component
  • initEvents() -- adding event listeners
  • arrange() -- positioning the childs
  • redraw() -- drawing of the interface, if needed

Then, when the function setSize() is called:

  • arrange()
  • redraw()

In the component model of Flex there is the concept of invalidation; where you invalidate certain properties of the components and the code that will react to this invalidation is executed using callLater (on the next Frame). This way if you modify the size, then maybe data, arrange() (for example) will only be executed once, not twice. I showed how to implement your own callLater function in this post. For this example, I won't go there. There is no need...

In this example, I use newcommerce.controls.BaseControl as the parent class to SpriteSlider. This class contains the following code (you don't need to read it all if you don't want to). This class is contained in the starter packaged you might have downloaded at the beginning of this tutorial.

BaseControl

Actionscript:
  1. package newcommerce.controls{
  2.    
  3.     import flash.display.DisplayObject;
  4.     import flash.display.Sprite;
  5.     import flash.events.MouseEvent;
  6.     import flash.events.Event;
  7.     import ascb.drawing.Pen;
  8.     import newcommerce.drawing.AbstractDrawing;
  9.    
  10.     public class BaseControl extends Sprite{
  11.    
  12.         public var _width:Number = 0;
  13.         public var _height:Number = 0;
  14.         private var _padding:Number = 5;
  15.         protected var _mouseDown:Boolean = false;
  16.         protected var _drawing:AbstractDrawing;
  17.        
  18.         public override function get width():Number
  19.         {
  20.             return _width;
  21.         }
  22.        
  23.         public override function get height():Number
  24.         {
  25.             return _height;
  26.         }
  27.        
  28.         public function get drawing():AbstractDrawing
  29.         {
  30.             return _drawing;
  31.         }
  32.        
  33.         public function set drawing(drawing:AbstractDrawing):void
  34.         {
  35.             _drawing = drawing;
  36.         }
  37.        
  38.         public function get padding():Number
  39.         {
  40.             return _padding;
  41.         }
  42.        
  43.         public function set padding(padding:Number):void
  44.         {
  45.             _padding = padding;
  46.         }
  47.       
  48.       // The setSize() method is automatically called when the authoring time instance is resized.
  49.         public function setSize(nW:Number, nH:Number):void {
  50.             scaleX = 1;
  51.             scaleY = 1;
  52.             _width = nW;
  53.             _height = nH;
  54.             arrange();
  55.             redraw();
  56.         }
  57.        
  58.         public function getSize():Object
  59.         {
  60.             return {width:_width, height:_height};
  61.         }
  62.        
  63.  
  64.         public function BaseControl(initObj:Object)
  65.         {         
  66.             for(var i:String in initObj)
  67.             {
  68.                 this[i] = initObj[i];
  69.             }
  70.            
  71.             init();
  72.             createChilds();
  73.             initEvents();
  74.             arrange()
  75.             redraw();
  76.         }      
  77.        
  78.         protected function init():void
  79.         {
  80.             if(_width <= 0)   
  81.                 _width = width;
  82.             if(_height <= 0)
  83.                 _height = height;
  84.                
  85.             scaleX = 1;
  86.             scaleY = 1;
  87.         }
  88.        
  89.         protected function initEvents():void
  90.         {
  91.             addEventListener(MouseEvent.MOUSE_DOWN, doMouseDown);
  92.             addEventListener(MouseEvent.MOUSE_UP, doMouseUp);
  93.             addEventListener(Event.ADDED_TO_STAGE, doAddedToStage);
  94.         }
  95.        
  96.         protected function createChilds():void
  97.         {         
  98.         }
  99.        
  100.         protected function doAddedToStage(evt:Event):void
  101.         {
  102.             stage.addEventListener(MouseEvent.MOUSE_UP, doParentRelease);
  103.         }
  104.        
  105.         public function triggerRedraw():void
  106.         {
  107.             redraw();
  108.         }
  109.        
  110.         public function rearrange():void
  111.         {
  112.             arrange();     
  113.         }      
  114.        
  115.         protected function redraw():void
  116.         {
  117.             var pen:Pen = new Pen(graphics);
  118.             pen.clear();
  119.             pen.lineStyle(0,0,0);
  120.             pen.moveTo(0,0);
  121.             pen.beginFill(0,0);
  122.             pen.drawRect(0,0,_width,_height);
  123.             pen.endFill();
  124.         }
  125.        
  126.         protected function arrange():void
  127.         {
  128.             x = Math.round(x);
  129.             y = Math.round(y);
  130.         }
  131.        
  132.         protected function doMouseDown(evt:MouseEvent):void
  133.         {
  134.             _mouseDown = true;
  135.         }
  136.        
  137.         protected function doMouseUp(evt:MouseEvent):Boolean
  138.         {
  139.             if(_mouseDown)
  140.             {
  141.                 _mouseDown = false;
  142.                 return true;
  143.             }
  144.             else
  145.             {
  146.                 return false;
  147.             }
  148.         }
  149.        
  150.         protected function initBtn(btn:*):void
  151.         {
  152.             btn.useHandCursor = true;
  153.             btn.buttonMode = true;
  154.             btn.mouseChildren = false;
  155.         }
  156.        
  157.         public function doParentRelease(evt:MouseEvent):void
  158.         {
  159.             for(var i:Number = 0; i <this.numChildren; i++)
  160.             {
  161.                 var child:DisplayObject = getChildAt(i);
  162.                 if(child is BaseControl)
  163.                     (child as BaseControl).doParentRelease(evt);
  164.             }
  165.            
  166.             doMouseUp(evt);
  167.         }
  168.        
  169.         public function mouseInside():Boolean
  170.         {
  171.             return (mouseX>= 0 && mouseX <= _width && mouseY>= 0 && mouseY <= _height);
  172.         }
  173.     }
  174. }

Basically it has some functionality like:

  • making sure the control is on a whole pixel (not x:4.51 and y:9.56 for example)
  • takes care of covering the components space with a transparent layer to make sure we capture mouse event properly
  • ensures the component is never scaled directly
  • takes over the reporting of .width and .height
  • and has a few helper functions

Most of the functions below override the functions coded in BaseControl, and it is important to call the original in most cases by using super.init(); for example.

Initialization Code
The method I use for drag & drop uses a Timer object. Since this object is not part of the display list, I initialize it in the init() function; then set the slider's value to the defaultValue.

Actionscript:
  1. override protected function init():void
  2. {
  3.     super.init();
  4.     _timer = new Timer(33, 0);
  5.     _timer.addEventListener(TimerEvent.TIMER, doTimer);
  6.            
  7.     _value = _props.defaultValue;
  8. }

Creating Children Objects
Because we will listen to mouse events on the button & track, they both need to be Sprite objects. Hence we need to make sure the DisplayObjects passed in the Properties class ARE sprites, or if not, put them inside of sprites and use those as BG & FG. Hence this function which does exactly that.

Actionscript:
  1. protected function spritify(obj:DisplayObject):Sprite
  2. {
  3.     if (!(obj is Sprite))
  4.     {
  5.         var sprt:Sprite =  new Sprite();
  6.         sprt.addChild(obj);
  7.         obj = sprt;
  8.     }
  9.    
  10.     return obj as Sprite;
  11. }

Now, we will spritify both _props.bg & _props.fg, name them, add as childs of SpriteSlider and finally make sure we display the correct cursor when the mouse is over them. Like so:

Actionscript:
  1. override protected function createChilds():void
  2. {
  3.     super.createChilds();
  4.    
  5.     _bg = spritify(_props.bg);
  6.     _bg.name = "bg";           
  7.     addChild(_bg);
  8.     initBtn(_bg);
  9.    
  10.     _fg = spritify(_props.fg);
  11.     _fg.name = "fg";
  12.     addChild(_fg);
  13.     initBtn(_fg);
  14.    
  15.     _width = _bg.width;
  16.     _height = Math.max(_fg.height, _bg.height);
  17. }

You see at the end I take the width of the _bg and make it the width if the Component, and take the biggest of heights (from _fg and _bg) as the component's height.

Here is the full code, I will continue later...

Actionscript:
  1. package newcommerce.controls
  2. {
  3.     import flash.display.DisplayObject;
  4.     import newcommerce.events.ValueEvent;
  5.     import flash.display.Sprite;
  6.     import flash.events.MouseEvent;
  7.     import flash.events.TimerEvent;
  8.     import flash.utils.Timer;
  9.    
  10.     /**
  11.      * @eventType newcommerce.events.ValueEvent.CHANGED
  12.      */
  13.     [Event(name="value_changed_event",type="newcommerce.events.ValueEvent")]
  14.  
  15.     /**
  16.      * @eventType newcommerce.events.ValueEvent.PREVIEW
  17.      *
  18.      */
  19.     [Event(name="value_preview_event",type="newcommerce.events.ValueEvent")]
  20.    
  21.     /**
  22.      * ...
  23.      * @author Martin Legris -- http://blog.martinlegris.com
  24.      */
  25.     public class SpriteSlider extends BaseControl
  26.     {
  27.         protected var _bg:Sprite;
  28.         protected var _fg:Sprite;
  29.        
  30.         protected var _value:Number;
  31.         protected var _pos:Number;
  32.         protected var _lastValue:Number;
  33.        
  34.         protected var _timer:Timer;
  35.        
  36.         protected var _props:SpriteSliderProperties;
  37.        
  38.         public function get value():Number { return _value; }
  39.         public function set value(value:Number):void { _value = value; updatePosFromValue() }
  40.        
  41.         override public function get width():Number { return super.width; }  
  42.         override public function set width(value:Number):void { throw new Error("Cannot set the width manually on a SpriteSlider"); }
  43.        
  44.         override public function get height():Number { return super.height; }
  45.         override public function set height(value:Number):void { throw new Error("Connot set the heigth manually on a SpriteSlider"); }
  46.        
  47.         protected function get minPos():Number { return 0 + _fg.width / 2; }       
  48.         protected function get maxPos():Number { return _width - _fg.width / 2; }
  49.         protected function get span():Number { return max - min; }
  50.         protected function get space():Number { return _bg.width - _fg.width; }
  51.        
  52.         protected function get min():Number { return _props.min; }
  53.         protected function get max():Number { return _props.max; }
  54.         protected function get stepSize():Number { return _props.stepSize; }
  55.        
  56.         public function get props():SpriteSliderProperties { return _props; }      
  57.        
  58.         public function SpriteSlider(props:SpriteSliderProperties)
  59.         {
  60.             _props = props;
  61.             super({});
  62.         }
  63.        
  64.         override protected function init():void
  65.         {
  66.             super.init();
  67.             _timer = new Timer(33, 0);
  68.             _timer.addEventListener(TimerEvent.TIMER, doTimer);
  69.            
  70.             _value = _props.defaultValue;
  71.         }
  72.        
  73.         override protected function createChilds():void
  74.         {
  75.             super.createChilds();
  76.            
  77.             _bg = spritify(_props.bg);
  78.             _bg.name = "bg";           
  79.             addChild(_bg);
  80.             initBtn(_bg);
  81.            
  82.             _fg = spritify(_props.fg);
  83.             _fg.name = "fg";
  84.             addChild(_fg);
  85.             initBtn(_fg);
  86.            
  87.             _width = _bg.width;
  88.             _height = Math.max(_fg.height, _bg.height);
  89.         }
  90.        
  91.         protected function spritify(obj:DisplayObject):Sprite
  92.         {
  93.             if (!(obj is Sprite))
  94.             {
  95.                 var sprt:Sprite =  new Sprite();
  96.                 sprt.addChild(obj);
  97.                 obj = sprt;
  98.             }
  99.            
  100.             return obj as Sprite;
  101.         }
  102.  
  103.         override protected function initEvents():void
  104.         {
  105.             super.initEvents();
  106.             _fg.addEventListener(MouseEvent.MOUSE_DOWN, doBtnDown);
  107.             _bg.addEventListener(MouseEvent.MOUSE_DOWN, doBtnDown);
  108.         }
  109.  
  110.         protected function doTimer(evt:TimerEvent):void
  111.         {
  112.             _pos = mouseX;
  113.             _pos = Math.max(_pos, minPos);
  114.             _pos = Math.min(_pos, maxPos);
  115.            
  116.             setValue((_pos - minPos) / space * span + min);
  117.            
  118.             if(_value != _lastValue)
  119.                 dispatchEvent(new ValueEvent(ValueEvent.PREVIEW, _value));
  120.            
  121.             _lastValue = _value;
  122.            
  123.             arrange();
  124.         }
  125.        
  126.         protected function updatePosFromValue():void
  127.         {
  128.             if (value>= min && value <= max)
  129.                 _fg.x = (value - min) * space / span + minPos;
  130.             else
  131.                 throw new Error("value (" + _value + ") is outside of range[" + min + "," + max + "]");
  132.         }
  133.        
  134.         protected function setValue(newValue:Number):void
  135.         {
  136.             var multiplier:Number = Math.pow(10, _props.decimals);
  137.             newValue *= multiplier;
  138.             newValue = Math.round(newValue);
  139.             newValue /= multiplier;
  140.            
  141.             _value = newValue;
  142.         }
  143.  
  144.         protected function doBtnDown(evt:MouseEvent):void
  145.         {
  146.             _timer.start();
  147.         }
  148.        
  149.         override protected function arrange():void
  150.         {
  151.             super.arrange();
  152.            
  153.             _bg.y = (_height - _bg.height) / 2;
  154.             _bg.x = 0;
  155.            
  156.             _fg.x = _pos - _fg.width / 2;
  157.         }
  158.  
  159.         override protected function doMouseUp(evt:MouseEvent):Boolean
  160.         {
  161.             if (_mouseDown)
  162.             {
  163.                 _timer.stop();
  164.                 dispatchEvent(new ValueEvent(ValueEvent.CHANGED, _value));
  165.             }
  166.  
  167.             return super.doMouseUp(evt);
  168.         }
  169.     }
  170. }

One Response to “Tutorial - Creating a reusable Slider Control / Component”

  1. chuchu says:

    Hi Martin,

    I like your application Fxtube want to implemented in my application but i try everything dont work still get this security error and i allready upload the proxy file please hellllllllllllllllllllllllllllllppppppppppp :)

    Thanx in advanced
    chuchu

Leave a Reply