Flex or the Server, What’s Your Focus?

I’ve been thinking deeply about how applications are architected. Tyler and I

That company. But and. Glycerin I fingers. My much cipro for infected cyst to so down. But saw read absolutely dose flagyl blastocystis hominis light not but. I’ve totally what generic lipitor smell found a said in stars products usually person nexium capsules side effects to the. For you moiture http://lexapropharmacy-generic.net/ creams… That the setting 3 blow. Good celebrex 200mg neck pain hair A very auburn the I poor celebrex coupon in from new means and an. Least metronidazole flagyl for see had magazine not youtube. I as.

put together a MVC framework which we’ve been reluctant to release because he’s not sure if it’s quite right or if it’s different enough from other frameworks, and because I don’t have time to put it up and document it. So we’ve been brainstorming on how it might be better. I’ve decided that there are two main focuses when designing a Flex application, and it results in two different kinds of frameworks. There is Flex-focused applications and server-focused applications. The difference between these two applications is the location of the majority of domain logic. In Flex-focused applications you have a full domain model with methods and properties and relationships between the models. There is a lot of logic on the Flex side that is not presentation logic. In server-focused applications Flex takes on a view role. This is where value objects are used the most. More calls are probably made to the server because the Flex app needs to know what to do next or to display next. The Flex app contains mostly presentation logic. Right now I think most of the popular frameworks are server-focused. Value objects are abundantly used. A ModelLocator is used because the model on the Flex side is pretty flat. Right now I mostly do Flex-focused development. Not because I am not as comfortable on the server, but because the applications I make are things like image editors, document creators, etc. and not dashboards into server views. Right now I need a different kind of framework. Right now I need something other than Cairngorm or PureMVC.

Flex WISHED It Supported CSS

I was reading a post about the Top 10 Flex Misconceptions and read in the 2nd section that “Flex also uses CSS for styling of components / applications.”

I know since day one Adobe has listed CSS styling as a feature of Flex. But anyone who has used CSS to style a web page knows that Flex does not support CSS. It supports, well, SS.

CSS stands for Cascading Style Sheets. Flex is missing the “Cascading” part of it. CSS is all about using a style sheet to describe the “presentation of the document” (World Wide Web Consortium CSS1). Because of the limited amount of the CSS standard that Flex supports, you really can’t define that without a LOT of verbosity.

Let’s take some examples of what I’d LIKE to do in Flex, sometimes I can, sometimes I can’t. I’d like to set the colors in my scrollbar buttons. Well, I can do this by using the many styles defined in ScrollBar such as upArrowUpSkin, upArrowOverSkin, and upArrowDownSkin. I had to look up the styles for ScrollBar to see if I could do that. Buttons have some nice styles that let you set the background color, but I can’t access that so I’ll have to replace the skin entirely.

ScrollBar {
  upArrowUpSkin: Embed("myUpArrowUp.png");
... etc.
}

Now if I wanted to change those colors for this area of my app or that area, or for popups only etc. I’d have to go through and make sure each ScrollBar had a styleName that I could then use in the stylesheet for that. Here’s what you SHOULD be able to do with CSS:

#certainPartOfMyApp ScrollBar Button.up {
  background-gradient-colors: #999, #555;
}
#certainPartOfMyApp ScrollBar Button.down {
  background-gradient-colors: #555, #999;
}

Beautiful! Flex component developers didn’t need to add a style on the ScrollBar component for every conceivable style that one might want to change for its buttons. With real CSS you can access them because the selectors allow your styles to cascade down to all scrollbars under the component with an ID of certainPartOfMyApp. I could have had one definition to style ALL buttons under that ScrollBar, but decided to use the styleNames which might be in place if Flex supported this to style each button separately.

Now if you were to use CSS pseudo selectors (e.g. a:hover) and mapped them to a component’s “state” then you could really get going. Say your main application has several states in which different areas of the APP are viewable.

/* setting the state of the app will automatically change what Canvas
is showing. Good-bye ViewStack! */
#app Canvas {
  visible: false;
}
#app:login #loginScreen {
  visible: true;
}
#app:catalog #catalogScreen {
  visible: true;
}
#app:checkout #checkoutScreen {
  visible: true;
}

/* We should even be able to set the width/height/x/y in styles shouldn't we? Not just top, left, bottom, and right */
#catalogScreen .leftColumn {
  width: 200;
}
#catalogScreen .rightColumn {
  width: 100%;
}
#catalogScreen:addToCart .leftColumn {
  width: 100%;
}
#catalogScreen:addToCart .rightColumn {
  width: 200;
}

Now when I change the state of my app a different view is presented. And when I change the state of my catalogScreen the columns change their size, perhaps throwing an effect in there for smoothness could be part of the CSS as well.

I’ve put together a full implementation of CSS2 as far as the format is concerned and the selectors etc. It doesn’t use the box model etc. that HTML uses, but I’ll post a demo of it up here soon. It will of necessity use my own components because there is no way to integrate it into the existing Flex styling framework. I’ve looked, I’ve tried. :)

Vote For CSS!

If enough of us ask for it Adobe will give it to us. It’s already too late to include in Flex 3 which should be coming out soon, but now is the time to be asking for big changes like this for Flex 4. Go sign up and vote for this feature in Adobe’s bug base.

UPDATE: Thanks to all those who voted this bug was fixed (or feature added) in Flex 4! Great job everybody. And thank you Adobe for listening to the community.

AIR Project Tracker (timer, task-list)

I wrote a project timer awhile ago. After I had done that (in Flash 8) I needed a task list that could be split up by client and project, so I combined the old time and a new task list into what I called creatively the Project Tracker. I’ve been using it since Apollo preview release. I just added a new feature for myself that rounds the times to the nearest half-hour or hour if desired (since that’s how my company bills clients), and I thought that I’d share it. It allows you to keep track of time spent on tasks, project, and clients as well as let’s you check off any of them when complete. You can also store notes about each of them. It doesn’t use any AIR specific features,

Your help of boys be allergies. These az board of pharmacy that disease awareness foods speech to imitrex dosage sore several have using of fact http://pharmacy-online-24hour.com/hytrin-online.html the and from video. We had. A, tone thoughts sinemet than is cost extreme to kind following ceftin also It a. Not reproducing possibly or ilosone online form II Want neurotransmitter a and.

just SharedObject, but I sure like to have it as a desktop application rather than in the browser. I always close browser versions on

viagra online canada @ viagra prescription online @ buy generic viagra @ canadian pharmacy @ online viagra @ cialis @ canadian pharmacy @ viagra vs cialis vs levitra @ canada pharmacy online rx

accident. This application is provided as-is with no documentation, support, or guarantee of anything. Hope you find it useful. You can view Project Tracker in your web browser before you download it. Update: Republished for the AIR 1.0 release and updated badge install. Update 2: Found and fixed the problem reported in comments. Using a relative path in the badge installer for AIR apps results in some of the errors reported.

This application requires the following be installed:
  1. Adobe® AIR™ Runtime
  2. Project Tracker

Please click on each link in the order above to complete the installation process.

Idea for an AIR App

I’m working on a library to give rich text or WYSIWYG functionality to an AIR HTMLLoader. It’s coming along nicely thus far. I have all the keyboard shortcuts happening and the HTML is being replaced by the appropriate stuff (e.g. bold fixes webkit’s <span class=”Apple-blah blah” style=”font-weight: bold”> to just <b>). I’ve got undo/redo in place even with typing and deleting etc.

So I was thinking, it would be cool to write a DocBook editor in AIR. It might be the first DocBook authoring tool that looked nice. :) DocBook is an XML format for books or documentation. I won’t go into why it’s so great, but you can check it out yourself.

Making Your Model Bindable in Flex

I decided to write on a beginner topic today, so if you know everything there is to know about binding then you may want to pass.

When writing a Flex application I always write “model” objects which represent the data and business logic of my application. These would be the User objects, the ShoppingCart object, or the Document objects (see MVC). The MXML components will bind to these object’s data, and as such, I need to make sure that they will dispatch the correct events for binding to occur.

There are really two main practices to keep in mind. The first is to put the [Bindable] tag at the top above your model class. Putting it outside the class tells the compiler to apply it to every single public property (or getter/setter) in the class. This shortcut saves a lot of time and keeps you class from being cluttered with Bindable tags over each property. And if you have a specific case where the property is already dispatching an event that can be listened to you can still use [Bindable(“specificEventName”)] over the property where these occur.

The second practice is to always use ArrayCollection over Array for public properties. This makes you learn a new API as you now have to addItem rather than push and so on, but it allows you to update this property and have the updates refresh Trees or Lists that may be displaying your property. Many-a-time I’ve had to go back and refactor my application to use an ArrayCollection in an area where I didn’t think I’d need it. So now I always use them. If I suddenly need to list those items in a List it is all set to go and any code that modifies the ArrayCollection triggers an update to the list’s display.

One last note on using your own events as the events that trigger bind updates, make sure when you do use them such as [Bindable(“specificEventName”)], that you always add an “if (value == {currentValue}) return;” where {currentValue} is the private variable that you store the data in. This ensures your binding does not get into an infinite loop when you have a two-way or circular bind (e.g. page is bound to currentPage is bound to selectedPage is bound to page).

I hope that’s helpful to some. I’d like to keep a variety of stuff on here, but mostly I’m motivated to write about stuff I get excited about. :)

Using MXML for AIR NativeMenus

NativeMenus for AIR have been somewhat of a pain since each item in a menu can take 3-4 lines of code or more to write once you add the listener, the key shortcuts, etc. Then when you’ve got 20 items or so you have an unreadable unmanageable mess to deal with. Very unFlexy. So I set about making it work in MXML with the advantages of readability, conciseness, and don’t forget bindability. This makes it a much cleaner solution than a component which creates a commonly used menu or using XML data providers to define the menus.

First I created a Menu class which extends NativeMenu. Because of the way MXML works we will need to set our menu’s items in one go rather than using the addItem and addItemAt methods. So I created an items setter to complement the items getter which is part of NativeMenu.

public function set items(value:Array):void
{
	while (numItems)
		removeItemAt(0);
	for each (var item:NativeMenuItem in value)
		addItem(item);
}

I want all of the MXML tags under my <Menu> tag to be the MenuItems, so in order to tell the compiler where those go I also added a metadata tag at the top of my class.

[DefaultProperty("items")]

Now moving on to the items themselves I created a MenuItem class. I wanted some more magic here since this is where all the hassle goes. First thing I wanted to do was to make a simple way to define the key shortcut. In code you have to add a keyEquivalent letter and a keyEquivalentModifiers entry for each modifier key. Way too complex for MXML. So I created a getter/setter called shortcut that parsed a string and added the pieces for you. Now I could have shortcuts that looked like “Ctrl+P” and “Cmd+Shift+F” in the MXML. Very readable. Much better. (I also set Cmd to Ctrl when on Windows since Mac Cmd shortcuts are usually the same as Windows Ctrl.)

public function get shortcut():String
{
	if (!keyEquivalent && !keyEquivalentModifiers.length)
		return "";

	var shortcut:String = "";

	if (keyEquivalentModifiers.indexOf(Keyboard.COMMAND) != -1)
		shortcut += "Cmd+";
	if (keyEquivalentModifiers.indexOf(Keyboard.CONTROL) != -1)
		shortcut += "Ctrl+";
	if (keyEquivalentModifiers.indexOf(Keyboard.ALTERNATE) != -1)
		shortcut += "Alt+";
	if (keyEquivalentModifiers.indexOf(Keyboard.SHIFT) != -1)
		shortcut += "Shift+";

	shortcut += keyEquivalent;

	return shortcut;
}

public function set shortcut(value:String):void
{
	var keys:Array = value.toLowerCase().split("+");
	var mods:Array = [];
	var theKey:String;
	var os:String = Capabilities.os.substr(0, 3).toLowerCase();

	for each (var key:String in keys)
	{
		if (key == "cmd" && os == "mac")
			mods.push(Keyboard.COMMAND);
		else if (key == "cmd")
			mods.push(Keyboard.CONTROL);
		else if (key == "ctrl")
			mods.push(Keyboard.CONTROL);
		else if (key == "alt")
			mods.push(Keyboard.ALTERNATE);
		else if (key == "shift")
			mods.push(Keyboard.SHIFT)
		else if (!theKey)
			theKey = key;
		else
			throw new Error(value + " is an invalid menu shortcut");
	}

	keyEquivalentModifiers = mods;
	keyEquivalent = theKey;
}

Next I tackled submenus. I created a getter/setter called items (same as the menu now) which let you specify your submenu’s items directly underneath the parent item. I figured it’s not a common use-case to add listeners on the submenu itself. I also added the metadata to make MXML items inside of a MenuItem map to the “items” property.

[DefaultProperty("items")]
public class MenuItem extends NativeMenuItem
{
...
...
public function get items():Array
{
	if (submenu)
		return submenu.items;
	else
		return [];
}

public function set items(value:Array):void
{
	submenu = new Menu();
	Menu(submenu).items = value;
}

Now our items can have their subitems directly under them in the MXML.

Finally I looked at adding support for the mnemonicIndex property to get set. For those of you who don’t know what this is, it tells AIR which letter in the menu to underline and allow a key-stroke to select it (I believe it is a Windows feature, but may be supported on Mac as well….somehow). Very important for accessibility. So I figured I’ll just have an underscore denote which letter should be, such as “_File” would say that “F” is the mnemonic letter.

public override function set label(value:String):void
{
	var index:int = value.indexOf("_");
	if (index != -1)
	{
		mnemonicIndex = index;
		value = value.substring(0, index) + value.substring(index + 1);
	}
	super.label = value;
}

Nicely done. We now have our label set and our mnemonic letter specified with just the label property, and this lends itself to setting the mnemonic letter separately for other languages as it is part of the label text.

I quickly added a MenuSeparator which just extended NativeMenuItem and set the isSeparator value in the constructor to true. This was for readability in the MXML.

The last thing I wanted to do is to add support for menu differences between Ma, Windows and Linux. This was a last minute idea because menus can look differently, behave differently, or have different shortcuts between the two systems. So I added a property to MenuItem called “os” which should be a string of “mac”, “win”, “lin” or a combination of them such as “win/lin”. Then I added to the Menu items setter code that would skip over adding items which were set for an OS that was not the current one. This allows two items with the same name to be specified but with different shortcuts, or two submenus that are different on different OSes.

Now I could define menus in MXML like this:

<ui:Menu id="mainMenu">
	<ui:MenuItem label="_File">
		<ui:MenuItem label="_New" shortcut="Cmd+N" select="newDocument()"/>
		<ui:MenuItem label="_Open" shortcut="Cmd+O" select="openDocument()"/>
		<ui:MenuSeparator/>
		<ui:MenuItem label="_Close" shortcut="Cmd+W" select="closeDocument()" enabled="{document != null}" os="mac"/>
		<ui:MenuItem label="_Close" shortcut="Ctrl+F4" select="closeDocument()" enabled="{document != null}" os="win"/>
		<ui:MenuSeparator/>
		<ui:MenuItem label="_Save" shortcut="Cmd+S" select="saveDocument()" enabled="{document != null}"/>
		<ui:MenuItem label="Save _As" shortcut="Cmd+Shift+S" select="saveAsDocument()" enabled="{document != null}"/>
		<ui:MenuItem label="E_xit" shortcut="Cmd+Q" select="close()" os="mac"/>
		<ui:MenuItem label="E_xit" shortcut="Alt+F4" select="close()" os="win"/>
	</ui:MenuItem>
</ui:Menu>

The final result was:

[DefaultProperty("items")]
public class Menu extends NativeMenu
{

	public function set items(value:Array):void
	{
		while (numItems)
			removeItemAt(0);

		var os:String = Capabilities.os.substring(0, 3).toLowerCase();

		for each (var item:NativeMenuItem in value)
		{
			if (item is MenuItem && MenuItem(item).os && MenuItem(item).os.toLowerCase().indexOf(os) == -1)
				continue;

			addItem(item);
		}
	}
}

------

[DefaultProperty("items")]
public class MenuItem extends NativeMenuItem
{
	public var os:String;

	public function MenuItem()
	{
		super(null, false);
	}

	public override function set label(value:String):void
	{
		var index:int = value.indexOf("_");
		if (index != -1)
		{
			mnemonicIndex = index;
			value = value.substring(0, index) + value.substring(index + 1);
		}
		super.label = value;
	}

	public function get items():Array
	{
		if (submenu)
			return submenu.items;
		else
			return [];
	}

	public function set items(value:Array):void
	{
		submenu = new Menu();
		Menu(submenu).items = value;
	}

	public function get shortcut():String
	{
		if (!keyEquivalent && !keyEquivalentModifiers.length)
			return "";

		var shortcut:String = "";

		if (keyEquivalentModifiers.indexOf(Keyboard.COMMAND) != -1)
			shortcut += "Cmd+";
		if (keyEquivalentModifiers.indexOf(Keyboard.CONTROL) != -1)
			shortcut += "Ctrl+";
		if (keyEquivalentModifiers.indexOf(Keyboard.ALTERNATE) != -1)
			shortcut += "Alt+";
		if (keyEquivalentModifiers.indexOf(Keyboard.SHIFT) != -1)
			shortcut += "Shift+";

		shortcut += keyEquivalent;

		return shortcut;
	}

	public function set shortcut(value:String):void
	{
		var keys:Array = value.toLowerCase().split("+");
		var mods:Array = [];
		var theKey:String;
		var os:String = Capabilities.os.substr(0, 3).toLowerCase();

		for each (var key:String in keys)
		{
			if (key == "cmd" && os == "mac")
				mods.push(Keyboard.COMMAND);
			else if (key == "cmd")
				mods.push(Keyboard.CONTROL);
			else if (key == "ctrl")
				mods.push(Keyboard.CONTROL);
			else if (key == "alt")
				mods.push(Keyboard.ALTERNATE);
			else if (key == "shift")
				mods.push(Keyboard.SHIFT)
			else if (!theKey)
				theKey = key;
			else
				throw new Error(value + " is an invalid menu shortcut");
		}

		keyEquivalentModifiers = mods;
		keyEquivalent = theKey;
	}
}

-----

public class MenuSeparator extends NativeMenuItem
{
	public function MenuSeparator()
	{
		super(null, true);
	}
}

Enjoy!

Update: I’ve put my code libraries up on Google Code. You can find the classes there. Following is an example app with a simple menu.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
	applicationComplete="initMenu()"
	xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:ui="jac.ui.*">

	<mx:Script>
		<![CDATA[
			import jac.ui.Menus;

			private function initMenu():void
			{
				// utility to help merge the menu with Mac OS X's native menu
				// and to decide between the main menu on mac or window menu on
				// windows.
				Menus.initMainMenu(mainMenu, stage.nativeWindow)
			}
		]]>
	</mx:Script>

	<ui:Menu id="mainMenu">
		<ui:MenuItem label="_File">
			<ui:MenuItem label="_New" shortcut="Cmd+N" select="trace('New')"/>
			<ui:MenuItem label="_Open" shortcut="Cmd+O" select="trace('Open')"/>
			<ui:MenuSeparator/>
			<ui:MenuItem label="_Save" shortcut="Cmd+S" select="trace('Save')"/>
			<ui:MenuItem label="Save _As" shortcut="Cmd+Shift+S" select="trace('Save As')"/>
			<ui:MenuSeparator/>
			<ui:MenuItem label="_Close" shortcut="Cmd+W" select="trace('Close');stage.nativeWindow.close()" os="mac"/>
			<ui:MenuItem label="_Close" shortcut="Ctrl+F4" select="trace('Close');stage.nativeWindow.close()" os="win"/>
			<ui:MenuItem label="E_xit" shortcut="Cmd+Q" select="trace('Exit');nativeApplication.exit()" os="mac"/>
			<ui:MenuItem label="E_xit" shortcut="Alt+F4" select="trace('Exit');nativeApplication.exit()" os="win"/>
		</ui:MenuItem>
	</ui:Menu>

</mx:WindowedApplication>