Archive for flex
Dotted Underline LinkButton (Flex)
Posted by: | CommentsI needed a link control that would display a dotted-underline on hover. To achieve this I overrode the rollOverHandler and the rollOutHandler of a standard LinkButton. Inside the rollOverHandler I used the graphics API to draw a dotted underline beneath the control’s textField.
Here’s an example:
There are some magic numbers, but tweaking them to get the look you want shouldn’t be too difficult.
And here’s the source: DottedLinkButton.as
Flex Socket Connections : Socket Policy File
Posted by: | CommentsStarting with certain versions in the 9.0’s of Flash player, socket communication in Flex began adding additional security measures. The one I am going to discuss in the post is the socket policy file. In short, the socket policy file is an XML file that is served by default from port 843 and contains information regarding which ports on _this_ server that Flash may connect to. Additionally it allows you to specify from which domains you wish to allow connections.
Loading the Policy File From Flex
The policy file can be explicitly requested by making the call:
Security.loadPolicyFile("host.withpolicyfile.com:843");
Or you can trust it will implicitly make the request when you attempt a socket connection. The policy is valid for a particular IP address over the life of the SWF. A policy request consists of the following line, nothing more:
<policy-file-request/>
And the correct response is the policy file, followed by a null byte. My example policy server file will not be so picky about it’s request, use it at your own risk. Adobe has one that actually checks to see if the request was formatted correctly before sending the response. Furthermore, rather than reading in an actual policy file, my example hard codes it into the policy server.
Policy File Format
Here is a sample policy file, it is provided by Adobe. You can make whatever changes you need to, as I did in mine:
<?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> <!-- Policy file for xmlsocket://socks.example.com --> <cross-domain-policy> <!-- This is a master socket policy file --> <!-- No other socket policies on the host will be permitted --> <site-control permitted-cross-domain-policies="master-only"/> <!-- Instead of setting to-ports="*", administrator's can use ranges and commas --> <!-- This will allow access to ports 123, 456, 457 and 458 --> <!--allow-access-from domain="swf.example.com" to-ports="123,456-458" /--> <allow-access-from domain="*" to-ports="80" /> </cross-domain-policy>
Policy File Server
And here is the Perl code that runs the policy server. You can see it is just a basic socket server. Adobe’s version of this (which I based mine off) allows you to pass in the port as well as the path to the policy file. This is a stripped down version of that server, with most of the essentials hard coded.
use Socket;
my $NULLBYTE = pack('c', 0);
my $port = 843;
my $content ='<?xml version="1.0"?>'."\n" .
'<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">'."\n" .
'<cross-domain-policy>' . "\n" .
'<site-control permitted-cross-domain-policies="master-only"/>'."\n" .
'<allow-access-from domain="*" to-ports="80" />'."\n" .
'</cross-domain-policy>'."\n";
socket (LISTENSOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'))
or die "socket() error: $!";
setsockopt(LISTENSOCK, SOL_SOCKET, SO_REUSEADDR, pack('l', 1))
or die "setsockopt() error: $!";
bind (LISTENSOCK, sockaddr_in($port, INADDR_ANY))
or die "bind() error: $!";
listen (LISTENSOCK, SOMAXCONN)
or die "listen() error: $!";
while ( my $clientAddr = accept(CONNSOCK, LISTENSOCK)) {
my ($clientPort, $clientIp)= sockaddr_in($clientAddr);
my $clientIpStr = inet_ntoa($clientIp);
# Consume the request
local $/ = $NULLBYTE;
my $request = <CONNSOCK>;
chomp $request;
# Send the policy file
print CONNSOCK $content;
print CONNSOCK $NULLBYTE;
close CONNSOCK;
}
}
Opening A Port
Remember to open port 843 (in Fedora Core) by adding the following line in /etc/sysconfig/iptables :
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 843 -j ACCEPT
Then reload the iptables:
/etc/init.d/iptables restart
Simple Flex Socket Client
Posted by: | CommentsClient-server programming is one of my passions, and I enjoy doing it in almost any language. Which makes it fitting that Flex (ActionScript) is one of my favorite languages to develop in, because it truly is a client-side technology which pretty much means it’s open to just about any type of backend server. I suppose you could make that argument with just about any language depending on how it’s being used, but since Flex isn’t processed and returned to the browser as HTML, that makes it a little different in my opinion.
Even in Flex, most applications will connect to a backend server that’s running an HTTP service (which queries the database on behalf of Flex), but I’m even going to depart from that in this post. I’m going to be demonstrating how to make socket calls to another service. You could apply this to making HTTP requests on port 80, make requests directly to a MySQL server running on port 3306. In this particular post, I will keep it simple by demonstrating how to make an HTTP request.
Declaring and initializing the Socket
You declare socket like this:
import flash.net.Socket; private var socket : Socket;
Inside an initialization method, we will add a listener for the CONNECT event, and the SOCKET_DATA event. The CONNECT event alerts us when the connection has been made, and allows us to send our request. The SOCKET_DATA event is triggered whenever there is data waiting to be read from the socket.
socket = new Socket(); socket.addEventListener( Event.CONNECT, onConnect); socker.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData);
Connecting and Sending Data
At some point you will need to call connect on the socket, which accepts the URL of the server and the port it will be connecting to. In the onConnect() method, you will write the request using one of the writeXXX() methods, and call flush() which actually sends the data over the wire.
socket.connect(txtUrl.text, 80);
private function onConnect(event : Event) : void {
var requestString : String = getHttp_1_1Request();
socket.writeUTFBytes(requestString);
socket.flush();
}
Reading Data
As not all socket data will be available at once, as in most client programs, you will want to read the data in a loop, using one of the readXXX() methods.
private function onSocketData(event : ProgressEvent) : void {
while (socket.bytesAvailable) {
txtResponse.text += socket.readUTFBytes(socket.bytesAvailable);
}
socket.close();
}
In general you would be checking for the end of the response you’re expecting (based on protocol), to simplify things I simply close the socket after the while loop exits the first time. If you leave the socket open for too long without reading data, I have noticed that I receive the following error, regardless of whether I have the correct policy file including cross-domain.xml:
Error #2044: Unhandled securityError:. filename.swf text=Error #2048: Security sandbox violation cannot load data from the.host.name
In this example, the raw output received from the socket request will be shown in the text box. You can download the complete source to this example here (where you may also view a screencast demo of this procedure).
Depending on what version of the Flash Player you’re running, this example may not run as-is if the server you are connecting to does not implement the policy-file (served from port 843. I will be discussing this in an upcoming post where I delve into a little more advanced socket programming in Flex, including how and where to deploy a master policy file.
Some Thoughts on Adobe Catalyst
Posted by: | CommentsI attended a user group presentation on Adobe Catalyst today (2/2/2010), and I thought I’d express some of the thoughts I had, and on code generation in general.
This product seems to spark up a lot of debate, and I think it’s because most conversations are only focusing on two roles (designer vs developer) when there are actually three roles that need to be considered. Those are designer, developer, and (man I hate using this term, but haven’t got a better one) interaction designer. And this is such a touchy area because (putting the science of interaction design aside) in terms of implementation this is where designer and developer overlap.
So there is some overlapping interests in terms of how the application behaves, and there’s only one tool– Catalyst. So who gets to use it? Wrong!! Most hard core developers I know who have tried Catalyst swear they will steer clear of it. Our preferred interaction design implementation tool is the same one we use for developing the rest of our software. In my case that would be Flex Builder. In the designer’s case, it will probably be Catalyst (maybe?).
So if it was so cut and dry, only one tool for this overlapping area, both developer and designer could learn to use Catalyst and get along. I don’t think that’s likely to happen anytime soon. So now the problem becomes one of getting Catalyst and Flex Builder to work nicely together. And I’ve only used Catalyst a little bit, and from what others have told me, making changes in Catalyst and importing them into Flex Builder seems to be pretty smooth. What I haven’t seen is how it goes the other way. If I make changes in Flex Builder, and the artist needs to make some changes in Catalyst– does that work as well?
I don’t know to tell the truth, but until I see how this interaction is going to work out, the jury is still out on whether this overlap of responsibilities is going to work out. I suppose if it were able to compartmentalize all of the Catalyst generated fluff where I could just “use” it and not have to work in it, I think I might be able to live with that. I haven’t seen how this is going to work either, though.
Like I said, I just wanted to get some thoughts out there, and we’ll see how this continues to play out in the coming months. It may be that it ends up being too expensive for my employer to use, in which case it will be business as usual.
Update
Sean Murphy sent me this link that I know my fellow developers will get a kick out of. Warning: If you’re a designer or a print publisher, you’ll probably be wondering, “What was so funny about that?”
Catalyst question in Adobe Forums
Anyway, I’d be very interested in taking a look at his site, I hope he’ll post a link to it. More than anything to see what kinds of projects can be accomplished by Catalyst all by itself in the hands of an experienced artist.
JUICE chat (Stratus Peer to Peer)
Posted by: | CommentsOne of my ongoing weekend projects is an AIR chat application, recently rechristened “JUICE” a.k.a. “John’s Ultimate Internet Chat Experience”. I realize that may only be the case for myself, but the project has been very educational and entertaining for me.
The initial release used AIR/Flex as the front-end, ColdFusion and MySQL for the backend, and BlazeDS messaging for message transmission and “peer discovery”. I worked on it over a couple weeks adding features like encryption, toast-style notifications, as well as a few other less notable things.
I knew the architecture was awful and would never scale beyond a couple hundred users (if that many). Here’s the basics of how it worked:
- The user would login, ColdFusion/MySQL would send back a list of chat buddies.
- Each logged in user would ping the messaging server every 10-30 seconds to announce “I’m still here!”
- The pings would be broadcast to everyone logged in (and connected to the messaging server). The application would filter out the ones it was interested in based on user id.
- Sending messages worked similarly, the user would send the message (which included information about the intended recipient), which would then be broadcast to EVERYONE.
- Everyone would filter this information, and the recipient would know it was for him, and would display it.
You can see why this would not scale well, the amount of traffic and pinging going on. Eventually even a user with only 1 or 2 buddies would notice a significant drop in performance as the number of total users increased. There are some applications of “chat” for which BlazeDS messaging and polling is well suited for (like a chat room). A chat application involving “buddies” is much better suited for P2P.
Enter Stratus. I discovered Stratus a few months ago but was unwilling to delve into it on account of my hectic schedule. Fortunately one of my friends went and did all the dirty work figuring out how to get it up and running (turns out it’s pretty easy) and I was able to apply it to my chat client.
I’m very pleased with the results, though it’s still very much a work in progress. I’ve even been able to add video and voice chat features, which is why I went through the trouble in the first place. Here is how my peer discovery mechanism operates. It requires only 3 calls to the server per client (which I could easily condense to 2 if I wanted).
- The user logs in.
- If the user successfully authenticated, he connects to Stratus and receives his peer ID.
- The user updates his peer ID in the database (which was set to 0) and gets a list of his buddies and their peer IDs. I also update information like whether or not I have a camera/mic.
- The user processes his buddy. If the peer ID is something other than 0, then I know this buddy logged in before me, so I must send him my peer ID.
- Any buddies that have a peer ID of 0 are not logged in, I need to listen for them though since they will get my peer ID when they log in.
- When I log out or close the application, I call the server and reset my peer ID to 0. I also notify all of my connected peers I’m logging out.
There are a few more steps in the process, but it decreases the load on the server significantly, transferring the “burden of proof” onto the clients.
Interesting to note is the way I get the peer ID of a client who connects after me (step 4). I don’t actually have to make a call for this, rather he simply has to start broadcasting to me on the NetStream I set up to listen for him (step 5). When the connection is made, an event will be dispatched by the NetStream class. In fact, 3 events will be fired, I just chose to act on one of them.
The peer ID can be obtained from the peerStreams array on the publishing NetStream. I then use that information to set up my subscribing NetSream.
if (this.peerId == null || this.peerId == &quot;0&quot;) {
this.peerId = publishNetStream.peerStreams[0].farID;
this.subscribeNetStream = new NetStream(model.netConnection, this.peerId);
this.subscribeNetStream.client = new NetStreamClient();
this.subscribeNetStream.play(streamName);
}
Anyway,I’m planning on doing another post to outline my video and voice handshake protocols. They’re nothing to write home about, but I’d love some feedback if there’s a better way. I’m also planning on releasing JUICE after I bring it’s level of functionality back up to where the original version was, so stay tuned and you should see my install badge at the bottom of my blog.
Adobe Stratus and Flash P2P
Posted by: | CommentsSean Murphy (my friend and fellow BYU-AUG member) just did a write up of some training he did last month for our user group. It’s an introduction to P2P with Flash+Stratus.
In my opinion, this is some really exciting technology as most communication of this sort (for Flash player) has to be routed through an intermediate server. Naturally there will still be cases where that makes the most sense, but for p2p apps (i.e. voice/video chat, p2p file transfer, etc) this is definitely a breath of fresh air.
I’ve been working on my own AIR chat application (previously implemented using polling channels on BlazeDS) which I may post more information about over the Christmas break. I’m converting it to use Stratus for real time P2P chatting. In the meantime if you’re interested in getting your feet wet with this, take a look at Sean’s write up: here.
He walks through a multi-user video conferencing app he built. The write up itself is still a work in progress (he’s cleaning up the source, and making a few other changes). He’s the kind of guy that appreciates feedback, so let him know what you think.
You might also want to register for your own Stratus beta dev key: here.
Text Flipper
Posted by: | CommentsOne of my friends posted an upside-down, reversed status to Facebook.
.ǝƃɐd ɹnoʎ oʇuo sIɥʇ ǝʇsɐd puɐ ʎdoɔ ’sʎɐs sIɥʇ ʇɐɥʍ ʇno ǝɹnƃIɟ oʇ ɥƃnouǝ ʇɹɐɯs ǝɹɐ noʎ ɟI
I’d never seen anyone do this before (sorry, I never really got into MySpace or Twitter, and only recently started using Facebook), so naturally I wanted to know how he did it. A google search later I realized he probably either copied it from somewhere, or used one of the many sites out there that perform the conversion.
That wasn’t good enough for me, so I set out to write my own tool. A few minutes of research taught me that it’s not done using a special font (though I wouldn’t be surprised if such a font existed), rather it uses unicode characters that resemble the upside down characters. Once I determined the correct mapping, the rest was simple.
Here it is.
You can browse the source here.
Update 12/24/2009: I also retrofitted it to an ASCII LOL-binary converter. Now you can make Facebook comments with nothing but the letters “L” and “O”.
Here it is.
Contextual Shortcut Manager
Posted by: | CommentsI’m about ready to sleep on my ShortcutManager, I figured I might as well finish off the series. I added context to it, while still maintaining backward compatibility with the non-context enabled version. I don’t think I posted it, so it probably won’t matter so much to my readers. For those who haven’t read the previous posts on my ShortcutManager, the “context” I’m referring to is the context in which a keyboard shortcut might be used; such that a given shortcut might have several functions associated with it depending on its context.
In short I needed four things to implement the context aware shortcut manager.
1. The IKeyboardContext interface
This is a simple interface that a model or class can implement that allows a keyboardContext to be set and retrieved. A keyboardContext is simply a string that identifies the current context. These contexts will be associated with a shortcut in the manager. Here is the entire interface:
package com.googolflex.gflib.interfaces {
public interface IKeyboardContext {
[Bindable(event="propertyChange")]
function get keyboardContext() : String;
function set keyboardContext(v : String) : void;
}
}
2. A reference to an IKeyboardContext needed to be added to the ShortcutManager
As the keyboardContext changes in the model, the ShortcutManager needs to be able to access it, so it can retrieve the correct function for a given keycode-flags-context tuple. The IKeyboardContext was left null, which helps with the backward compatibility (the implementer will be forced to set it if she wants to use it). Here is the line I added, which is pretty trivial:
public static var model : IKeyboardContext = null;
3. Add the context to the addShortcut method
I gave it a default value, which incidentally was “default”, so that every function added to the Dictionary would have some kind of context. Here is the new addShortcut() method:
public static function addShortcut(keycode : uint, func : Function, flags : uint, context : String = "default") : void {
if (flags > 0 && flags < 8)
functionMap[keycode + "-" + flags + "-" + context] = func;
}
4. Finally, the shortcutHandler() needed to incorporate the context
I first check if the IKeyboardContext is null, if it is I know to use “default” as the context. If no context was ever specified, and no IKeyboardContext was ever set, then it still works. Here is the modified code:
public static function shortcutHandler(event : KeyboardEvent) : void {
var flags : uint = getFlags(event);
var context : String = (model!=null) ? model.keyboardContext : "default";
if ( functionMap[event.keyCode + "-" + flags + "-" + context] != null )
(functionMap[event.keyCode + "-" + flags + "-" + context] as Function).apply();
}
And was pretty much it. I will post the modified code, along with a demonstration application at the end of the post. I do want to make a couple points to be aware of when actually incorporating this into a project.
First, your model/class will need to implement IKeyboardContext. Second, you need to remember to set ShortcutManager.model = myIKeyboardContext somewhere. Third, you’re on your own when it comes to maintaining your context. Maybe the “SimpleContextManager” will be next, who knows? And fourth, you’ll have to specify a context when you call addShortcut(). Remember if you download the demo, it will need to have some kind of reference to the ShortcutManager code.
Simple Flex ShortcutManager (revisited)
Posted by: | CommentsI’ve put some more thought into my shortcut manager, and have decided on a way to implement the shortcut context, as well as curb the Dictionary explosion that my previous architecture would have had.
The new version uses one Dictionary to store all functions, the keyCode, combo keys, and context is all encoded into the dictionary key. To illustrate here is my new addShortcut() method:
public static function addShortcut(keycode : uint, func : Function, pair : String) : void {
var flags : int = getFlagsFromString(pair);
if (flags > 0)
functionMap[keycode + "-" + flags] = func;
}
It accepts the same parameters, the only difference is that the pair string is now a dash delimited string, containing the key combinations (i.e. “ctrl“, “ctrl-alt“, “shift-ctrl“, etc). Those are parsed by a method getFlagsFromString() which I will probably get rid of in favor of some named constants on the ShortcutManager class. That will eliminate the need for the additional method, and pair (which will be one of said constants) can be added to the key as-is.
The removeShortcut() is very similar. I haven’t implemented “contexts” yet, but you can visualize how it will be done:
functionMap[keycode + "-" + flags + "-" + context] = func;
Now that there is only one Dictionary, the shortcutHandler() method has become almost trivial. Here it is, in all of its 5-lined glory:
public static function shortcutHandler(event : KeyboardEvent) : void {
var flags : uint = getFlags(event);
if (functionMap[event.keyCode + "-" + flags] != null)
(functionMap[event.keyCode + "-" + flags] as Function).apply();
}
Like I said… trivial.
Using Bit-wise Math to Simplify Logic
Posted by: | CommentsStrictly speaking, bit strings are not nearly as easy to understand as named boolean variables; but there are situations when they can simplify or eliminate the need for long boolean expressions.
Consider my recent post about the ShortcutManager. There are three control keys that may or may not be pressed at any given time. This amounts to 8 possible key combinations (7 if you ignore when none of them are pressed). Here’s what this would look like if you used a boolean expression to check for each of the possible combinations:
var ctrl : Boolean = event.ctrlKey;
var alt : Boolean = event.altKey;
var shift : Boolean = event.shiftKey;
if (!shift && !alt && ctrl) {
// CTRL
}
else if (!shift && alt && !ctrl) {
// ALT
}
else if (!shift && alt && ctrl) {
// CTRL-ALT
}
else if (shift && !alt && !ctrl) {
// SHIFT
}
else if (shift && !alt && ctrl) {
// CTRL-SHIFT
}
else if (shift && alt && !ctrl) {
// SHIFT-ALT
}
else if (shift && alt && ctrl) {
// CTRL-SHIFT-ALT
}
That might not seem too bad, and it isn’t that hard to understand what’s going on (even without the comments). But what happens when you’ve got 4 variables (16 possibilities)? The number of combinations increase exponentially. Even if the combinations you are actually interested in are sparse, who wants to type out 10 lines each with 32 boolean variables?
With a simple method to construct my “bit string”, we can greatly simplify this. ActionScript doesn’t have a binary number type, so you’ll have to use integers. If you can count by powers of two you won’t have any trouble. Here’s a method that constructs my “bit string” integer based on selected control keys:
private static function getFlags(event : KeyboardEvent) : uint {
var flags : uint = 0;
flags += (event.ctrlKey) ? 1 : 0;
flags += (event.altKey) ? 2 : 0;
flags += (event.shiftKey) ? 4 : 0;
return flags;
}
Having this integer allows me to simplify the logic as follows (which isn’t harder to understand at all, if you use comments):
switch ( getFlags(event) ) {
case 1: // CTRL
break;
case 2: // ALT
break;
case 3: // CTRL-ALT
break;
case 4: // SHIFT
break;
case 5: // CTRL-SHIFT
break;
case 6: // SHIFT-ALT
break;
case 7: // CTRL-SHIFT-ALT
break;
}
This is powerful, but it’s just scratching the surface. I haven’t even discussed the bitwise operators &, | and ^. Or the bitwise shift operators >> and <<. These come in handy when you store a series of options as a bit string and need to test whether a certain option is on or off.
For example, if we needed to test if value returned by getFlags() had the SHIFT bit set, we could use the following boolean expression to test it. Remember SHIFT = 4:
if (getFlags(event) & 4 == 4)
Of course this doesn’t help us out much now in the ShortcutManager, but assume I was to add 3 possible contexts that these shortcuts might be used in (different screens, for example). They would hold the 8, 16, and 32 bit places. I could use bitwise math to split them if I only needed to manipulate one them at a time (a stretch, I know).
var screenOnly: uint = flags & 56; var keysOnly: uint = flags & 7;
They have a variety of uses and are there when you need them. There’s an excellent explanation of various bitwise operations and their uses here.


