April 28, 2005
Examples have been fixed
Ok.. The examples should be working again. Sorry about that.
Posted by sho at 1:48 PM
April 27, 2005
Argh!
My @()*&$ SWFs timed out! The funny thing is that I've sat through meetings (as a a manager) where we discussed this very thing, so I should have known better. :-)
Anyway, I'll find a public facing MXML server I can use to post examples. In the meantime, the example links in my earlier posts won't function.
Posted by sho at 4:56 PM
There are problems with comments on this blog.
Several people have written me to say that they are confronted with an error when they try to view the comments. This is due to an anti-spam measure that sometimes gets confused. It will be fixed soon, but to work around it, go to the entry detail page before viewing and adding comments.
BTW, I shortened all the entries on the main index and put the remainder of the text on the entry detail page. I thought that MT did that for you automatically, but I was wrong.
Thanks for reading, and thanks for commenting!
Posted by sho at 8:32 AM
April 26, 2005
It's ugly when the animation engine and layout engine fight.
Originally, I wanted the "new user..." label to animate into position between the welcome screen and the new user screen. As it turns out, moving the label while its parent container is moving leads to some jagged animation.
Stare at the label as you go through the animation. Notice how it appears to jump up and down? I had to ask a lot of questions before I got to the bottom of the issue. When animations run in parallel, do all tweens update at the same time? Yes, theoretically. If there isn't enough time between frames to do all the updates, do some of the updates get dropped? No, the answer is that the frame is delayed. etc., etc.
The answer, as it turns out, is obvious in hindsight. It has to do with the layout managers and how they work.
Certain properties, such as the position of elements relative to their parents, are wired up directly to the underlying Flash Player display list. That means that when these properties are updated, the Flash Player automatically displays the new results.
The MoveEffect modifies position properties at each frame. This happens "immediately."
Meanwhile, the ResizeEffect modifies size properties at each frame. This can cause positions to change (because my panel is vertically aligned middle within the application), but that doesn't happen until the layout manager computes the new position.
The reason you see the jagged motion is that the contents get moved, and a frame or two later, the effects of the parent resize are displayed.
Short of changing Flex to have tighter guarantees on this sort of thing, the best solution is to not animate the positions of things that are inside containers that are being resized. Either let the layout engine figure out the positions of everything inside the container, or use MoveEffect to move something inside the container, but not both.
At some point, I want to experiment with creating a proxy object that floats above the container to see if I can create the illusion of having the label move smoothly as its container resizes. It's probably a better way to go in any case, because this allows you to set start delays and easing functions for both the resize and the move without causing weird interactions between the two effects.
P.S. Let me know if you've tried something along these lines!
Posted by sho at 10:54 AM
Effects are hard to get just right.
One thing I wanted to do was to create nice effects between pages. This turned out to be harder than I thought.
As you recall, I'd settled on separating my app into "pages" which were implemented as components inside of a ViewStack. To go to a new page, you flip to different index of the ViewStack.
As it turns out, this makes it hard to do smooth effects. For example, the effect that I wanted between the welcome panel and the new user panel was that the the welcome panel contents would fade out, and then the panel would smoothly change size to be the same size as the new user panel, after which the ViewStack would flip to the new user panel. The page flip was triggered off of the effectEnd event.
Some issues:
- I couldn't figure out the size of the new user panel because it hadn't been created yet.
- The panel contents didn't fade nicely because of device fonts.
- The last frame of the resize effect ended up not being played, which meant that the transition felt "glitchy".
- There is sometimes a flash of gray when the page is flipped
I tried various ways of lazily instantiating the new user panel in order to resolve issue 1. I even went as far as to read the Flex source code to try to mimic what ViewStack does. In the end, I gave up and used creationPolicy="all". This was fine for my app, but there is obviously a direct tradeoff between startup performance and responsiveness later on in the app.
Issue 2 was easy to resolve, once I learned about the dissolve effect. It's a shame that these have to be different, but I suppose that's the price you pay for relying on the OS to do your fonts for you. Another option would have been to embed the fonts as outlines, but that would have meant that the download size would be bigger, and that the OS font smoothing technology wouldn't be used.
Issue 3 was frustrating, and I tried to solve it in several ways. It's only really noticeable when there is a big delay between the last frame of the animation and the page flip, which can happen when loading big pages.
First, I tried putting the page flip into a doLater() call in order to allow the system more time to show the last frame of the animation. The good news was that the last frame of the animation was properly displayed. The bad news is that immediately after the last frame of the animation, the page flip cased the gray background to appear, and what had once been a momentary glitch (issue 4) became a blank gray screen that stayed up while my data was loading! Ack! Talk about out of the frying pan, into the fire!
For now, I am punting on issues 3 and 4 and going back to the initial, straightforward implementation. You can see the results here. Click on the "new user" link to go to the new user page, and click on the "cancel" button to go back.
I am still trying to think of ways to get rid of the flicker of gray as the page is swapped. One possibility is to change my containment to ensure a smoother transition like so:
<Application> <Panel> <ViewStack id="vs"> <local:WelcomePage> <local:NewUserPage> <local:AlbumInfoPage> </ViewStack> </Panel> </Application>
The problem (for me) with this approach is that in reality, the album info page has two panels, not one. And even if they were all one panel pages, there would be no way to swap out the control bar on the panel (AFAIK). The upside, of course, is that there is one and only one panel, so that if you use effects to resize it, you don't have to worry about "swapping it out" when you are finished. Not sure what I'm going to do about that, but I have to get rid of that gray flicker!! Grr....
Now that I've complained about effects, let me cap all of this off with some perspective. Yes, effects are harder than I thought, but they're easier (for me) than in traditional Flash, or in HTML. :-) As I learn Flex, I'm finding myself doing things that I was never able to do before, which is pretty cool.
Posted by sho at 8:30 AM
April 25, 2005
Are components really a good substitute for pages?
One of the things I get hung up on is that HTML-based sites are built up from pages, whereas Flex sites are one big glob of goo as far as the outside world is concerned. Some people see breaking up sites into pages as a bad thing (e.g., it forces you to jump through hoops to ensure that the proper data has been fetched on each page, etc.), whereas I see breaking up sites into pages as a good thing (in general, I agree with the REST folks, although I'm not religious about it).
For my project, I envisioned the following "pages" to start with:
- welcome
- new user
- album list + album detail
In the Flex world, the easiest way to split things up like this is to use a ViewStack. Coming from the HTML world, I find the idea that all the pages of your app are just lying around waiting to be displayed a bit unnerving, but I think it's just something I need to get used to.
At this point, my app looks something like this:
<Application> <Script> all script for all pages goes here... </Script> <ViewStack id="vs"> <Panel title="welcome"> lots of stuff... </Panel> <Panel title="new user"> lots of stuff... </Panel> <Panel title="album list"> lots of stuff... </Panel> </ViewStack> </Application>
While the visual elements for all the "pages" of my app are split up in the ViewStack, the logic is all stored in one big block.
In Flex-land, the way to separate this out is to create components, so I tried that. At this point, my app looks like this:
<Application> <ViewStack id="vs"> <local:WelcomePanel id="welcomePanel" /> <local:NewUserPanel /> <local:AlbumInfoPanel /> </ViewStack> </Application>
Hooray for encapsulation! It looks pretty, right?
Well, now what happens when I want to hook these pages up? Let's say there's a button on the welcome panel that takes you to the new user page. Before, the code might have looked like:
<Button label="Create account" click="vs.selectedIndex = 1" />
Now, the same code would look like this:
<Button label="Create account" click="Application.application.vs.selectedIndex = 1" />
Ack! That looks like a severe violation of encapsulation! How does the component know that the application has a viewstack called "vs", let alone what index to set?
Another possible solution is to add the handler to the application, not the button, like so:
<Script>
<![CDATA[
function appInit()
{
welcomePanel.newAccountButton.addEventListener("click", this);
}
function handleEvent(event: Object)
{
if (event.type == "click" && event.target == welcomePanel.newAccountButton)
{
vs.selectedIndex = 1;
}
}
]]>
</Script>
But this is a violation of encapsulation in the other direction. How does the application know that the welcome panel has a button named "newAccountButton"?
The only "clean" solution is to provide a formal contract between the components and the application. This could be done by having the component declare an event (newUserClicked) or having the application create API functions which the components can depend on. The problem is that all of these solutions feel like overkill, when all I want is the equivalent of "go to this page".
In HTML, this is solved by the <a> tag, which essentially says "set the application state as described by 'xxx.html'." One could say that this violates "encapsulation" in that the page needs to know that xxx.html exists, but that's part of the architecture of the web. URIs are meant to be meaningful, persistent, and represent states that you are guaranteed to be able to get back to.
I don't have a perfect answer to this yet, but it's something I've been thinking about a lot.
Posted by sho at 10:08 AM
This is my first Flex project.
I've been working with Flex for a while now, giving my thoughts here and there about this and that. (vague enough for ya?). However, I had yet to build a Flex app, because there never seemed to be time.
So, a few weeks ago, I decided to make time in my schedule to learn Flex for real. Other than go to meetings, I did virtually nothing else.
I had three goals:
- Learn Flex.
- Prototype ideas for improvements to the Flex framework.
- Think about what makes for a good RIA.
For this first project, I wanted to pick a project that was "real" enough that I would learn what Flex development was all about. I wanted something that had a heavy focus on usability, involved data and effects, and had potential scalability issues to consider.
I settled on building a prototype social music tagging site. The idea is as follows:
- You create an account and optionally upload your iTunes music library file as a starting point.
- The interface allows you to rate and tag your albums.
- You can find out about new music by looking for other users with similar albums, or by sorting albums by tag.
- Later on, I would love to add things like reviews, top 10 lists, etc.
BTW, if something like the above already exists, I'd love to hear about it. Not that it would stop me from building out my prototype. :-)
Posted by sho at 9:59 AM
April 24, 2005
Does this page look ok?
Quick note. I tried this page on IE6, Firefox, and Safari, but not earlier versions of IE. I resisted the urge to use tables for centering, but I'm worried that my code may not look right on IE4/5. Let me know if you have problems.
Thanks!
Posted by sho at 1:11 PM
Tools are all about details.
Before talking about Flex, a quick word about Dreamweaver.
To put the templates for this site together, I used Dreamweaver for the first time in over a year. I'd forgotten how much I love that tool! There are plenty of enhancements and improvements I'd like to see, but most of the big things are right and most of the little things are right. Surprisingly, the little things are often more important than the big things. In fact, I'd go as far as to say that it is more important for a tool to get the little details right than anything else.
Here is a story about the little details.
Early on in the hacking up of my templates, things looked like this. Notice how the text runs past the right edge. I double checked my CSS and I was convinced that I'd found a bug in Dreamweaver. However, when I tried it out in the browser, I got the same result.
Doh! It turned out that Dreamweaver knew more than I did about how browsers calculate padding and width, which changed to be more standards compliant in IE6. Thanks to Randy Edmunds, who fixed hundreds of layout bugs in MX 2004, DW correctly mimics the browser in this case, which alerted me to this problem.
Yeah, yeah, rendering is important. But the story doesn't end there. If you look at the line breaks, you'll notice that they're identical. The words wrap at exactly the same point, and this is not an accident. An engineer by the name of Don Woodward and I spent some concerted effort experimenting with font metrics during Dreamweaver 1.0 to try to get as close to Netscape Navigator as possible, and it turned out to be not as easy as we thought. I forget the details, but there are different ways to ask the system for metrics, there were fractional sizes involved, and so forth.
Being obsessed about getting the lines to break at the right points might seem silly (after all, the HTML spec doesn't guarantee how the UA will do linebreaks, right?) but things like this do matter. People expect Dreamweaver and the browsers to render things the same way, and a misplaced line break can mean that an extra line is added, which can cause other layout issues...
What's the point? Well, details are important when it comes to tools, and the most important details are ones that you will never notice if things are working properly.
Posted by sho at 9:45 AM
April 23, 2005
Hello.
My name is Sho Kuwamoto, and I've been hanging around the web for about ten years. I've kept a relatively low profile over the years, possibly for different reasons than you might think.
For the last eight+ years of my life, I've been working at Macromedia. I started out on the Dreamweaver team, as an engineer on version 1 of the product. At some point, I may tell a story or two about those times.
Since then, I've spent most of my time here overseeing engineering for Dreamweaver and related products, such as HomeSite, UltraDev, Fireworks, Contribute, and even FreeHand (for a brief period!)
Recently, I've shifted gears again (still at Macromedia) and now I spend most of my time thinking about Flex. I'll be blogging primarily about Flex, but I'll also blog about HTML, CSS, and Dreamweaver, as well as general thoughts about software engineering.
I'm a relative latecomer to the blog world. Let's hope that I have something interesting to say, and that someone listens.
P.S. Bonus points will be awarded if anyone can dig up my first (silly) web project.
P.P.S. Don't spoil it if you already know.
P.P.P.S. You won't find it on the wayback machine.
Posted by sho at 5:37 PM