Posted in April 2007

Apollo Mail Client Version 0.3

by

screenshot

screenshot

screenshot

I’m pleased to announce the first alpha release of ApolloMail, a cross-platform POP3 / SMTP e-mail client written in Apollo (obviously) in under 500K (and most of that is my gratuitous about banner). It’s just the beginnings, really, but here is a short feature matrix:

  • Authenticated POP3
  • Authenticated SMTP
  • MIME multipart emails
  • HTML e-mail rendering
  • Image attachments
  • Base64 decoding
  • Quoted-printable decoding

Features that may be added very soon are:

  • Local message store
  • HTML e-mail composing
  • Rich Text rendering
  • Better attachment handling
  • Far more robustness

IMAP and SSL are less likely to be added soon. I would like to also use this as a platform to do something new with email, including several unique views which visualize your e-mail life graphically and in three dimensions. Otherwise it’s just another boring e-mail client.

E-mail has been around since 1971 (that’s ten years longer than me!), and it’s been built upon time and time again. I learned a ton about how e-mail works by building this app. On the other hand, I am sure I haven’t covered every kind of e-mail, POP server, or SMTP server; chances are fairly good you will come across an e-mail that this client doesn’t handle. Don’t panicdon't panic! It’s just an alpha. In addition to mail rendering, the error handling while communicating to the server could be better. If you are experiencing trouble, watch the Activity window. Further, the windowing built into this version of Apollo is a hack, so many Flex components don’t work correctly.

There are a number of interesting technologies in Apollo that this app takes advantage of, which I will be sharing all of in the coming days. First, it leverages my windowing framework which I discussed in a bit of depth before. It logs to a file using the File Logging Target I published earlier. It also uses another simple but awesome technique to implement the activity window — a String logger which exposes its cumulative log messages as a bindable variable — so the activity window is a TextArea bound to a log target which filters only a specific category of logging information (while all logs are saved to disk). It extends an abstract preferences class which makes it a snap to bind to, serialize and deserialize application preferences to disk. And of course, it makes heavy use of binary sockets and regular expressions made possible by Flash Player 9.

I’ll be writing more about the technology involved, and sharing more of the source, in another post or two. For now, grab the Apollo runtime if you need it (link has mandatory registration), and take ApolloMail for a spin! Cheers!

Update: This application is made for the Apollo Alpha. If you have the AIR Beta runtime, it will not work. The next version of ApolloMail will be upgraded for this release of the runtime.

icon ApolloMail (ZIP, 486k, ZIP decompresses to an AIR file, open the AIR file after installing the Apollo Runtime.)

Hand Me That Cursor, Would You?

by

Today I’d like to talk about a basic technique that’s a little deceptive when migrating from AS2 to AS3: creating a clickable button from a Sprite or MovieClip.

So you create a new Sprite or custom view class that subclasses Sprite. For purposes of argument, here’s a simple button class:

package
{
    import flash.display.Sprite;
    import flash.filters.BevelFilter;

    public class CustomButton extends Sprite
    {
        public function CustomButton(width:Number = 100, height:Number = 20)
        {
            super();
            graphics.beginFill(0xaaaaaa);
            graphics.drawRoundRect(0, 0, width, height, 6, 6);
            graphics.endFill();
            filters = [new BevelFilter(2)];
        }
    }
}

Then you do two things new to AS3. You add it to your display list, and you attach an event listener:

var button:CustomButton = new CustomButton();
addChild(button);
button.addEventListener(MouseEvent.CLICK, onButtonClick);

You’ll notice that (if you do something in onButtonClick) the button is functional. But the problem is: no hand cursor! What the devil?

For a second let’s recall AS2. To get our little pointy finger cursor, all we had to do was add an onRelease callback to the MovieClip or MovieClip subclass. The code above proves the analog of this in AS3 does not apply. We didn’t automatically get a hand cursor by virtue of adding a CLICK listener.

Remember, though, in AS2, there was a property on MovieClips called useHandCursor? Setting this to false could disable the hand cursor on that object. Well, Sprites and MovieClips still have this property in AS3. You might think: why not set this to true? Unfortunately, that’s not it either.

The proper way to make a Sprite/MovieClip show the system hand cursor when the mouse is over it is to use the new buttonMode property. See it in LiveDocs here.

buttonMode tells a Sprite if it should behave like a button or not. It defaults to false: even if you have event listeners set on the Sprite, it will not behave like a button. You need to manually set buttonMode to true.

“Behaving like a button” means three things.

  1. The system hand cursor is used.
  2. The item appears in the tab order.
  3. When the item has tab focus and you press space, it broadcasts the CLICK event.
  4. (Minor) if you have _over, _up, and _down frame labels they will be used as button states.

As far as hand cursors go, useHandCursor can control whether the hand cursor is used with the object or not, but it means nothing if buttonMode is not set.

tabEnabled can set whether the item appears in the tab order. This property doesn’t require buttonMode to be true to take effect. In other words, you can have something in the tab ordering without it needing to be a button. But remember, without buttonMode, when you tab to the item and press space, it won’t trigger a CLICK event.

Some problems we run into: If your clickable object contains anything else clickable, the target of those events will be the inner object. Furthermore, if you have a TextField inside of a button mode Sprite, the mouse cursor won’t appear as a hand cursor above that TextField, even if you have no event listeners on it and it’s not selectable. You can see this in the demonstration below. Try clicking inside the flash movie and tabbing around as well. The button mode button inside button 1 (on the left) is getting in the tab order, and the text field inside button 2 (on the right) is stealing the cursor type.

In order to fix these issues, if they are indeed problematic, you can use these additional properties of InteractiveObject and DisplayObjectContainer.

tabEnabled
Whether this item can be tabbed to.
tabChildren
Whether the children of this item can be tabbed to.
mouseEnabled
Whether this item accepts mouse events.
mouseChildren
Whether the children of this item accept mouse events.

By setting mouseChildren to false, you can treat any complex compositions of objects as one mouse target, even if the inner items would otherwise be clickable.

If you see this message, you need to install Flash Player 9.

Play around with the example to see how these properties can affect the mouse cursor, ability to be tabbed to, and the target of events.

In short: buttonMode makes a Sprite a button. useHandCursor is only meant to override behavior set by buttonMode. You can also make buttons by extending the SimpleButton class.

Logging to a File in Apollo

by

Since Apollo apps will be run as standalone desktop applications, logging to trace output or a LocalConnection won’t really be useful once the app is installed on the end-user’s machine. It would be great to log (a responsible amount) (if you want) to the resource directory of that application itself. And it would be nice to be able to use built in logging to do so.

Well, I don’t know why this wasn’t included with Apollo, but it was certainly easy enough to add in. :) I created com.partlyhuman.apollo.logging.FileTarget so you can use the Flex logging framework while logging to a file. It supports all the options of TraceTarget (livedocs), and you can also (optionally) specify a custom filename to log to, or force it to append log output across sesssions.

Here’s how you might put in a file logging target in MXML:

<logging:FileTarget
	filename="error.log"
	append="false"
	level="{LogEventLevel.ERROR}"
	includeDate="true"
	includeTime="true"
	includeCategory="true"
	includeLevel="true"/>

That’s showing off a lot of the options. You could just do <logging:FileTarget/> and all would be fine. And if you haven’t checked out logging in Flex, it’s pretty nice (livedocs). All logging events have a category, so you get a logger for that category then call the appropriate level on it, or call log with the level as an argument. For example:

Log.getLogger("com.partlyhuman.demoapp.MainController").error("initialization failed!");
Log.getLogger("com.partlyhuman.demoapp.Bubble").info("bubble popped!");

You don’t have to be so verbose in your categories, but that’s one way to use it.

This is gonna totally become like, a thing, but… happy logging!

filecom.partlyhuman.apollo.FileTarget View Source | Download (.as, 3k)

Apollo Native Windows Part 3

by

As promised I’m back with more goodies! This time I’ve extended the simple window manager to support document windows as well as application windows. I also included a class that binds to your MenuBar in an empty menu and keeps it populated with a list of windows. Clicking a window name in the menu will activate, unminimize, and bring the window to the front.

Application windows are windows that can always be brought up, like an activity window, or an about window. When you create an application window, it is created and hidden. Pressing the close button on the window is captured to hide the window rather than allowing it to be destroyed. Thus, it occupies a permanent position on the Window menu.

Document windows are windows which can be created and destroyed. You can have many instances of the same view class. These are useful for new mails or text files or what-have-you.

The main window has a special use. When you attempt to close it, it attempts to close all the child windows as well — so you can have an opportunity to save your unfinished document windows.

Apollo Windowing in Action
This is the windowing toolkit at work on an Apollo app I’m finishing up now. File→New Mail… creates a new document window with the compose view, and adds it to the Window menu. As you change the subject, the title of the window and its name in the Window menu are updated. The Window menu also permanently has several application-wide windows which the close button appears to close. The Window menu brings them and any other window back, even if they are minimized, hidden, or stacked on the bottom.

After the cut, let’s take a look at how this is set up in code.

Continue reading

Apollo Native Windows Part 2

by

Previously, I was trying to manage multiple native windows in an Apollo app. I found that I couldn’t add Flex components to a new window, and was dismayed. But Danny Dura came to the rescue with a sweet workaround. See the play by play here.

I’m developing a window manager to make things much easier for Apollo apps. The full window manager will be up shortly. For now, I have created a simple window manager, that wraps up the many steps necessary to create a window containing a Flex view (and clean it up on destruction!) into a really simple singleton class. The more fully-featured window manager will use this class, but it can be very helpful on its own. It makes creating new windows with Flex views a one-line operation:

var aboutWin:NativeWindow = WindowManagerSimple.getInstance().newWindow(AboutView, "About", {maximizable: false, resizable: false}, 300, 100);

You can use either a class name or a UIComponent instance for the view, and all the other parameters are optional. The window options parameter can accept a NativeWindowInitOptions object or an anonymous object of properties that override the defaults for brevity. See the source file for more info, Javadoc-styleeeee.

Next: A more complete window manager, including application and document windows. Read on.

filecom.partlyhuman.apollo.WindowManagerSimple View Source | Download (.ZIP, 6K)