Rating Component (Flex)

This is the example of rating component:

rating.mxml

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; layout=”vertical”
xmlns=”com.Rating.*” horizontalAlign=”center” verticalAlign=”middle” >
<mx:Style>
Ratings{
horizontalGap:3;
paddingTop:3;
paddingLeft:6;
}

RatingItem{
borderAlpha:0;
fillEnabled:true;
fillColors:FFCC33,FFCC33;
fillSelectedColors:#FF9933,#FF9933;
fillAlphas:1,1;
fillRatios:0,255;
fillAngle:90;
}
</mx:Style>

<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.*;
[Bindable] private var rate_number:Number;
private function handleChange(event:Event):void
{
rate_number=Number(event.currentTarget.value);
Alert.show(String(rate_number));
}
]]>
</mx:Script>

<Ratings id=”rateit” change=”handleChange(event);” horizontalGap=”3″
tooltips=”[‘Bad’,’Better’,’Average’,’Good’,’WOW!! +5′]”
value=”0″ width=”60″  height=”14″ x=”169″ y=”34″
points=”5″
innerRadius=”25″
outerRadius=”50″
angle=”90″
styleName=”example7″
/>
</mx:Application>

Here is the Components which we adding in our main file:

in folder com

Ratings.as

package com.Rating
{
import mx.core.UIComponent;

import flash.events.MouseEvent;
import flash.events.Event;

import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.IDataRenderer;
import mx.events.FlexEvent;

[Style(name=”horizontalGap”, type=”Number”, format=”Length”, inherit=”no”)]
[Style(name=”paddingLeft”, type=”Number”, format=”Length”, inherit=”no”)]
[Style(name=”paddingTop”, type=”Number”, format=”Length”, inherit=”no”)]

[Event(“change”)]
public class Ratings extends UIComponent implements IDataRenderer, IDropInListItemRenderer,    IListItemRenderer
{

public function Ratings():void
{
//add the mouse move event listener so that we can update
//the display as the user moves out of the component capture both
//rollout and mouse out to ensure proper display updating
addEventListener(MouseEvent.MOUSE_OUT,handleMouseOut);
addEventListener(MouseEvent.ROLL_OUT,handleMouseOut);

//make sure we can get notified of the child events
mouseChildren = true;

}

/**
* Store the number of items to create.
**/
private const itemCount:Number =5;

private var contentWidth:Number=0;

/**
* Data storage.
**/
private var _data:Object;

[Bindable(“dataChange”)]
[Inspectable(environment=”none”)]
public function get data():Object
{
return _data;
}

public function set data(value:Object):void
{
_data = value;

try{
if (_listData && _listData is DataGridListData)
{
this.value = _data[DataGridListData(_listData).dataField];
}
else
{
this.value = int(_listData.label);
}

}
catch(e:Error){
this.value =0;
}

dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));

}

/**
* Storage for the listData property.
*/
private var _listData:BaseListData;
[Bindable(“dataChange”)]
public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = value;
}

/**
* An array of tooltips for the rating items
**/
[Bindable]
[Inspectable]
private var _tooltips:Array = null;
public function set tooltips(value:Array):void
{
_tooltips = value;

}
public function get tooltips():Array
{
return _tooltips;
}

/**
* the value of the rating
**/
[Bindable(event=”change”)]
[Inspectable]
private var _value:int = 0;
public function set value(value:int):void
{
_value = value;
selectItems(value);

try{
if (_listData && _listData is DataGridListData)
{
_data[DataGridListData(_listData).dataField] = _value;
}
else
{
_listData.label = _value.toString();
}
}
catch(e:Error){

}

dispatchEvent(new Event(“change”));

}
public function get value():int
{
return _value;
}

[Bindable]
[Inspectable]
private var _outerRadius:Number=50;
public function set outerRadius(value:Number):void
{
_outerRadius = value;
updateChildren(“outerRadius”,value);
}

public function get outerRadius():Number
{
return _outerRadius;

}

[Bindable]
[Inspectable]
private var _innerRadius:Number=25;
public function set innerRadius(value:Number):void
{
_innerRadius = value;
updateChildren(“innerRadius”,value);
}
public function get innerRadius():Number
{
return _innerRadius;
}

[Bindable]
[Inspectable]
private var _points:Number=5;
public function set points(value:Number):void
{
_points = value;
updateChildren(“points”,value);
}
public function get points():Number
{
return _points;
}

[Bindable]
[Inspectable]
private var _angle:Number = 90;
public function set angle(value:Number):void
{
_angle = value;
updateChildren(“angle”,value);
}
public function get angle():Number
{
return _angle;
}

/**
* Update the children if the property changes.
**/
private function updateChildren(property:String, value:Number):void
{
for (var i:int = 1; i < itemCount+1; i++)
{

if (getChildByName(i.toString())){
RatingItem(getChildByName(i.toString()))[property]=value;
}
}

}

/**
* Add the star objects for rating and set thier properties and
* add the event listener for rollover and click
**/
override protected function childrenCreated():void
{

//use the horizontal Gap style for spacing between items
var horizontalGap:Number = getStyle(“horizontalGap”);
var paddingLeft:Number = getStyle(“paddingLeft”);
var paddingTop:Number = getStyle(“paddingTop”);

var lastX:Number = 0;

//create each item, set the properties, and add the listeners.
for (var i:int = 1; i < itemCount+1; i++)
{

var newItem:RatingItem = new RatingItem();
newItem.id = (i).toString();
newItem.name =(i).toString();

//if the tooltips are set apply it to the primitive
if (tooltips)
{
if (tooltips.length >(i-1)){
newItem.toolTip = tooltips[i-1].toString();
}
}

//set the default width and height
newItem.width = 12;
newItem.height = 12;
addChild(newItem);

if (lastX == 0)
{
newItem.x=paddingLeft;
}
else
{
newItem.x= ((12+horizontalGap)+lastX);
}

lastX = newItem.x;

newItem.y= paddingTop;

//set the inicial value based on this value
if ((i-1) < value)
{
newItem.selected = true;
}

newItem.addEventListener(MouseEvent.CLICK,handleItemClick,false,1);
newItem.addEventListener(MouseEvent.ROLL_OVER,handleMouseRoll);
newItem.addEventListener(MouseEvent.ROLL_OUT,handleMouseRoll);

}

width=newItem.x+horizontalGap;
height = 12;
}

override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void
{

super.updateDisplayList(unscaledWidth,unscaledHeight);

//draw a transparent background so we can get the
//rollout/over event on the ui object in not doing
//this we’ll get flashing when moving between items
graphics.lineStyle(0,0xFFFFFF,0);
graphics.beginFill(0xFFFFFF,0);
graphics.drawRect(0,0,unscaledWidth,unscaledHeight);
graphics.endFill();

}

//do the selection based on passed value
private function selectItems(value:Number):void{
//make sure items are selected up to the target name
//and any items after are not selected
var currentItem:RatingItem;
for (var i:int = 1; i < itemCount+1; i++)
{
currentItem = RatingItem(getChildByName(i.toString()));
if (currentItem)
{
if (i <= value)
{
//selected
currentItem.selected = true;

}
else
{
//not selected
currentItem.selected = false;
}
}
}

}

private function handleMouseRoll(event:MouseEvent):void{
selectItems(Number(event.currentTarget.name));
}

private function handleMouseOut(event:MouseEvent):void{
if (event.currentTarget is Ratings)
{
selectItems(value);
}
}

/**
* handle the click and dispatch the event
**/
private function handleItemClick(event:MouseEvent):void
{

//prevent the default and stop the propogation
//so that the base class does not select it.
event.preventDefault();
event.stopImmediatePropagation();

if (event.currentTarget.id == 1 && value == 1){
value=0;
}
else{
value= Number(event.currentTarget.id);
}
dispatchEvent(event);
}
}
}

RatingItem.as

package com.Rating
{
import com.Primitives.PrimitiveStar;

/**
* Add any specific things you require here for your rating component.
**/
public class RatingItem extends PrimitiveStar
{
public function RatingItem()
{
super();
}
}
}

in folder Primitives

This folder incudes 4 files

BasePrimitive.as

package com.Primitives
{
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.*;

import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.EdgeMetrics;
import mx.core.IDataRenderer;
import mx.core.IFlexDisplayObject;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.managers.IFocusManagerComponent;

use namespace mx_internal;

include “PrimitiveStyles.as”;

public class BasePrimitive extends UIComponent
implements IDataRenderer, IDropInListItemRenderer,
IFocusManagerComponent, IListItemRenderer
{

public var selectedField:String = null;
private var selectedSet:Boolean;
private var styleChangedFlag:Boolean = true;

public function BasePrimitive()
{
mouseChildren = false;

//setup the events
addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
addEventListener(MouseEvent.CLICK, clickHandler);

addEventListener(FlexEvent.UPDATE_COMPLETE, handleUpdateComplete);

}

private var toolTipSet:Boolean = false;
[Inspectable(category=”General”, defaultValue=”null”)]
override public function set toolTip(value:String):void
{
super.toolTip = value;

if (value)
{
toolTipSet = true;
}
else
{
toolTipSet = false;
invalidateDisplayList();
}
}

mx_internal var _selected:Boolean = false;
[Bindable(“click”)]
[Bindable(“valueCommit”)]
[Inspectable(category=”General”, defaultValue=”false”)]

public function get selected():Boolean
{
return _selected;
}
public function set selected(value:Boolean):void
{
selectedSet = true;
setSelected(value);
}

mx_internal function setSelected(value:Boolean):void
{
if (_selected != value)
{
_selected = value;

invalidateDisplayList();

if (toggle)
dispatchEvent(new Event(Event.CHANGE));
dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
}
}

mx_internal var _toggle:Boolean = false;
mx_internal var toggleChanged:Boolean = false;

[Bindable(“toggleChanged”)]
[Inspectable(category=”General”, defaultValue=”false”)]
public function get toggle():Boolean
{
return _toggle;
}
public function set toggle(value:Boolean):void
{
_toggle = value;
toggleChanged = true;

invalidateProperties();
invalidateDisplayList();

dispatchEvent(new Event(“toggleChanged”));
}

private var _data:Object;

[Bindable(“dataChange”)]
[Inspectable(environment=”none”)]
public function get data():Object
{
if (!_data)
_data = {};

return _data;
}

public function set data(value:Object):void
{
var newSelected:*;

_data = value;

if (_listData && _listData is DataGridListData)
{
newSelected = _data[DataGridListData(_listData).dataField];

}
else if (_listData)
{
if (selectedField)
newSelected = _data[selectedField];

}
else
{
newSelected = _data;
}

if (newSelected !== undefined && !selectedSet)
{
selected = newSelected as Boolean;
selectedSet = false;
}

dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}

/**
* Storage for the listData property.
*/
private var _listData:BaseListData;

[Bindable(“dataChange”)]
[Inspectable(environment=”none”)]
public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = value;
}

/***
* Some extensions of this class may be required to not have a background drawn,
* so this provides and ability to specify that via the constructor
* of the extending class.
**/
private var _backgroundEnabled:Boolean = true;
public function set backgroundEnabled(value:Boolean):void
{
_backgroundEnabled = value;
invalidateProperties();
invalidateDisplayList();
}
public function get backgroundEnabled():Boolean
{
return _backgroundEnabled;
}

override public function styleChanged(styleProp:String):void
{
styleChangedFlag = true;
super.styleChanged(styleProp);
invalidateProperties();
invalidateDisplayList();
}

/**
* Events Handlers
**/
protected function rollOverHandler(event:MouseEvent):void
{
//trace(event);

}

protected function rollOutHandler(event:MouseEvent):void
{
//trace(event);

}

protected function mouseDownHandler(event:MouseEvent):void
{
//trace(event);
}
protected function mouseUpHandler(event:MouseEvent):void
{
//trace(event);
}

protected function clickHandler(event:MouseEvent):void
{
selected = !selected;
//trace(event);

}

/**
* End any fill or gradient fill drawing actions on this event
* so that the classes extending this one can do their specific
* drawing to the surface.
**/
private function handleUpdateComplete(event:FlexEvent):void
{
//End the fill always for each extension, since all common drawing is done in the
//base class. Including fills.
if (backgroundEnabled)
{
graphics.endFill();
}
}

override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void
{

super.updateDisplayList(unscaledWidth,unscaledHeight);

//clear the drawing surface.
graphics.clear();

/**
* Setup the line styles as required.
**/
//get the border color
var borderColor:uint;
if (!selected)
{
borderColor = getStyle(“borderColor”);
}
else
{
borderColor = getStyle(“borderSelectedColor”);
}

if (borderColor ==0)
{
borderColor = 0x000000;
}

var borderThickness:Number = getStyle(“borderThickness”);
var borderAlpha:Number = getStyle(“borderAlpha”);
var borderPixelHinting:Boolean = getStyle(“borderPixelHinting”);
var borderJointStyle:String = getStyle(“borderJointStyle”);

graphics.lineStyle(borderThickness,borderColor,borderAlpha,borderPixelHinting,”normal”,null,borderJointStyle);

if (getStyle(“borderFillEnabled”))
{
var borderColors:Array
if (!selected)
{
borderColors = getStyle(“borderColors”);
}
else
{
borderColors = getStyle(“borderSelectedColors”);
}

var borderAlphas:Array = getStyle(“borderAlphas”);
var borderRatios:Array = getStyle(“borderRatios”);

if (borderColors == null)
{
borderColors=[0x000000,0xFFFFFF];
}

if (borderAlphas == null)
{
borderAlphas=[1,1];
}

if (borderRatios == null)
{
borderRatios=[0,255];
}

var borderFillType:String = getStyle(“borderFillType”);
var borderSpreadMethod:String = getStyle(“borderSpreadMethod”);
var borderFocalPointRatio:Number = getStyle(“borderFocalPointRatio”);

var borderAngle:Number = getStyle(“borderAngle”);

if (!borderAngle)
{
borderAngle =0;
}

if (!borderFillType)
{
borderFillType = “linear”;
}

if (!borderSpreadMethod)
{
borderSpreadMethod = “pad”;
}

var borderMatrix:Matrix = new Matrix();
borderMatrix.createGradientBox(unscaledWidth,unscaledHeight,borderAngle, 0, 0);
graphics.lineGradientStyle(borderFillType, borderColors, borderAlphas, borderRatios, borderMatrix,borderSpreadMethod,”rgb”,borderFocalPointRatio);

}

//If fillcolors is set then use a gradient.
if (getStyle(“fillEnabled”) && backgroundEnabled)
{

var fillColors:Array;
if (!selected){
fillColors = getStyle(“fillColors”);
}
else{
fillColors = getStyle(“fillSelectedColors”);
}

var fillAlphas:Array = getStyle(“fillAlphas”);
var fillRatios:Array = getStyle(“fillRatios”);

if (fillColors == null)
{
fillColors=[0x000000,0xFFFFFF];
}

if (fillAlphas == null)
{
fillAlphas=[1,1];
}

if (fillRatios == null)
{
fillRatios=[0,255];
}

var fillType:String = getStyle(“fillType”);
var fillSpreadMethod:String = getStyle(“fillSpreadMethod”);
var fillFocalPointRatio:Number = getStyle(“fillFocalPointRatio”);

var fillAngle:Number = getStyle(“fillAngle”);

if (!fillAngle)
{
fillAngle =0;
}

if (!fillType)
{
fillType = “linear”;
}

if (!fillSpreadMethod)
{
fillSpreadMethod = “pad”;
}

var fillMatrix:Matrix = new Matrix();
fillMatrix.createGradientBox(unscaledWidth,unscaledHeight,fillAngle, 0, 0);
graphics.beginGradientFill(fillType, fillColors, fillAlphas, fillRatios, fillMatrix,SpreadMethod.REFLECT,”rgb”,fillFocalPointRatio);
}
else
{
if (backgroundEnabled){

var backgroundColor:uint;
if (!selected)
{
backgroundColor= getStyle(“backgroundColor”);
}
else
{
backgroundColor= getStyle(“backgroundSelectedColor”);
}

var backgroundAlpha:Number = getStyle(“backgroundAlpha”);

if (backgroundColor !=0)
{
graphics.beginFill(backgroundColor,backgroundAlpha);
}
}
}
}
}
}

DrawUtils.as

/**
* DrawUtils is a static class that provides a number of functions
* to draw shapes that are not part of the standard ActionScript Drawing
* API.
*
* based on source code found at:
* http://www.macromedia.com/devnet/mx/flash/articles/adv_draw_methods.html
*
* @author Ric Ewing – version 1.4 – 4.7.2002
* @author Kevin Williams – version 2.0 – 4.7.2005
* @author Jason Hawryluk – version 3.0 – 22.02.2007
*         -Modified for Flex 2.01
*/
package com.Primitives
{
import mx.core.UIComponent;

public class DrawUtils
{

public static function dashLineToPattern(target:UIComponent, x1:Number, y1:Number,x2:Number, y2:Number,pattern:Array):void
{

var x:Number = x2 – x1;
var y:Number = y2 – y1;
var hyp:Number = Math.sqrt((x)*(x) + (y)*(y));

var units:Number = hyp/(pattern[0]+pattern[1]);
var dashSpaceRatio:Number = pattern[0]/(pattern[0]+pattern[1]);

var dashX:Number = (x/units)*dashSpaceRatio;
var spaceX:Number = (x/units)-dashX;
var dashY:Number = (y/units)*dashSpaceRatio;
var spaceY:Number = (y/units)-dashY;

target.graphics.moveTo(x1, y1);

while (hyp > 0)
{
x1 += dashX;
y1 += dashY;
hyp -= pattern[0];
if (hyp < 0)
{
x1 = x2;
y1 = y2;
}

target.graphics.lineTo(x1, y1);
x1 += spaceX;
y1 += spaceY;
target.graphics.moveTo(x1, y1);
hyp -= pattern[1];
}

target.graphics.moveTo(x2, y2);
}

/**
* Draws an arc from the starting position of x,y.
**/
public static function arcTo(target:UIComponent, x:Number, y:Number, startAngle:Number, arc:Number, radius:Number,yRadius:Number):void
{

var ax:Number;
var ay:Number;

// Circumvent drawing more than is needed
if (Math.abs(arc)>360)
{
arc = 360;
}

// Draw in a maximum of 45 degree segments. First we calculate how many
// segments are needed for our arc.
var segs:Number = Math.ceil(Math.abs(arc)/45);

// Now calculate the sweep of each segment
var segAngle:Number = arc/segs;

// The math requires radians rather than degrees. To convert from degrees
// use the formula (degrees/180)*Math.PI to get radians.
var theta:Number = -(segAngle/180)*Math.PI;

// convert angle startAngle to radians
var angle:Number = -(startAngle/180)*Math.PI;

// find our starting points (ax,ay) relative to the secified x,y
ax = x-Math.cos(angle)*radius;
ay = y-Math.sin(angle)*yRadius;

// Draw as 45 degree segments
if (segs>0)
{
target.graphics.moveTo(x,y);

// Loop for drawing arc segments
for (var i:int = 0; i<segs; i++)
{

// increment our angle
angle += theta;

//find the angle halfway between the last angle and the new one,
//calculate our end point, our control point, and draw the arc segment
target.graphics.curveTo(ax+Math.cos(angle-(theta/2))*(radius/Math.cos(theta/2)),
ay+Math.sin(angle-(theta/2))*(yRadius/Math.cos(theta/2)),
ax+Math.cos(angle)*radius, ay+Math.sin(angle)*yRadius);

}
}
}

/**
* Burst is a method for drawing star bursts.
*/
public static function burst(target:UIComponent, x:Number, y:Number,points:Number, innerRadius:Number, outerRadius:Number,angle:Number=0 ):void
{

if (points >=2)
{

// calculate length of sides
var step:Number = (Math.PI*2)/points;
var halfStep:Number = step/2;
var qtrStep:Number = step/4;

// calculate starting angle in radians
var start:Number = (angle/180)*Math.PI;

target.graphics.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius));

// draw curves
for (var i:int=1; i<=points; i++)
{

target.graphics.curveTo(x+Math.cos(start+(step*i)-(qtrStep*3))*(innerRadius/Math.cos(qtrStep)),
y-Math.sin(start+(step*i)-(qtrStep*3))*(innerRadius/Math.cos(qtrStep)),
x+Math.cos(start+(step*i)-halfStep)*innerRadius,
y-Math.sin(start+(step*i)-halfStep)*innerRadius);

target.graphics.curveTo(x+Math.cos(start+(step*i)-qtrStep)*(innerRadius/Math.cos(qtrStep)),
y-Math.sin(start+(step*i)-qtrStep)*(innerRadius/Math.cos(qtrStep)),
x+Math.cos(start+(step*i))*outerRadius,
y-Math.sin(start+(step*i))*outerRadius);

}

}
}

/**
* Draws a gear shape on the target.  The gear position
* is indicated by the x and y arguments.
*/
public static function gear(target:UIComponent, x:Number, y:Number, points:Number, innerRadius:Number, outerRadius:Number,    angle:Number=0, holeSides:Number=0, holeRadius:Number=0 ):void
{

if (points>=2)
{

// calculate length of sides
var step:Number = (Math.PI*2)/points;
var qtrStep:Number = step/4;

// calculate starting angle in radians
var start:Number = (angle/180)*Math.PI;
target.graphics.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius));

// draw lines
for (var i:int=1; i<=points; i++)
{
target.graphics.lineTo(x+Math.cos(start+(step*i)-(qtrStep*3))*innerRadius,
y-Math.sin(start+(step*i)-(qtrStep*3))*innerRadius);

target.graphics.lineTo(x+Math.cos(start+(step*i)-(qtrStep*2))*innerRadius,
y-Math.sin(start+(step*i)-(qtrStep*2))*innerRadius);

target.graphics.lineTo(x+Math.cos(start+(step*i)-qtrStep)*outerRadius,
y-Math.sin(start+(step*i)-qtrStep)*outerRadius);

target.graphics.lineTo(x+Math.cos(start+(step*i))*outerRadius,
y-Math.sin(start+(step*i))*outerRadius);
}

if (holeSides>=2)
{
if(holeRadius == 0)
{
holeRadius = innerRadius/3;
}

step = (Math.PI*2)/holeSides;
target.graphics.moveTo(x+(Math.cos(start)*holeRadius), y-(Math.sin(start)*holeRadius));

for (var j:int=1; j<=holeSides; j++)
{
target.graphics.lineTo(x+Math.cos(start+(step*j))*holeRadius,
y-Math.sin(start+(step*j))*holeRadius);
}
}

}
}

/**
* A method for creating polygon shapes.
*/
public static function polygon(target:UIComponent, x:Number, y:Number, points:Number, radius:Number, angle:Number=0):void
{

// convert sides to positive value
var count:int = Math.abs(points);

if (count>=2)
{

// calculate span of sides
var step:Number = (Math.PI*2)/points;

// calculate starting angle in radians
var start:Number = (angle/180)*Math.PI;
target.graphics.moveTo(x+(Math.cos(start)*radius), y-(Math.sin(start)*radius));

// draw the polygon
for (var i:int=1; i<=count; i++)
{
target.graphics.lineTo(x+Math.cos(start+(step*i))*radius,
y-Math.sin(start+(step*i))*radius);
}

}
}

/**
* Star draws a star shaped polygon.
*/
public static function star(target:UIComponent, x:Number, y:Number, points:Number, innerRadius:Number, outerRadius:Number,angle:Number=0 ):void
{

var count:int = Math.abs(points);
if (count>=2)
{

// calculate distance between points
var step:Number = (Math.PI*2)/points;
var halfStep:Number = step/2;

// calculate starting angle in radians
var start:Number = (angle/180)*Math.PI;
target.graphics.moveTo(x+(Math.cos(start)*outerRadius), y-(Math.sin(start)*outerRadius));

// draw lines
for (var i:int=1; i<=count; i++)
{
target.graphics.lineTo(x+Math.cos(start+(step*i)-halfStep)*innerRadius,
y-Math.sin(start+(step*i)-halfStep)*innerRadius);

target.graphics.lineTo(x+Math.cos(start+(step*i))*outerRadius,
y-Math.sin(start+(step*i))*outerRadius);
}
}
}

/**
* draws pie shaped wedge.
*/
public static function wedge(target:UIComponent, x:Number, y:Number, startAngle:Number, arc:Number, radius:Number,yRadius:Number):void
{

// move into position
target.graphics.moveTo(x, y);

// limit sweep to reasonable numbers
if (Math.abs(arc)>360)
{
arc = 360;
}

// Draw in a maximum of 45 degree segments. First we calculate how
// many segments are needed for our arc.
var segs:Number = Math.ceil(Math.abs(arc)/45);

// Now calculate the sweep of each segment.
var segAngle:Number = arc/segs;

// The math requires radians rather than degrees. To convert from degrees
// use the formula (degrees/180)*Math.PI to get radians.
var theta:Number =-(segAngle/180)*Math.PI;

// convert angle startAngle to radians
var angle:Number =-(startAngle/180)*Math.PI;

// draw the curve in segments no larger than 45 degrees.
if (segs>0)
{
// draw a line from the center to the start of the curve
target.graphics.lineTo(x+Math.cos(startAngle/180*Math.PI)*radius,
y+Math.sin(-startAngle/180*Math.PI)*yRadius);
//draw curve segments
for (var i:int = 0; i<segs; i++)
{
angle += theta;
var angleMid:Number = angle-(theta/2);
target.graphics.curveTo(x+Math.cos(angleMid)*(radius/Math.cos(theta/2)),
y+Math.sin(angleMid)*(yRadius/Math.cos(theta/2)),
x+Math.cos(angle)*radius, y+Math.sin(angle)*yRadius);
}

//close the wedge by drawing a line to the center
target.graphics.lineTo(x, y);
}
}
}
}

PrimitiveStar.as

package com.Primitives
{
import mx.core.UIComponent;
import com.Primitives.DrawUtils;
import com.Primitives.BasePrimitive;

public class PrimitiveStar extends BasePrimitive
{
public function PrimitiveStar():void
{
super();
}

[Bindable]
[Inspectable]
private var _outerRadius:Number=50;
public function set outerRadius(value:Number):void
{
_outerRadius = value;

invalidateProperties();
invalidateDisplayList();
}
public function get outerRadius():Number
{
return _outerRadius;
}

[Bindable]
[Inspectable]
private var _innerRadius:Number=25;
public function set innerRadius(value:Number):void
{
_innerRadius = value;
invalidateProperties();
invalidateDisplayList();
}
public function get innerRadius():Number
{
return _innerRadius;
}

[Bindable]
[Inspectable]
private var _points:Number=5;
public function set points(value:Number):void
{
_points = value;
invalidateProperties();
invalidateDisplayList();
}
public function get points():Number
{
return _points;
}

[Bindable]
[Inspectable]
private var _angle:Number = 90;
public function set angle(value:Number):void
{
_angle = value;
invalidateProperties();
invalidateDisplayList();
}
public function get angle():Number
{
return _angle;
}

override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void
{

super.updateDisplayList(unscaledWidth,unscaledHeight);

//get the ratio of the difference for the inner and outer radius
var ratio:Number= outerRadius/innerRadius;

//use the smallest of the width and height to do the
//size so we can use as much space as possible
var maxSize:Number = Math.min(unscaledHeight, unscaledWidth);
DrawUtils.star(this,unscaledWidth/2,unscaledHeight/2,points,(maxSize/2)/ratio,(maxSize/2),angle);
}
}
}

PrimitiveStyles.as

//background
[Style(name=”backgroundAlpha”, type=”Number”, inherit=”no”)]
[Style(name=”backgroundColor”, type=”uint”, format=”Color”, inherit=”no”)]
[Style(name=”backgroundSelectedColor”, type=”uint”, format=”Color”, inherit=”no”)]

//border
[Style(name=”borderColor”, type=”uint”, format=”Color”, inherit=”no”)]
[Style(name=”borderThickness”, type=”Number”, format=”Length”, inherit=”no”)]
[Style(name=”borderAlpha”, type=”Number”, inherit=”no”)]
[Style(name=”borderPixelHinting”, type=”Boolean”, inherit=”no”)]
[Style(name=”borderJointStyle”, type=”String”, enumeration=”bevel,miter,round”, inherit=”no”)]
[Style(name=”borderSelectedColor”, type=”uint”, format=”Color”, inherit=”no”)]

//border gradient
[Style(name=”borderFillEnabled”, type=”Boolean”,enumeration=”true,false”, inherit=”no”)]
[Style(name=”borderRatios”, type=”Array”, arrayType=”Number”, inherit=”no”)]
[Style(name=”borderFillType”, type=”string”,enumeration=”linear,radial”, inherit=”no”)]
[Style(name=”borderSpreadMethod”, type=”string”,enumeration=”pad,reflect,repeat”, inherit=”no”)]
[Style(name=”borderFocalPointRatio”, type=”Number”, inherit=”no”)]
[Style(name=”borderAlphas”, type=”Array”,arrayType=”Number”, inherit=”no”)]
[Style(name=”borderColors”, type=”Array”, arrayType=”uint”, format=”Color”, inherit=”no”)]
[Style(name=”borderSelectedColors”, type=”Array”, arrayType=”uint”, format=”Color”, inherit=”no”)]
[Style(name=”borderAngle”, type=”Number”, inherit=”no”)]

//fill gradient
[Style(name=”fillEnabled”, type=”Boolean”,enumeration=”true,false”, inherit=”no”)]
[Style(name=”fillRatios”, type=”Array”, arrayType=”Number”, inherit=”no”)]
[Style(name=”fillType”, type=”string”,enumeration=”linear,radial”, inherit=”no”)]
[Style(name=”fillSpreadMethod”, type=”string”,enumeration=”pad,reflect,repeat”, inherit=”no”)]
[Style(name=”fillFocalPointRatio”, type=”Number”, inherit=”no”)]
[Style(name=”fillAlphas”, type=”Array”, arrayType=”Number”, inherit=”no”)]
[Style(name=”fillColors”, type=”Array”, arrayType=”uint”, format=”Color”, inherit=”no”)]
[Style(name=”fillSelectedColors”, type=”Array”, arrayType=”uint”, format=”Color”, inherit=”no”)]
[Style(name=”fillAngle”, type=”Number”, inherit=”no”)]

These all above files are needed to do Rating things in Flex.
🙂

Leave a comment