Here is a small example of one method of creating a component that is both beveled (on one or more edges) and has a gradient applied.
This gradient can be rotated, but currently I only have it going from top to bottom – this can be done in the updateDisplaylist code.
Here is a demo (with source code) of the Gradient Bevel VBox
Please note that this example was built using Flex 3.4
The basic idea is that you create a basic custom MXML component (extending in this case, VBox). You specify a programmatic skin, which is where the bevel and gradient gets applied.
The application code displayed here is very simple:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="1024" minHeight="768" xmlns:local="*" viewSourceURL="srcview/index.html">
<local:GradientVBox
left="20" bottom="20" top="20" right="20"
cornerRadiusTopRight="20" cornerRadiusTopLeft="4" cornerRadiusBottomLeft="3" cornerRadiusBottomRight="3"
gradientFrom="0xFFFFFF"
gradientTo="0x555555"/>
</mx:Application>
Next we have the component, which does little, declaring a few styles and assigning the custom skin Class to the component.
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
borderStyle="solid"
borderSkin="{BevelBorderSkin}">
<mx:Metadata>
[Style(name="cornerRadiusTopLeft",type="Number", inherit="no")]
[Style(name="cornerRadiusTopRight",type="Number", inherit="no")]
[Style(name="cornerRadiusBottomLeft",type="Number", inherit="no")]
[Style(name="cornerRadiusBottomRight",type="Number", inherit="no")]
[Style(name="gradientFrom",type="int", inherit="no")]
[Style(name="gradientTo",type="int", inherit="no")]
</mx:Metadata>
</mx:VBox>
The real work is done in the skin – it determines which corner radius styles have been applied and draws the canvas accordingly. Likewise, the gradient is drawn based on styles.
There is only one area that really was a bit tricky – getting the line to look smooth. This involved manipulating the linestyle as shown below:
g.lineStyle(1,borderColor,1,true,LineScaleMode.NORMAL,CapsStyle.ROUND,JointStyle.ROUND);
The rest of the drawing was just the use of drawRoundRectComplex, making sure that all the correct parameters were supplied.
Skin Code Code:
package
{
import flash.display.*;
import flash.geom.*;
import flash.utils.*;
import mx.core.EdgeMetrics;
import mx.skins.RectangularBorder;
import mx.utils.GraphicsUtil;
public class BevelBorderSkin extends RectangularBorder
{
public function BevelBorderSkin(){
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
var backgroundColor:int = getStyle("backgroundColor");
var backgroundAlpha:Number = getStyle("backgroundAlpha");
var borderColor:Number = getStyle("borderColor");
var g:Graphics = graphics;
var cn:Number = this.getStyle("cornerRadius");
var crtl:Number = this.getStyle("cornerRadiusTopLeft") > 0 ? this.getStyle("cornerRadiusTopLeft") : cn;
var crtr:Number = this.getStyle("cornerRadiusTopRight") > 0 ? this.getStyle("cornerRadiusTopRight") : cn;
var crbl:Number = this.getStyle("cornerRadiusBottomLeft") > 0 ? this.getStyle("cornerRadiusBottomLeft") : cn;
var crbr:Number = this.getStyle("cornerRadiusBottomRight") > 0 ? this.getStyle("cornerRadiusBottomRight") : cn;
var gradFrom:Number = this.getStyle("gradientFrom");
var gradTo:Number = this.getStyle("gradientTo");
var b:EdgeMetrics = borderMetrics;
var w:Number = unscaledWidth - b.left - b.right;
var h:Number = unscaledHeight - b.top - b.bottom;
var m:Matrix = verticalGradientMatrix(0, 0, w, h);
g.clear();
g.beginGradientFill("linear", [gradFrom, gradTo], [1, 1], [0, 255], m);
g.lineStyle(1,borderColor,1,true,LineScaleMode.NORMAL,CapsStyle.ROUND,JointStyle.ROUND);
GraphicsUtil.drawRoundRectComplex(g, b.left, b.top, w, h, crtl, crtr, crbl, crbr);
g.endFill();
}
}
}
Enjoy.