MiniInspector utility for Flex

Working on a huge project it can be hard to find and work with components and elements. Mini Inspector is a utility that allows you to click on the element at runtime and get information about it. It can also be used to manually fade in and out a bitmap image using the mouse wheel. This is used to compare the design image with the MXML layout or skin at runtime.

Getting information about what you click on
Click on an object while holding down the CTRL or COMMAND key and information about the object under the mouse will be written to the console. This does not include objects that are in skins.

Click on an object while holding down CTRL / COMMAND and the ALT key and information about the object under the mouse will be written to the console. This does include objects that are in skins.

Add the SHIFT key to the above keyboard shortcuts will cause you to enter the debugger and inspect properties and values on the item you clicked.

The information output to the console includes a way to find the object in the file in Eclipse. It does this by creating a regular expression search pattern. You use this pattern to locate the document the target object is defined in. Use this with the Eclipse Search in Files dialog.

Detailed steps to use find in files:
• Click on an object at runtime to get information in the console
• Copy the created pattern from the console
• Open the Search in Files dialog (CTRL + H)
• Paste the pattern into the search text input
• Select the regular expression checkbox
• Select current workspace or project
• Click search.

Note: If the object has an ID it will find it more quickly. If it doesn’t that’s OK; it will narrow it down to a few locations.

Mini Inspector Usage
Add the class to the declarations tag usually in the root application like so,

<utils:MiniInspector />

To use the image fade in fade out:
• Add an image to your component for example,

<s:BitmapImage id="image" source="mockup.png" />

• Set the background image property to the image like so,

<utils:MiniInspector backgroundImage="{image}"/>

• Run the application
• While holding COMMAND / CTRL scroll the mouse wheel up or down. Note: There is a property to adjust the scroll step size.

More information at http://code.google.com/p/flexcapacitor/

Download

Posted in Flash, Flex | Leave a comment

How to add OSX / minimalist scrollbars

If you use a Mac and OSX Lion you’ll notice the scroll bars have changed to a simple line or track similar to what Flash sites have been using. You can get the same look and feel in your Flex Spark projects using this skin class. Demo and source is at the link.

minimal scrollbars

Posted in Flex | Leave a comment

How to declare a component or skin inline

I’ve wanted to know how to do this for a while and I couldn’t get it to work until now. Here’s how how to set the skin class to the skin declared in the declarations.

<?xml version="1.0" encoding="utf-8"?>
<s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
		 xmlns:s="library://ns.adobe.com/flex/spark"
		 xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300"
		 skinClass="{mySkinClass}">

	<fx:Declarations>
		<fx:Component className="mySkinClass">
			<s:Skin >
				<s:states>
					<s:State name="normal" />
					<s:State name="disabled" />
					<s:State name="normalWithControlBar" stateGroups="withControls" />
					<s:State name="disabledWithControlBar" stateGroups="withControls" />
				</s:states>
				<s:Button label="HELLO SKIN"/>
			</s:Skin>
		</fx:Component>
	</fx:Declarations>

</s:SkinnableContainer>

Note: It’s not “inline” as an item renderer is inline but it’s in the same document which is close enough for me. :)

Example II

	<s:ButtonBar id="buttonBarList"
				 top="120"
				 width="100%"
				 height="40"
				 skinClass="{MyButtonBarSkin}"
				 >

	</s:ButtonBar>

	<fx:Declarations>
		<fx:Component className="MyButtonBarSkin">
			<skins:ButtonBarSkin>

			</skins:ButtonBarSkin>
		</fx:Component>
	</fx:Declarations>

NOTE: When declaring a skin class you may have to manually add the namespace to the package path to the document since it is not in the default manifest. You can do that like this:

<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
		xmlns:s="library://ns.adobe.com/flex/spark"
		xmlns:skins="spark.skins.mobile.*"
		>

Notice how we point right to the package path that has our skin class into it. This also works for every other class that is not showing up automatically in code hinting.

Posted in Flex | Leave a comment

Understanding FXG with a vector based button example

This post will show the FXG code generated from Illustrator of creating a button with vector based artwork from start to finish. For this post we’ll be creating a circular button with a transparent gradient on top. You will see code for an Ellipse, Rectangle, Solid Color Fill, Linear Gradient, transparent gradient, rotation of the gradient, scale of the gradient, the start location of the gradient, applying a mask and fixing the code so our graphic element can be scaled to any size and keep our sharp vector graphics and original aspect ratio.

But first let’s look at an FXG code that is exported from a blank artboard in Illustrator.

<?xml version="1.0" encoding="utf-8" ?>
<Graphic version="2.0" viewHeight="792" viewWidth="612" ai:appVersion="15.1.0.39" ATE:version="1.0.0" flm:version="1.0.0" d:using="" xmlns="http://ns.adobe.com/fxg/2008" xmlns:ATE="http://ns.adobe.com/ate/2009" xmlns:ai="http://ns.adobe.com/ai/2009" xmlns:d="http://ns.adobe.com/fxg/2008/dt" xmlns:flm="http://ns.adobe.com/flame/2008">
  <Library/>
  <Group ai:seqID="1" d:layerType="page" d:pageHeight="792" d:pageWidth="612" d:type="layer" d:userLabel="Artboard 1"/>
  <Private/>
</Graphic>

Notice the viewHeight and viewWidth property in the Graphic tag.

Creating the circle or Ellipse (An Ellipse is a filled circular graphic element.).

<?xml version="1.0" encoding="utf-8" ?>
<Graphic version="2.0" viewHeight="792" viewWidth="612" ai:appVersion="15.1.0.39" ATE:version="1.0.0" flm:version="1.0.0" d:using="" xmlns="http://ns.adobe.com/fxg/2008" xmlns:ATE="http://ns.adobe.com/ate/2009" xmlns:ai="http://ns.adobe.com/ai/2009" xmlns:d="http://ns.adobe.com/fxg/2008/dt" xmlns:flm="http://ns.adobe.com/flame/2008">
  <Library/>
  <Group ai:seqID="1" d:layerType="page" d:pageHeight="792" d:pageWidth="612" d:type="layer" d:userLabel="Artboard 1">
    <Group ai:seqID="2" d:type="layer" d:userLabel="Layer 3">
      <Ellipse width="100" height="100" ai:seqID="3">
        <fill>
          <SolidColor color="#FF0000"/>
        </fill>
      </Ellipse>
    </Group>
  </Group>
  <Private/>
</Graphic>

The Ellipse above is 100 x 100. In Illustrator it has been placed at 0×0 position on the artboard. This position is relative to the center of the Ellipse not the upper left hand corner (so from the middle of Ellipse at 0×0 half off it is off the artboard). When you are creating content in Illustrator position it in the upper left corner of the artboard. This location is called the registration point. Note: For this example we are not applying any transformations to the image. It is important to know that transformations work with the registration point.  See http://en.wikipedia.org/wiki/Image_registration

To see what this looks like create a new Flex project and paste the code above into a new file called “circleAI.fxg”. Then add it to the Application like so:

<?xml version="1.0" encoding="utf-8"?>
<s:rApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:local="*">

	<local:circleAI >

</s:Application>

If that’s all you wanted to do then that will work. But if you set any dimensions on it such as 200×200 then you will notice that becomes skewed.

<?xml version="1.0" encoding="utf-8"?>
<s:rApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:local="*">

	<local:circleAI width="200" height="200">

</s:Application>

The reason is that the viewWidth and viewHeight properties are defining the whole size of the artboard in Illustrator not the dimensions of the Ellipsis. We can fix this. Open up the circleAI.fxg file and remove those properties and try it again.

In the design of the button we have a linear gradient that fades into the background. To get a transparent gradient we must first create a mask.

<?xml version="1.0" encoding="utf-8" ?>
<Graphic version="2.0" ai:appVersion="15.1.0.39" ATE:version="1.0.0" flm:version="1.0.0" d:using="" xmlns="http://ns.adobe.com/fxg/2008" xmlns:ATE="http://ns.adobe.com/ate/2009" xmlns:ai="http://ns.adobe.com/ai/2009" xmlns:d="http://ns.adobe.com/fxg/2008/dt" xmlns:flm="http://ns.adobe.com/flame/2008">
  <Library/>
  <Group ai:seqID="1" d:layerType="page" d:pageHeight="792" d:pageWidth="612" d:type="layer" d:userLabel="Artboard 1">
    <Group maskType="luminosity" luminosityClip="true" ai:seqID="2" ai:spare="1">
      <mask>
        <Group>
          <Rect width="100" height="100" ai:seqID="3">
            <fill>
              <SolidColor color="#FF0000"/>
            </fill>
          </Rect>
        </Group>
      </mask>
      <Group ai:seqID="4" d:type="layer" d:userLabel="Layer 3">
        <Ellipse width="100" height="100" ai:seqID="5">
          <fill>
            <SolidColor color="#FF0000"/>
          </fill>
        </Ellipse>
      </Group>
    </Group>
  </Group>
  <Private/>
</Graphic>

This is the first part of creating the gradient. That is creating the mask. In the Group element above we have a property called mask. A mask is a stupid name for what it does. A mask is just a second graphic element that is used to define what areas should be visible in the layer it is part of. In the code above we use a rectangle for this purpose. Because we specified a mask everything in the Group is hidden. The only part of our original content that will be shown is the opaque pixels defined in our mask area. So since we have a fully opaque rectangle sized the same as the Ellipse our Ellipse is fully visible. If the rectangle was sized 50 x 50 then only the upper left quarter of the Ellipse would be visible.

BTW Notice all the additional namespaces in the code above. You can remove these and get a much cleaner looking code. However they don’t affect the result so we will leave them in.

Next we add a gradient to the fill of the rectangle.

<?xml version="1.0" encoding="utf-8" ?>
<Graphic version="2.0" ai:appVersion="15.1.0.39" ATE:version="1.0.0" flm:version="1.0.0" d:using="" xmlns="http://ns.adobe.com/fxg/2008" xmlns:ATE="http://ns.adobe.com/ate/2009" xmlns:ai="http://ns.adobe.com/ai/2009" xmlns:d="http://ns.adobe.com/fxg/2008/dt" xmlns:flm="http://ns.adobe.com/flame/2008">
  <Library/>
  <Group ai:seqID="1" d:layerType="page" d:pageHeight="792" d:pageWidth="612" d:type="layer" d:userLabel="Artboard 1">
    <Group maskType="luminosity" luminosityClip="true" ai:seqID="2" ai:spare="1">
      <mask>
        <Group>
          <Rect width="100" height="100" ai:seqID="3">
            <fill>
              <LinearGradient x="0" y="50" scaleX="100">
                <GradientEntry ratio="0" color="#FFFFFF"/>
                <GradientEntry ratio="0.618104" color="#5A5A5A"/>
                <GradientEntry ratio="1"/>
              </LinearGradient>
            </fill>
          </Rect>
        </Group>
      </mask>
      <Group ai:seqID="4" d:type="layer" d:userLabel="Layer 3">
        <Ellipse width="100" height="100" ai:seqID="5">
          <fill>
            <SolidColor color="#FF0000"/>
          </fill>
        </Ellipse>
      </Group>
    </Group>
  </Group>
  <Private/>
</Graphic>

The code above creates a gradient but it does not provide transparency. We can add transparency by setting the alpha property on the Gradient Entry.

<?xml version="1.0" encoding="utf-8" ?>
<Graphic version="2.0" ai:appVersion="15.1.0.39" ATE:version="1.0.0" flm:version="1.0.0" d:using="" xmlns="http://ns.adobe.com/fxg/2008" xmlns:ATE="http://ns.adobe.com/ate/2009" xmlns:ai="http://ns.adobe.com/ai/2009" xmlns:d="http://ns.adobe.com/fxg/2008/dt" xmlns:flm="http://ns.adobe.com/flame/2008">
  <Library/>
  <Group ai:seqID="1" d:layerType="page" d:pageHeight="792" d:pageWidth="612" d:type="layer" d:userLabel="Artboard 1">
    <Group maskType="luminosity" luminosityClip="true" ai:seqID="2" ai:spare="1">
      <mask>
        <Group>
          <Rect width="100" height="100" ai:seqID="3">
            <fill>
              <LinearGradient x="0" y="50" scaleX="100">
                <GradientEntry ratio="0" color="#FFFFFF"/>
                <GradientEntry ratio="0.618104" color="#5A5A5A" alpha="0.381896"/>
                <GradientEntry ratio="1" alpha="0"/>
              </LinearGradient>
            </fill>
          </Rect>
        </Group>
      </mask>
      <Group ai:seqID="4" d:type="layer" d:userLabel="Layer 3">
        <Ellipse width="100" height="100" ai:seqID="5">
          <fill>
            <SolidColor color="#FF0000"/>
          </fill>
        </Ellipse>
      </Group>
    </Group>
  </Group>
  <Private/>
</Graphic>

Notice the linear gradient X and Y. This is where it starts. Also notice the scaleX. This is how wide it is. If it is set to 100 percent and the width of the rectangle is 100 then the gradient is also 100.

Next you set the rotation on the gradient.

<?xml version="1.0" encoding="utf-8" ?>
<Graphic version="2.0" ai:appVersion="15.1.0.39" ATE:version="1.0.0" flm:version="1.0.0" d:using="" xmlns="http://ns.adobe.com/fxg/2008" xmlns:ATE="http://ns.adobe.com/ate/2009" xmlns:ai="http://ns.adobe.com/ai/2009" xmlns:d="http://ns.adobe.com/fxg/2008/dt" xmlns:flm="http://ns.adobe.com/flame/2008">
  <Library/>
  <Group ai:seqID="1" d:layerType="page" d:pageHeight="792" d:pageWidth="612" d:type="layer" d:userLabel="Artboard 1">
    <Group maskType="luminosity" luminosityClip="true" ai:seqID="2" ai:spare="1">
      <mask>
        <Group>
          <Rect width="100" height="100" ai:seqID="3">
            <fill>
              <LinearGradient x="0" y="100" scaleX="100" rotation="-90">
                <GradientEntry ratio="0" color="#FFFFFF"/>
                <GradientEntry ratio="0.618104" color="#5A5A5A" alpha="0.381896"/>
                <GradientEntry ratio="1" alpha="0"/>
              </LinearGradient>
            </fill>
          </Rect>
        </Group>
      </mask>
      <Group ai:seqID="4" d:type="layer" d:userLabel="Layer 3">
        <Ellipse width="100" height="100" ai:seqID="5">
          <fill>
            <SolidColor color="#FF0000"/>
          </fill>
        </Ellipse>
      </Group>
    </Group>
  </Group>
  <Private/>
</Graphic>

When we do this the X and Y are also rotated as well. To maintain the gradient position we set the Y to 100.

              <LinearGradient x="0" y="100" scaleX="100" rotation="-90">
                <GradientEntry ratio="0" color="#FFFFFF"/>
                <GradientEntry ratio="0.618104" color="#5A5A5A" alpha="0.381896"/>
                <GradientEntry ratio="1" alpha="0"/>
              </LinearGradient>

If we want to use this in Flex as a button then create a new Skin and place the instances  inside. This button will scale and maintain it’s vector graphics irregardless of the width and height of the button.

<?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" xmlns:local="*">

    <fx:Metadata>
        [HostComponent("spark.components.Button")]
    </fx:Metadata>

    <!-- states -->
    <s:states>
        <s:State name="up" />
        <s:State name="over" />
        <s:State name="down" />
        <s:State name="disabled" />
    </s:states>

	<s:Rect width="100%" height="100%" alpha="0">
		<s:fill>
			<s:SolidColor color="0"/>
		</s:fill>
	</s:Rect>

	<local:circleFinal includeIn="up,over,disabled" width="100%" height="100%">
	</local:circleFinal>

	<local:circleFinalDown includeIn="down" width="100%" height="100%" >
	</local:circleFinalDown>

</s:SparkButtonSkin>

 

	<s:HGroup verticalCenter="0" horizontalCenter="0" verticalAlign="middle">

		<s:Button skinClass="MyButtonSkin"
				  width="100" height="100"/>

		<s:Button skinClass="MyButtonSkin"
				  width="150" height="150"/>
	</s:HGroup>

 

 

Posted in AIR, Flash, Flash Catalyst, Flex, FXG | Leave a comment

Creating a recessed line in MXML

I’ve been trying to get a recessed line type of look with MXML and since it took a while I’m posting it here. It can be improved so please post any updates.

	<s:Line width="100%" top="98" left="10" right="10">
		<s:stroke>
			<s:SolidColorStroke color="#555555" weight="1" caps="none"/>
		</s:stroke>
		<s:filters>

			<s:BevelFilter angle="45"
						   type="outer"
						   distance="1"
						   knockout="true"
						   highlightColor="#000000"
						   highlightAlpha=".5"
						   shadowColor="#ffffff"
						   shadowAlpha=".5"
						   blurX="3"
						   blurY="3"
						   />

		</s:filters>
	</s:Line>

I think the look I’m trying to go for is the horizontal rule in Visual Studio type GUI.

Here’s a slightly sharper alternative setting:

<s:BevelFilter angle="45"
						   type="outer"
						   distance="1"
						   knockout="true"
						   highlightColor="#000000"
						   highlightAlpha=".5"
						   shadowColor="#ffffff"
						   shadowAlpha=".5"
						   blurX="0"
						   blurY="0"
						   />
Posted in Flex | Leave a comment