Wednesday, January 31, 2007

Flex Data Model Architecture

So, I'm chin-deep in Joe Berkovitz's Architectural Blueprint for Flex Applications... That is to say, this is about the 5th time I've read it. I think it's a great article, as architectural blueprints go... It really helps to make the abstract principles of MVCS more concrete for me.

I think I'm a little slow on the uptake when it comes to architecture. Old habits die hard, and years of working on small, underfunded projects have molded my thought patterns accordingly - I always seek the most direct approach that works. Even though this is not my first exposure to MVCS by a long shot, I still find myself getting a bit lost in the translation between the idea of MVCS and the details of how you implement it in a real world project.

The code examples that are shown in Joe's article are only moderately helpful to me - it wasn't until I opened the source code itself and could see the import statements that some of it became clear.

For example, the Model portion of the app. After reading the article several times (and also referencing Aral Balkan's article "Defining Data Models"), I was still unsure of the appropriate place to instantiate the model classes, and I also thought that there should be a single Model class that encapsulated the other model classes. I was visualizing the model as a single respository for all the data needed by the application, which would have bindable properties (sort of like a model defined by mxml Model tags). After reviewing the source code, I see that the model is really implemented as a set of Value objects that are instantiated in both the Controller and the Services, and are passed around the application.

I'm not used to thinking in this way. When someone says "this architecture is made up of 4 parts" I am thinking of 4 discreet parts. When someone refers to "the Model" I naively think "there's a single model object somewhere". So I'm trying to adjust my brain to the concept of a nebulous model that consists of several Value Objects being tossed around the app.

But I'm also (maybe naively) wondering if it wouldn't be better to have a single Model that encapsulates all the data. That would have a couple main benefits, in my estimation:

1) It would be easier to serialize the model and save it in a local shared object for later restoration (the purpose of the model is to handle state, correct?)
2) It would be easier to store revisions of the model for undo/redo purposes
3) It would be easier for the view to bind to it

This is what the mx:Model tag has going for it, but the problem there is you can't have strongly typed data.

I'm pretty sure there are architectures that work this way - it sounds kind of like what Aral describes in the "Using Class-Based Models" section of his article. But maybe I'm reading Joe Berkovitz's code wrong... Pretty sure I'm missing quite a lot here - hopefully I haven't said anything that is obscenely stupid.

Hopefully some of my readers can help me fill in the blanks!

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Monday, January 22, 2007

Update - Flex Text Highlighter Class

Last night I updated my demo of tl.text.Highlighter, my TextField highlighting class for Flex. You point it at a TextField object, and then use one of its methods to highlight the word or words of your choosing. Here's the demo (right-click it to view source).

In this revision, I added some performance optimizations to reduce the number of calls to TextField.getCharBoundaries, which it turns out was the most expensive call I was making. In the last version, I highlighted each character individually, regardless of whether it was part of a word or not, because it was easier to handle word wrapping that way. This meant making a separate call to TextField.getCharBoundaries for each letter in a word. The performance was pretty good, but could get a little slow when highlighting a whole paragraph. Now, I make two calls per word: one for the first character, and one for the last character and combine them into a single Rectangle object that spans the whole word (a la Keith Peters). It's a bit trickier to manage when words or phrases wrap into multiple lines, but I was able to write some logic to handle those scenarios.

Anyway, this results in much better performance when highlighting many sequential characters in a TextField. To pull this off, I created a StringBoundaries class which returns an array of Rectangles that define the boundaries of the character range. The array has a length of 1 if the character range fits on one line.

Also, I moved the search logic into a separate class called Finder, where it will be easier to work with. I intend to add some features such as Match Whole Words Only and Case Sensitive/Insensitive options.

Keep those suggestions coming!

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Friday, January 19, 2007

A TextField Highlighter Class for Flex

One of the features I've always felt was missing from Flash TextFields is the ability to highlight a range of characters with a color. What I did in the past was highlight words by changing their color, which is not nearly as satisifying. So, I was really happy to learn that TextFields in Flash 9 have a new method, getCharBoundaries, which returns the bounding rectangle of the specified character. With this method, we can create a rectangle of color to place behind the TextField, highlighting the specified character or characters.

Keith Peters of BIT-101 and Betaruce both have released demos of this exact functionality. However, their demos lack support for word wrapping, or resizing and scrolling of the TextField. Since text highlighting is on the wishlist for an app I'm developing, I figured I'd Flex it up a bit.

My Highlighter class supports word wrapping, resizing, scrolling, and more. You can highlight all instances of a string, or highlight the next and previous instances of the string. You can also use multiple Highlighters on the same TextField for combinations of colors and functionality.

Try out the demo. You may have to wait a few seconds for the sample text and fonts to load. I'm using embedded fonts and a StyleSheet here just to test that it will handle them, but TextFields in general seem to perform better without them. Oh, and you can right-click and view source too (love that about Flex!).

Here's how it works: when you pass the Highlighter a string to highlight, it finds the instances of that string in the TextField and stores the indexes of each character separately in an array. When the TextField is scrolled or resized, the Highlighter determines which of those characters are visible on the screen and draws a Bitmap rectangle behind them. On every SCROLL or RESIZE event, the Bitmap is cleared and highlights are calculated and redrawn.

This could get to be a pretty processor-intensive system, especially when you have a lot of characters being highlighted. This is where I was really pleasantly surprised by Flash Player 9. When I first started the project, I thought "this will never work - it'll be too slow". But Player 9 handles it like a champ. Unbelievably fast.

There are some things that can screw up TextField.getCharBoundaries, such as newline, carriage return, and other whitespace characters (see my last post). Using condenseWhite on your TextField will take care of that. In my case, I have to preserve whitespace, so some pre-processing of the text is necessary to strip out the offending characters.

Also, in my demo I have padding on my TextArea. This throws off getCharBoundaries, and I compensate by passing an xOffset and yOffset value into the Highlighter class.

Speaking of TextAreas... In the Flex components that use a TextField, there is a property called textField, which would be ideal for my Highlighter class to make use of. But, no. It is protected. Am I really going to extend every component in the Flex framework that I want to use my Highlighter class with? Please. For now, I iterate through the children of the TextArea until I find a TextField. It seems to work fine, but I'd prefer to not resort to such hackery. Anyone else got an alternative?

I'm really happy with the Highlighter class so far, but I'm no architect. I could really use some feedback on what should be public, private, protected, etc... and just architectural advice in general, I guess. How can I make this thing fit in better with the Flex framework? Are there changes I could make that would simplify things, or improve performance? Looking forward to your comments.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Tuesday, January 16, 2007

Flash/Flex TextField Bug - Dancing FlashType Characters

I just discovered this TextField bug today and wanted to get a demo of it out there. Basically, there are certain whitespace characters which are not properly handled by Flash TextFields. If you're not aware of them, they can really leave you scratching your head. One thing they can do is throw off the text metrics returned by methods such as getCharBoundaries, making them wildly unpredictable. A more visible symptom of these characters is text that expands, wiggles and reflows every time you make a selection or click within the TextField.

Check out the demo, and the mxml used to make it. To replicate the issue in the top TextArea, click in the white space to the left of a line of text, and then drag right to select. You should see the text wriggle and jump around like me after a six pack. Notice the bottom TextArea doesn't have the problem, because it doesn't use FlashType.

The character codes that can cause the anomolous behavior are:
11,12,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,30,31, & 160.

Most of these characters will never be a problem, because they're seldom encountered in the wild. However, 160 is frequently seen in its other form: - the non-breaking space.

To work around this issue, I'll be pre-processing all HTML that comes into Flash by stripping out all those characters and replacing them with regular old spaces, which don't have the problem.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Thursday, January 04, 2007

SIFR 3 Beta Announced - Should I Finish Mine?

Mark Wubben of novemberborn.net has recently announced SIFR 3 Beta 1, which he has been diligently working on for quite some time. It's looking very good, and I'm really glad to see that he is still on the case - it's a pretty complicated task, especially for one guy, and if anyone's up to the challenge, he is.

I attempted my own Flash heading replacement solution (TL.FlashHeaders) some months ago, and ran out of steam at the alpha stage when I suddenly got really busy with other work. Now, I'm slowly beginning to get some more free time, but since SIFR 3 is so close to being done, I'm debating whether it's worth finishing TL.FlashHeaders.

There are a couple of areas where TL.FlashHeaders differs from SIFR in concept. For one, TL.FlashHeaders requires almost no JavaScript configuration. Fonts are specified in CSS, rather than in JavaScript. I really wanted deployment to be as easy including the JS library in the head of your document, and specifying the fonts in CSS as you normally would. There are no special style sheets to include. Everything should just take care of itself.

The second main difference is in the way that TL.FlashHeaders handles fonts. It uses a standard Flash shared font library, so it can be reused in other Flash applications. This approach allows support for multiple fonts within the same heading.

Third, I wanted to provide support for inline headings. This may be the most problematic feature to implement cross-platform, due to box model differences, and may be the least useful.

One of the compromises I had to make in order to achieve those goals was dropping support for Opera. I did, however, keep support for IE 5.x and Netscape 7.2.

Here's the current test page. I haven't touched the code in months, and I know it's got some issues at the moment. Try resizing the page to see how things scale. Even the floats at the top of the page should scale as they normally would. To compare, here's the same page without TL.FlashHeaders.

Even if I don't finish it, it was totally worth starting. One thing that was really awesome about developing my own solution in parallel to SIFR 3 was that I was able to contribute to Mark's efforts a little bit, and it always feels good when someone else finds your work helpful. Also, I learned a ton of stuff that has already been useful in other projects.

Early on, there were a few people who expressed interest in the project. So, what do you think? Should I finish what I started, or move on to other things? It's sooo close....

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.