Java, once my mistress, has been ignored while I callously hung out with her rivals PHP, JavaScript and ActionScript. One thing is for sure, Java…she is something special.

So, I decided to rekindle our flame…and wrote a simple web server. It felt so right.

I wrote a very, very, very simple web server that is multi-threaded and supports HTTP 1.1 keep-alive to a certain degree and Chunked transfer encoding. I didn’t see many samples of this online, so here you go:

My httpd project on Github.

I just noticed that AIR apps (mobile too) have access to a built in DNS Resolver class. That means I had to whip up an app that uses it.

Here is the FXP file…

I’ve just started getting serious about Flex skinning, and I’ve learned quite a bit lately. Here I will share what I think is the simplest example possible of skinning a custom component.

First, create the custom component:

package ag.mackenzie.components
{
	import flash.events.Event;

	import spark.components.TextArea;
	import spark.components.supportClasses.SkinnableComponent;

	public class StickyNote extends SkinnableComponent
	{
		[Bindable]
		[SkinPart(required="true")]
		public var textField:TextArea;

		public function StickyNote()
		{
			super();
			setStyle("skinClass", StickyNoteSkin);
		}
	}
}

Next, make the skin:

<?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">
	<!-- host component -->
	<fx:Metadata>
		[HostComponent("ag.mackenzie.components.StickyNote")]
	</fx:Metadata>
	<fx:Declarations>
		<s:DropShadowFilter id="shadow" strength=".3"/>
	</fx:Declarations>
	<!-- SkinParts
	name=textField, type=spark.components.TextArea, required=true
	-->
	<s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0" radiusX="4" radiusY="4" filters="{[shadow]}">
		<s:fill>
			<!--- @private -->
			<s:LinearGradient rotation="70">
				<s:GradientEntry color="#F2FA02" />
				<s:GradientEntry color="#CAD106" ratio=".6"/>
				<s:GradientEntry color="#B4BA04" />
			</s:LinearGradient>
		</s:fill>
	</s:Rect>
	<s:TextArea id="textField" width="100%" height="100%" fontFamily="Arial" fontSize="16" alpha="0"/>
</s:Skin>

Then finally, reference it in your application like so:

(note… I have it in a mobile view, you can use it in your normal Flex app as well.

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
		xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView" xmlns:skinning="ag.mackenzie.x.skinning.*" xmlns:components="ag.mackenzie.components.*">
	<s:layout>
		<s:VerticalLayout/>
	</s:layout>
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<components:StickyNote left="10" top="10" width="300" height="250" id="sn"/>
</s:View>

I was looking to add a gift certificate generator for a Flex Mobile application I developed, which takes a blank PNG that has the gift certificate look and feel I was looking for and write text onto it to personalize it. The certificate is then saved to the iOS (or Android) Camera Roll.

This isn’t the prettiest yet, but it took me a lot of googling to figure out what would work. Take this as a hopefully valuable example.


<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
		xmlns:s="library://ns.adobe.com/flex/spark" title="GiftCertificateView" viewActivate="viewActivated(event)" actionBarVisible="false">
	<fx:Script>
		<![CDATA[
			import mx.formatters.DateFormatter;
			import mx.utils.UIDUtil;

			import spark.components.Button;
			import spark.components.Image;
			import spark.components.Label;
			import spark.events.ViewNavigatorEvent;
			import spark.primitives.BitmapImage;

			[Embed(source='../resources/images/gc_blank.png')]
			public var GCBlank:Class;

			protected function viewActivated(event:ViewNavigatorEvent):void
			{
				stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
				var bitmapData:BitmapData = new BitmapData(480, 320, true, 0xFF82DC);
				bitmapData.draw(new GCBlank());
				var df:DateFormatter = new DateFormatter();
				df.formatString="DD-MM-YYYY";
				var dateIssued:Date = new Date();
				var dateExpired:Date = new Date(dateIssued.fullYear +1, dateIssued.month, dateIssued.date);

				var uuid:String = UIDUtil.createUID();

				drawString(bitmapData, "For: " + data.recipient, 50, 75);
				drawString(bitmapData, "From: " + data.from, 50, 100);
				drawString(bitmapData, "Amount: $" + data.amount, 50, 125);
				drawString(bitmapData, "Issued:" + df.format(dateIssued), 50, 150);
				drawString(bitmapData, "Expires:" + df.format(dateExpired), 50, 175);
				var format:TextFormat = new TextFormat();
				format.color = 0x000000;
				format.size = 12;
				format.font = "Sans-Serif";

				drawString(bitmapData, uuid, 75, 220, format);

				format.size = 10;
				drawString(bitmapData, "Book anytime at www.foo.com.", 130, 270, format);

				var img:Image = new Image();
				img.source = bitmapData;
				container.addElement(img);
				var cr:CameraRoll = new CameraRoll();
				cr.addBitmapData(bitmapData);
				var button:Button = new Button();
				button.x = 400;
				button.y = 250;
				button.label = "Ok";
				button.addEventListener(MouseEvent.CLICK, function():void {
					stage.setAspectRatio(StageAspectRatio.PORTRAIT);
					navigator.popToFirstView();
				});
				container.addElement(button);
				var label:Label = new Label();
				label.x=400;
				label.y=235;
				label.text = "Saved!";
				container.addElement(label);
			}

			protected function drawString(target:BitmapData,text:String,x:Number,y:Number,formatOveride:TextFormat=null):void {
				var tf:TextField = new TextField();
				tf.antiAliasType = AntiAliasType.ADVANCED;
				var format:TextFormat = new TextFormat();
				format.size = 20;
				format.font = "Sans-Serif";
				format.color = 0xFFFFFF;
				if (formatOveride != null) format = formatOveride;
				tf.defaultTextFormat = format;

				tf.background = false;
				tf.text = text;
				tf.width = 350;
				var bmd:BitmapData = new BitmapData(tf.width,tf.height, true, 0xFF82DC);

				bmd.draw(tf);
				var mat:Matrix = new Matrix();
				mat.translate(x,y);
				target.draw(bmd,mat);
				bmd.dispose();
			}

		]]>
	</fx:Script>
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<s:Group width="100%" height="100%" id="container"/>
	</s:View>

Here is a code snippet that you can use to have a Spark list filter itself as you type.

First, the filter method, which is triggered from your search box’s change event:

protected function filterList(event:TextOperationEvent):void
{
	var txtLength:Number = searchBox.text.length;
	var txtEntered:String = searchBox.text;
	var filteredListArray:Array = new Array();
	if(searchBox.text == "")
	{
		clientsList.dataProvider = DataModel.clients;
		return;
	}
	else
	{
		for(var i : int = 0 ; i < DataModel.clients.length; i++)
		{
			var client:Object = DataModel.clients.getItemAt(i);
			if(client.label.toString().substring(0, txtLength).toLowerCase() == txtEntered.toLowerCase())
			{
				filteredListArray.push(client);
			}
			clientsList.dataProvider = new ArrayCollection(filteredListArray);
		}
	}
}
  • DataModel.clients is an ArrayCollection of Objects, all with a property (string) called label.
  • searchBox is a TextInput control.
  • clientsList is a List control
© 2011 Matt MacKenzie Suffusion theme by Sayontan Sinha