Restrict MouseEvents to Mask in Flex Skin? - actionscript-3

I have a ButtonSkin (Flex 4 Skin) with a Rect, a Label, and a Group, the Group masking the Rect. On rollOver, I animate the Label's x to this.width, and on rollOut, back to the original position. The problem is, when I rollOut, if I roll to the right (where the label is hiding behind the mask), it doesn't register rollOut, until I go past the label (this.width * 2). How do I prevent that, so when I rollOut of the visible area, even though I'm still over the label behind the mask, I get a "rollOut" event?
Here's the Skin:
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
xmlns:style="http://www.flexinstyle.org/2009"
minWidth="21" minHeight="21"
alpha.disabledStates="0.5">
<!-- states -->
<s:states>
<mx:State name="up" />
<mx:State name="over" stateGroups="overStates" />
<mx:State name="down" stateGroups="downStates" />
<mx:State name="disabled" stateGroups="disabledStates" />
<mx:State name="upAndSelected" stateGroups="selectedStates, selectedUpStates" />
<mx:State name="overAndSelected" stateGroups="overStates, selectedStates" />
<mx:State name="downAndSelected" stateGroups="downStates, selectedStates" />
<mx:State name="disabledAndSelected" stateGroups="selectedUpStates, disabledStates, selectedStates" />
</s:states>
<!-- transitions -->
<s:transitions>
<mx:Transition fromState="*" toState="*">
<s:Animate
target="{labelDisplay}"
duration="300">
<s:SimpleMotionPath property="x"/>
</s:Animate>
</mx:Transition>
</s:transitions>
<!-- fill -->
<s:Rect left="1" right="1" top="1" bottom="1" mask="{masker}" maskType="clip">
<s:fill>
<mx:LinearGradient rotation="90">
<mx:GradientEntry id="backgroundTopGradient"
color="0xff0000"/>
<mx:GradientEntry id="backgroundBottomGradient" color="0xf00000"/>
</mx:LinearGradient>
</s:fill>
</s:Rect>
<!-- label -->
<s:Label id="labelDisplay"
textAlign="center"
verticalAlign="middle"
maxDisplayedLines="1" x.up="10" x.over="100"
horizontalCenter="0" verticalCenter="1"
left="10" right="10" top="2" bottom="2" mouseChildren="false"
color="0xffffff" mouseEnabled="false">
</s:Label>
<!-- mask -->
<s:Group id="masker" width="100%" height="100%" mouseEnabled="false">
<s:Rect width="100%" height="100%">
<s:fill>
<s:SolidColor alpha="0.1"/>
</s:fill>
</s:Rect>
</s:Group>
</s:SparkSkin>

The easiest way to do this is to create a "hit" object that sits on the top of the display in your button skin. You create the "hit" object to the exact dimensions you want the mouse to be interactive with and attach the event listeners to the "hit" object.
In flex flex 4 you can use <s:Group> and not have to worry about transparency or visibility.

Related

Is there a way to use a bitmap fill as the stroke of a rectangle?

Using the Rect primitive you can define a fill using bitmap data like so.
<!-- Draw rectangle that is filled with a repeating bitmap. -->
<s:Rect height="100" width="200">
<s:stroke>
<s:SolidColorStroke color="0x000000" weight="2"/>
</s:stroke>
<s:fill>
<s:BitmapFill
source="#Embed('../assets/AirIcon12x12.gif')"
fillMode="repeat"/>
</s:fill>
</s:Rect>
That looks like this:
Is there a way to set define a bitmap fill for the border stroke (and the center is transparent)?
Answer based on suggestions. Since I was trying to create dashed border there are a few additions:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600"
mouseMove="application1_mouseMoveHandler(event)"
click="application1_clickHandler(event)">
<fx:Script>
<![CDATA[
protected function application1_mouseMoveHandler(event:MouseEvent):void
{
if (resize) {
mainGroupRect.width = event.stageX - mainGroup.x;
mainGroupRect.height= event.stageY - mainGroup.y;
}
}
protected function application1_clickHandler(event:MouseEvent):void
{
resize = !resize;
application1_mouseMoveHandler(event);
}
public var resize:Boolean;
]]>
</fx:Script>
<s:Button id="button" label="hello" width="100%" height="100%" visible="true" />
<s:Group id="mainGroup" verticalCenter="0" horizontalCenter="0" maskType="alpha" mask="{rectMask.displayObject}">
<s:Rect id="mainGroupRect" height="100" width="200" >
<s:fill>
<s:BitmapFill source="#Embed('checker.png')"
fillMode="repeat" />
</s:fill>
</s:Rect>
<s:Rect id="rectMask" top="0" left="0" right="1" bottom="1"
alwaysCreateDisplayObject="true" alpha=".9999999">
<s:stroke>
<s:SolidColorStroke color="0xFF0000" pixelHinting="true"/>
</s:stroke>
</s:Rect>
<s:Rect id="rightEdge" height="100%" width="1" right="1" bottom="1">
<s:fill>
<s:BitmapFill source="#Embed('checker.png')"
fillMode="repeat" />
</s:fill>
</s:Rect>
<s:Rect id="bottomEdge" height="1" width="100%" right="1" bottom="1">
<s:fill>
<s:BitmapFill source="#Embed('checker.png')"
fillMode="repeat" />
</s:fill>
</s:Rect>
</s:Group>
</s:Application>
The fill image is shown below (it appears as a dot. It's a 4x4 image png with transparency on half the image. So additional fills are used on those.
This creates a dashed border. Since there are transparent pixels it does not fill in the image on the right or bottom sides at times. So there are two extra fills that run along the right and bottom edges.
In the example above, click on the stage and you can resize the fill.
You can also wrap the rectMask in a group and then you can just set the mask="{rectMask}"

Adobe Flex collapsible panel in flex 4.6

i am quite new to Adobe Flex and im currently trying to build a collapsible Panel as Sidebar (sidebar extends panel) for my mobile application. My problem is, that the tutorial I followed , was built with Flex 4 and I am using 4.6.
However, I have no errors, only a warning, telling me that "the CSS Typeselector of my SidebarPanel component wasn't processed, because the type is not used in the application."
I tried to run it, but all my Flexbuilder does, is showing a normal blank panel, without a button, change the skinstate. The point where I am stuck, is the grouping of all title bar layers and adding the button. I did both, but still got the blank panel.
I put the "titleBarGroup" from the tutorial arround "contents", "topGroup","tbHilite", "tbDiv" and "titleDisplay" and the "collapseButton" after the "contents"-group.
SidebarPanelSkin.mxml:
<!-- layer 3: contents -->
<!--- Contains the vertical stack of titlebar content and controlbar. -->
<s:Group id="titleBarGroup" left="0" top="0" right="0" bottom="0"
maxHeight="32" rotation.collapsed="90">
<s:Group left="1" right="1" top="1" bottom="1" id="contents">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<!--- #private -->
<s:Group id="topGroup" mask="{topGroupMask}">
<!-- layer 0: title bar fill -->
<!--- #private -->
<s:Rect id="tbFill" left="0" right="0" top="0" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xE2E2E2" />
<s:GradientEntry color="0xD9D9D9" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<!-- layer 1: title bar highlight -->
<!--- #private -->
<s:Rect id="tbHilite" left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xEAEAEA" />
<s:GradientEntry color="0xD9D9D9" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<!-- layer 2: title bar divider -->
<!--- #private -->
<s:Rect id="tbDiv" left="0" right="0" height="1" bottom="0">
<s:fill>
<s:SolidColor color="0xC0C0C0" />
</s:fill>
</s:Rect>
<!-- layer 3: text -->
<!--- #copy spark.components.Panel#titleDisplay -->
<s:Label id="titleDisplay" maxDisplayedLines="1"
left="9" right="3" top="1" bottom="0" minHeight="30"
verticalAlign="middle" textAlign="start" fontWeight="bold">
</s:Label>
</s:Group>
<s:Button id="collapseButton" width="16" height="16" top="7" right="7"
label="-" label.collapsed="+" toolTip="Collapse" toolTip.collapsed="Open" />
</s:Group>
main.mxml:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:cc="customcomp.*"
xmlns:customskins="skins.*" applicationDPI="160" xmlns:skins="skins.*">
<fx:Declarations>
<!-- Platzieren Sie nichtvisuelle Elemente (z. B. Dienste, Wertobjekte) hier -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import skins.SidebarPanelSkin;
]]>
</fx:Script>
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace cc "customcomp.*";
#namespace customskins "skins.*";
customskins|SidebarPanel{
skin-class: ClassReference('skins.SidebarPanelSkin');
}
</fx:Style>
<cc:SidebarPanel id="collapsiblePanel" >
</cc:SidebarPanel>
</s:Application>
Is the error resulting from my not processed typeselector or is there another error in my code? Another question is, whether there are any docs on transitioning from Flex 4 to 4.6. Found some stuff concerning 3 to 4.6, but not much more.
Greets,
oaten_cracker

Flex DataGrid with Button with Skin

Try as I may, I am not able to skin a spark Button, when I place the button within a spark dataGrid. I am constrained to using the halo theme.
I have created the button renderer in a separate mxml file; I have separate buttons outside the dataGrid that show the skin correctly, so I am sure that there is nothing wrong with the skin. The whole point of this is to use the same skin inside the dataGrid as outside
The following code shows the same behavior that I am seeing; in this case the renderer is created in line. It seems like the skinClass is not respected. Or is there another way to do it.
<s:DataGrid id="dg" width="500" dataProvider="{employees2}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="name" headerText="Name">
<s:itemRenderer>
<fx:Component>
<s:GridItemRenderer>
<s:Button label="Press Me"
top="0" bottom="0" left="0" right="0"
skinClass="MyButtonSkin" />
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
In file MyButtonSkin.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:SparkButtonSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
minWidth="21" minHeight="21"
alpha.disabled="0.5">
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.Button")]
]]>
</fx:Metadata>
<fx:Script fb:purpose="styling">
<![CDATA[
/* Define the skin elements that should not be colorized.
For button, the graphics are colorized but the label is not. */
static private const exclusions:Array = ["labelDisplay"];
/**
* #private
*/
override public function get colorizeExclusions():Array {return exclusions;}
/**
* #private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
]]>
</fx:Script>
<!-- states -->
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<!-- layer 2: fill -->
<!--- #private -->
<s:Rect id="fill" left="1" right="1" top="1" bottom="1" radiusX="10">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFAFAFA"
color.over="0xBBBDBD"
color.down="0xAAAAAA"
alpha="0.85" />
<s:GradientEntry color="0x808080"
color.over="0x9FA0A1"
color.down="0x929496"
alpha="0.85" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<!-- layer 8: text -->
<!--- #copy spark.components.supportClasses.ButtonBase#labelDisplay -->
<s:Label id="labelDisplay"
textAlign="center"
maxDisplayedLines="1"
horizontalCenter="0" verticalCenter="1" verticalAlign="middle">
</s:Label>
</s:SparkButtonSkin>
It appears that scaling the button to the size of the grid item does not size the corner radius.
I ended up with a button 200x200 pixels with a corner radius of 6 pixels; it just couldn't be seen. I upped the value to 25 and now I can see it

Create a Panel skin (Spark) with a background fill color I can pass as a parameter

I'm trying to create a Panel skin (Spark) with a background fill color I can pass as a parameter.
(See in bold:)
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin name="CustomPanelSkin"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
blendMode="normal">
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
<s:State name="normalWithControlBar" stateGroups="withControls" />
<s:State name="disabledWithControlBar" stateGroups="withControls" />
</s:states>
<fx:Metadata>
[HostComponent("spark.components.Panel")]
</fx:Metadata>
<s:Group left="0" right="0" top="0" bottom="0">
<s:Rect left="0" right="0" top="0" bottom="0" radiusX="12" radiusY="12">
<s:fill>
<s:SolidColor color="#184c81" />
</s:fill>
</s:Rect>
<s:Group id="contents" left="1" right="1" top="1" bottom="1">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0">
</s:Group>
</s:Group>
</s:Group>
</s:SparkSkin>
From what I read I should create a subclass, but there is not much material on the subject.
I would later on want to use this skin in many Panel controls I have in my application.
Base Panel skin has background color implementation using css styles. You can set it using action script:
panel.setStyle("backgroundColor", 0x184c81);
Also you can control skin components when you have a reference to it in the host component.
Read Implementing the partAdded() and partRemoved() methods for skinnable components for Spark components
This is simple.Create a panel skin and name it something as "panelSkin.mxml".In the .as file use the following statement
newPanelBlock.setStyle("skinClass",com.foldername.panelSkin);
newPanelBlock.setStyle("backgroundColor", 0x184c81);

How to create a Flex image with transparent border and rounded corners?

I have a photo in a Flex project:
<s:Image source="#Embed('images/photo.png')" />
But now I'm wondering if I can make this image as the image below, in Flex (4 / 4.5 / 4.6) (in MXML and/or ActionScript 3):
Is this possible?
Here's a feathering mask tutorial in flash that you should be able to port to Flex.
Yes it is possible, first you need to create a mask layer for the rounder corners and inner shadow using AI or PS
Create a mask in Photoshop or AI. If you're using PS, it must be a vector mask.
Import it to Flash catalyst. If you're using PS, you must chose "Shape Layers > Keep Editable" in the import dialog.
In the layers panel, you'll see a Group with your masked content inside of it. Anything that goes inside that group will be masked.
Add the one image inside the masked group and copy the masked code in code view of Flash catalyst. (FC)
Now create one skin class for the spark image and add the mask code above the imageDisplay (BitmapImage).
MaskedImageSkin.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabled="0.5">
<s:states>
<s:State name="uninitialized" />
<s:State name="loading"/>
<s:State name="ready" />
<s:State name="invalid" />
<s:State name="disabled" />
</s:states>
<fx:Script fb:purpose="styling">
<![CDATA[
/**
* #private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
{
// Push backgroundColor and backgroundAlpha directly.
// Handle undefined backgroundColor by hiding the background object.
if (isNaN(getStyle("backgroundColor")))
{
background.visible = false;
background.includeInLayout = false;
}
else
{
background.visible = true;
background.includeInLayout = true;
bgFill.color = getStyle("backgroundColor");
bgFill.alpha = getStyle("backgroundAlpha");
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
]]>
</fx:Script>
<!-- host component -->
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.Image")]
]]>
</fx:Metadata>
<!--- Defines the appearance of the image background. -->
<s:Rect id="background" left="0" right="0" top="0" bottom="0">
<s:fill>
<!-- #private -->
<s:SolidColor id="bgFill"/>
</s:fill>
</s:Rect>
<s:Group x="0" y="0">
<s:filters>
<s:DropShadowFilter color="#FFFFFF" inner="true" blurX="10" blurY="10" quality="5" alpha="0.85" angle="45" distance="10" />
<s:DropShadowFilter color="#FFFFFF" inner="true" blurX="10" blurY="10" quality="5" alpha="0.85" angle="90" distance="10"/>
<s:DropShadowFilter color="#FFFFFF" inner="true" blurX="10" blurY="10" quality="5" alpha="0.85" angle="-45" distance="10" />
<s:DropShadowFilter color="#FFFFFF" inner="true" blurX="10" blurY="10" quality="5" alpha="0.85" angle="-90" distance="10"/>
</s:filters>
<s:mask>
<s:Group x="0" y="0" width="280" height="180" >
<s:Rect left="0" right="0" top="0" bottom="0" radiusX="10" radiusY="10">
<s:fill>
<s:SolidColor color="#FFFFFF"/>
</s:fill>
</s:Rect>
</s:Group>
</s:mask>
<!--- Primary image display skin part. -->
<s:BitmapImage id="imageDisplay" left="0" top="0" right="0" bottom="0"/>
</s:Group>
<!--- Progress indicator skin part. -->
<s:Range id="progressIndicator" skinClass="spark.skins.spark.ImageLoadingSkin" verticalCenter="0" horizontalCenter="0" includeIn="loading" layoutDirection="ltr" />
<!--- Icon that appears in place of the image when an invalid image is loaded. -->
<s:BitmapImage id="brokenImageIcon" includeIn="invalid" source="#Embed(source='Assets.swf',symbol='__brokenImage')" verticalCenter="0" horizontalCenter="0"/>
</s:Skin>
Apply this skin class for spark image
<s:Image source="#Embed('assets/maskImg.png')" skinClass="MaskedImageSkin" width="200" height="200"/>
The above code is just an example of masking image, create your own mask using rounded rectangle. This will solve your issue.
Happy skinning ...