How to create a dotted line or dashed line in Flex 4

October 29, 2010

This is something I need to do every once in a while but can never find a way to create a dotted or dashed line using code. Usually the solution is to either repeat an image, or to use the drawing api to create a dotted line. I took some pointers from both approaches and created the following custom class to draw dotted/dashed lines without the need for images, but still maintaining the ability to customize the colors and sizes of the dashes. Enjoy!

First, create a new class by creating a custom MXML component that extends the Spark Rect class. (I have to leave off the opening xml tag to be able to insert the code here).


<s:Rect width="100%" height="100%" x="0" y="0" 
		xmlns:fx="http://ns.adobe.com/mxml/2009" 
		xmlns:s="library://ns.adobe.com/flex/spark" 
		xmlns:mx="library://ns.adobe.com/flex/mx" >
	
	<fx:Script>
		<![CDATA[
			import flash.display.CapsStyle;
			import flash.display.JointStyle;
			import flash.display.LineScaleMode;
			

			/** Color of the primary dash in the line */
			public function set dotColor( value:uint  ):void
			{
				_dotColor = value;	
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
			
			/** Alpha of the primary dash in the line */
			public function set dotAlpha( value:Number ): void
			{
				_dotAlpha = value;
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
			
			/** With od the primary dash in the line */
			public function set dotWidth( value:Number ):void
			{
				_dotWidth = value;
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
			
			/** Height of the primary dash in the line */
			public function set dotHeight( value:Number ):void
			{
				_dotHeight = value;
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
					
			/** 
			 * Color of the spacer in the line (usually transparent, but can
			 * be another color)
			 */
			public function set spacerColor( value:uint ):void
			{
				_spacerColor = value;
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
			
			/** 
			 * Alpha of the spacer in the line. (usually transparent, but doesn't
			 * have to be)
			 */
			public function set spacerAlpha( value:Number ):void
			{
				_spacerAlpha = value;
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
			
			/** Width of the spacer in the line */
			public function set spacerWidth( value:Number ):void
			{
				_spacerWidth = value;
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
			
			/** Height of the spacer in the line */
			public function set spacerHeight( value:Number ):void
			{
				_spacerHeight = value;
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
			
			/** Padding betweent the dot and spacer */
			public function set padding( value:Number ):void
			{
				_padding = value;
				dispatchEvent( new Event( 'linePropertyChanged' ) );
			}
			
			[Bindable ('linePropertyChanged')]
			public function get lineSegment():Shape
			{
				var bg:Shape = new Shape();
				bg.graphics.beginFill( _dotColor, _dotAlpha );
				bg.graphics.drawRect( _padding, 0, _dotWidth, _dotHeight );
				bg.graphics.endFill();
				
				bg.graphics.beginFill( _spacerColor, _spacerAlpha );
				bg.graphics.drawRect( _dotWidth + (_padding * 2 ), 0, _spacerWidth, _spacerHeight );
				bg.graphics.endFill();
				
				return bg;
			}
			
			private var _dotColor:uint = 0xFFFFFF;
			private var _dotAlpha:Number = 1;
			private var _dotWidth:Number = 3;
			private var _dotHeight:Number = _dotWidth
			private var _spacerAlpha:Number = 0;
			private var _spacerColor:uint  = 0xFFFFFF;
			private var _spacerWidth:Number = _dotWidth;
			private var _spacerHeight:Number = _spacerWidth;
			private var _padding:Number = 0;

		]]>
	</fx:Script>

	<!--- Fill the rect with a repeating LineSegment -->
	<s:fill>
		<s:BitmapFill source="{ lineSegment }" fillMode="repeat" />
	</s:fill>
	
</s:Rect>

To use the class, just place the following wherever you want a dotted/dashed line (assuming a class name of DottedLine.mxml)

<components:DottedLine width="500" height="2" dotColor="0xFFFFFF" dotWidth="3" dotAlpha="1" />

There are other optional parameters that allow for setting the color, alpha and width between the dots, but this is enough to get you started.

Advertisements

Mysterious Background Colors on HTML Buttons with Image Backgrounds in Safari and Chrome

March 12, 2010

?I am working on a project with lots of HTML/CSS. The client provided some background images to skin the form buttons with. Easy enough, right! The graphics were in PNG format and had a transparent background. Nevertheless, Safari and Chrome applied a gray “background” to the buttons.

I double and tripled checked to see what CSS property might be causing this. Here’s how the buttons looked in Safari and Chrome:

Mysterious Gray/Alpha effect on HTML button in Safari/Chrome

Here’s the CSS:

position: relative;
width: 50px;
height: 19px;
border: none;
font-family: Myriad Pro, Trebuchet MS, Arial, Sans-Serif;
font-size: 12px;
padding: opx
background-image: url('../images/buttonBG.png');
background-repeat: none;
 background-color: none;
 background-alpha: 1;

So what was the problem? background-color! Apparently ‘none’ was not a good option. To fix, I changed:

 background-color: none;

to

 background-color: transparent;

Now, the image appears as it should:

Buttons no longer showing mysterious background/alpha effect in Chrome/Safari


Applying Filters to TitleWindow Header

March 12, 2010

I like to blog about simple issues with elusive answers. When I cannot quickly find online information for how to do what I want to do, I’m annoyed.

Recently, I wanted to add a shadow to TitleWindow component’s header label in Flex 3. Styles with CSS didn’t seem to work, so I took another approach. Here’s what I did:

Firstly, I was working with a custom Flex component that already extended TitleWindow. While you can create a “title-style-name” for components that extend panel, setting drop shadow doesn’t appear to work. The solution lies in using the internal namespace. When using the internal namespace, you can directly reference the titleTextField and apply filters. These filters can be set in the updateDisplayList method and be sourced from a public variable.

package .....
{
import mx.containers.TitleWindow;&lt;/code&gt;&lt;/span&gt;

use namespace mx_internal; //this is necessary

public class CustomTitleWindow extends TitleWindow
 {

  public var titleFilters:Array;

  public function CustomTitleWindow()
  {
    super();
  }

  override protected function updateDisplayList( w:Number, h:Number ):void
  {
    super.updateDisplayList( w, h );
      titleTextField.filters = titleFilters;
  }

To Instantiate, just do this:

//somewhere inside your flex code
<mx:dropshadowfilter id="dsf" alpha=".5" color="0x000000">
<custom:customtitlewindow titlefilters="{[ds]}" xmlns:custom="path.to.your.custom.code.folder">

That does it! Now you can pass along any filter you desire to the titleWindow through the titleFilters property.


Applying custom skins and styles to ToggleButtonBar buttons independently

November 24, 2009

I recently had a requirement to apply custom skins and styles to a set of ToggleButtonBar buttons. The thing was, each button had a different icon and style to apply. The Flex framework makes it easy to style the first and last buttons with the firstButtonStyleName and lastButtonStyleName attributes, but these didn’t go quite far enough.

It’s easy to handle this by a function similar to the one below:

<pre><code>private function styleMyToggleButtons():void{    
  var btn1:Object = Object( myToggleButtonBar.getChildAt( 0 ) );    
  var btn2:Object = Object( myToggleButtonBar.getChildAt( 1 ) );    
  var btn3:Object = Object( myToggleButtonBar.getChildAt( 2 ) );    
  var btn4:Object = Object( myToggleButtonBar.getChildAt( 3 ) );    
  var btn5:Object = Object( myToggleButtonBar.getChildAt( 4 ) );

  btn1.styleName = "firstButtonStyleName";          
  btn2.styleName = "secondButtonStyleName";          
  btn3.styleName = "thirdButtonStyleName";          
  btn4.styleName = "fourthButtonStyleName";          
  btn5.styleName = "fifthButtonStyleName";
}


Note: Why cast each button as “Object” rather than “Button”? Because the actual under-the-covers type is “ToggleBarButton” (I think that was the name – you can see for yourself in debugger). When cast as button, the resulting variable is not a handle to the button, but to a copy of it. Because of this, the style changes never appear in the layout because they belong to components in memory that are not present on the screen.

Next, create CSS styles for each button (and name accordingly), then flesh out each one using normal CSS syntax (ie. up/over/down/selected skins, icon, etc).

Then, just figure out where/when to call your method. UpdateDisplayList() or commitProperties() are probably some of the most common places to do this.

I realize that this isn’t rocket science, nor is it hard. Hopefully though, this will give you some ideas for creating a quick solution to a challenge with ToggleButtonBar buttons.


Minimize button disabled on Mac OS windows? A most unusual solution

October 27, 2009

Today I noticed that all my open applications had the minimize button disabled/greyed out. Bizarre! While I still don’t know why it happened, I found a really easy, albeit unusual solution.

Open Quick Time Player, open a movie file, enter full screen, then quit Quick Time. Ba da bing! Problem solved!

Weird, eh?


The Perils of Adjusting Close Buttons in TitleWindows

August 6, 2009

In my current project, I have a custom component that extends TitleWindow. The client has provided skins for just about everything, including the close buttons for several components.

When I applied these skins and styles, I just could not get the close button to appear WHERE I wanted it to appear, nor did it seem to be the right size.

I tried adjusting nearly every style property I could find all with no results.

I next decided to override the createChildren() method, then try to get a handle on the close button there. No luck.

Finally, I discovered an easy way to get a handle on the closeButton:


var closeButton:Button = this.mx_internal::closeButton;
//add new closeButton properties at will
closeButton.x += [new value]
closeButton.height = [new value]
closeButton.width = [new value]

I added this to the updateDisplayList() handler instead of createChildren() since I needed to see and adjust properties that would not have been set yet in createChildren().

From there, I could at least see the darn thing in debugger and decide what properties to manually adjust.

Couple comments….
1. I noticed that despite my defined styles for the component, that the closeButton had it’s own non-inherited style properties for paddingLeft and paddingRight equal to 10. This was one of the culprits keeping my button from appearing where I wanted it to appear, although the main issue was solved by adjusting closeButton.x by a few pixels.

2. Strangely enough – despite manually adjusting the paddingRight and paddingLeft properties of closeButton, only the first one altered would actually change. In my case, I made this the paddingRight since it was the troubling setting. Still, there’s something odd about a setting being so stubborn. Maybe it has something to do with the draw/measure aspects of the component lifecycle.

Hopefully my headache will become your blessing!


Cold Flash Forms Missing – Grrggghh!

March 11, 2009

I have a client who notified me that they could no longer login to their site. I thought that odd since I had not made changes to the code in months, and had not received any announcements of problems from the hosting company (HostMySite.com).

So, I went to check it out and whadya’ know – the login form isn’t even there – nor are any of the forms!

Now, the site is a ColdFusion site and uses Flash Forms (keep your nasty comments to yourself!) and is hosted on a shared server. It’s really not large enough to warrant isolated hosting on its’ own server.

Long story short, when the CF Server reaches a certain threshold of resource utilization, it just stops compiling the flash forms so they don’t show up. Therefore, as the number of sites on the server increases, or perhaps someone elses’ site has some memory hogging code, then the forms dissappear! Can you believe that crap?

ColdFusion cuts off flash form compilation way before resource utilization reaches a problematic threshold. The only solution is to restart the instance. I think this is crap! HostMySite mentioned that it’s not worth it for them to reduce their resource utilization for just that purpose since flash forms are lightly used. I can understand that – but I still think it’s crap. Now I have to either re-code the forms, or tell the client (who’s frustrated by now) to upgrade to more expensive hosting – just so their forms will work again. Yeah right!

So – lesson learned and warning to all people using shared hosting with places like HostMySite.com – don’t use flash forms unless you’re on your own dedicated server. I know that sounds rediculous – that forms would require your own server – but if you want them to work that’s your option!