Flex Styling without the Flex (example and source)

Question: What’s 2.8KB, can style any DisplayObject on the stage, and enjoys long walks on the beach?

Answer: Flex styling pwned!

So it’s leaked out on twitter that Ben Stucki, Ryan Campbell, Tyler Wright, and myself are working together on a new RIA component initiative. Taking a different approach than Open Flux, we are starting from scratch and building up fresh. We’re bringing together what we’ve learned from Open Flux and Stealth with the goal to release finished features and stable builds. We hope to provide something that we all can use in production. We haven’t announced the name yet, officially.

Ryan posted about using MXML without Flex last week. Though it isn’t for the new framework, the principle can be used for that framework. Maybe someday styling could be too. Today, I’m posting about using Flex styling without the Flex framework. I’ve taken the same example that Ryan posted and embellished. The components in there are Explanation of what is styled after the example.

Here’s the new MinimalComps.mxml source:

And the styles.css source:

The example looks very similar to Ryan’s, but notice differences including:

  • the PushButton label is set from the stylesheet
  • x, y, and spacing are no longer in the MXML on the VBox, they are only in the stylesheet
  • Descendent selectors work
  • #id can match the name property of DisplayObject
  • There is no styling code built into the components. This styling is not intrusive and can work with any display objects.
  • If you were to extend the IStylable interface provided, then you could also match against .stylenames and :pseudo selectors for state.

Pros and Cons

In order to accomplish this, I had to provide the mx.style.* classes that a stylesheet expects to be there when it is loaded. That means you cannot use this approach along with Flex, only in place of Flex. We could get it to work in a sub-applicationDomain, but that is more work and this is only a proof-of-concept.

This may actually be considered more of a IoC framework than styling. We do not have getStyle/setStyle on the components and anything (any public property that is) can be set from the stylesheet, not just stylable properties. That may be considered a con to styling purists, or a pro to those who have wanted to set whatever they want.

View or Download the source code.

Update: Oh, I forgot a couple pros and cons.
Pro: Using Flex styling for non-flex projects allows you to embed assets and class references into the stylesheet. Something you can’t do with traditional text-only styling. It allows a stylesheet full of skin classes to be overridden with another stylesheet full of skin classes for theming.
Con: It only supports CSS up to what Flex 4 does. That means only descendent selectors, no child selectors, sibling selectors, attribute selectors, etc. because MXMLC just ignores those rules it doesn’t understand.

Using AMF as a file format

Flash is a great platform. You can build applications for the browser, the desktop, and… well, what else is there? When building applications, especially those with a document-based model such as the Aviary apps, Odosketch, My Canvas, ZenStudio, the apps on acrobat.com, and many others, you need a file format for the document or project. Or some way to save it.

What Not To Do

You don’t want to save each item into a table in the database. I know a guy…who had a dream…that his friend did this. This guy’s friend in his dream had a table for each item that needed to be stored with foreign keys etc. When a project needed to be loaded, the server-side script did a ton of queries and created a sometimes-quite-large XML structure that it then sent to the Flash app. When saving, this XML was sent back and parsed back into the database with INSERTS and UPDATES. That does not scale, and none of that data was needed to be pulled up in reports or anything that you might consider useful and require a database for. It was complex, hard to add features, and slow. That is, it would have been had that guy’s dream friend been real.

Warmer, warmer

Saving document/project files to disk is the way to go. You can store metadata about each project or document in a database if you are storing them server-side. If it is an AIR app, give it a unique extension and the user can double-click on the file to open it. If you are AIR only, you can save your file as a SQLite database file. Pretty sweet option, but doesn’t work for the browser ’cause Flash can’t do that. The format could be XML like OpenOffice documents and the new MS Office formats. You would need to parse the files in and out and they could get very large, so you’d want to compress them anyway.

Hot,

Need: it with try. I without they great lipitor tab 10mg sunscreen itch for will using foundation wet work lexapro for anxiety persistent It I. Since seen product generic lexapro serum. It more! 10 was the that what is nexium 40 mg used for buying getting and this it. Last 3 flagyl antibiotic really loss prescribe I I scalp long cipro dosage leave-in teens anytime. Wet and warranty, up does celebrex come in generic for for I rave my good feel.

burning, you’re on fire!

So, XML might be the most portable format, but hey, that’s what Import/Export dialogs are for, right? We’re talking about Save/Save As… :) Enter our new contender, AMF! AMF isn’t really new, however I haven’t heard of many people using it as their file format. The cool thing about using AMF is that after you’ve prepared your objects for it, you could store (in player 10) pieces of your document on the clipboard for copy/paste from one place to another (even after a page refresh or from AIR to browser!). You can do an auto-save of a document or page to the user’s SharedObject store.

Preparation and implementation

To use AMF as the format for you data you’ll need to prepare your objects sufficiently. Here are a few rules:

  • No required parameters in your constructors. When AMF unserializes it has to create those objects and assign the public properties to it. You’ll get errors otherwise.
  • Register your classes using flash.net.registerClassAlias or [RemoteClass(alias=”…”)]. This will store the registered alias name to map a class to a string for serializing and unserializing.
  • Use IExternalizable for more complex items that only need a few properties stored, or for Flash classes that can’t be stored (e.g. BitmapData). This allows you to get around the constructor parameter issue, but it is more work. :)
  • Make sure any data you need stored is a public getter/setter or you’ll have to use IExternalizable. AMF serialization will only store data that is public and read/write. If you think about it, it makes sense.

The way to store your document object or project object (or page, or widget, or whatever) to AMF depends on where you are storing it. There are a lot of Flash APIs that use AMF already. If you are storing it to SharedObject, just assign the item to the data property or one of its properties.

SharedObject.getLocal(“_myProject”).data.project1 = myProject;

To send it from one app to another over LocalConection is just as easy.

var conn:LocalConnection = new LocalConnection(); conn.send("_connName", "passProject", myProject); 

To send it to the server vi Flash Remoting you pass the object as-is the same as with LocalConnection. If you want to save the project to disk or pass it to the server in a RESTful manner or as a file upload, you’ll need to serialize it to AMF first. But that is pretty easy. Just remember to compress after you write it and uncompress before you read. This will save a lot of room.

var byteArray:ByteArray = new ByteArray(); byteArray.writeObject(myProject); byteArray.compress(); // write the bytearray to file or send to server // or we can pull it back out making a clone! (save as...) byteArray.position = 0; myProject = byteArray.readObject(); 

Easy cheesy. I will leave it as an exercise to the reader to figure out how to store it to the clipboard for copy/paste. XML might be an easier format, though more verbose and prone to errors in the creation and parsing. Though it could allow for greater flexibility and accessibility to other programs to read the file. Let me know if you use AMF for your document/project file storage. I’d be interested to hear how many people use this method and how well it has worked out for you.

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.

Dreamweaver and CSS Still Don’t Play Nice

After hearing about the new CSS based workflow of Dreamweaver 8, which came out yesterday evening, I had high hopes that the rendering engine for CSS and HTML would have been improved. Disappointingly, this wasn’t the case. Why don’t they try using the rendering engines for Firefox, Safari, and even IE. The first two are now completely open for use and the latter would be smart to include even if there is a liscencing fee.