Tutorial: Context menus are our friends if we use them correctly

 

In my quest to blur the line between native apps and AIR apps, I decided to fully incorporate context menus (right-click) in the next release of DestroyTwitter. In my initial tests, I came to realize that the ContextMenu class is the roommate who is really nice and optimistic before you move in, then a nightmare to get along with once you’re finally settled. It screams to be extended, but ironically it’s a final class (not extendable). After a few hours, I found a solution. But first, the problem.

Let’s say I have 100 icons. I want each icon to have five actions accessible from its context menu. This results in 100 ContextMenu instances and 500 NativeMenuItem instances, as seen below:

ContextMenu memory

This is not pretty. The solution: share. In programming, sharing is one big step towards drastically reducing memory usage. If I share a single context menu, I will have one instance instead of 100 and five item instances instead of 500.

Context Menu memory

As expected, memory usage is divided by 100. The problem with sharing the ContextMenu class using a display object’s contextMenu property is that it can’t be done. On paper it can be, but not the way you want. To share a context menu, you’d have to listen on Event.DISPLAYING and use the hitTest() method to check which object the user is right-clicking. From a developer’s standpoint, this is simply unethical. Also, Flash content doesn’t update the mouse position between sequential right-clicks, so you could have a major issue with power users.

The solution is to forget the ContextMenu class altogether. While you’re at it, forget the contextMenu property as well. If you want something done right, you have to do it yourself. Add a listener to the MouseEvent.RIGHT_CLICK event, share a single NativeMenu instance, and call the NativeMenu.display() method in the right-click handler. For the purpose of this demonstration, I construct the NativeMenu in the Icon class. Since we’d ideally share the menu, you’d construct it outside of the class that’s using it, then reference it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package {
	// import classes
 
	public class Icon extends Sprite {
		public var _menu:NativeMenu;
 
		public function Icon () {
			__construct ();
			__init ();
		}
		private function __construct ():void {
			_menu = new NativeMenu ();
 
			// construct NativeMenu items
		}
		private function __init ():void {
			addEventListener (MouseEvent.RIGHT_CLICK, __rightClick__, false, 0, true);
		}
		private function __rightClick__ ($event:MouseEvent):void {
			// change NativeMenu items' attributes
 
			_menu.display (stage, stage.mouseX, stage.mouseY);
		}
	}
}

There is a second chapter to the context menu nightmare, which is the API for managing items. It’s clumsy, excessive, and requires the developers to write some pretty gross-looking code. I’ll save the solution to that for another time.

DestroyTwitter + Twitter = @destroytwitter

 

DestroyTwitter twitter account

DestroyTwitter is finally on Twitter. For the past nine months, I’ve used my personal Twitter account (@destroytoday) to post news and respond to feedback. That’s all fine by me, but I figured an account of its own would make things more official. Lots of people asked how I was able to get an account with the word “Twitter” in the name. In all honesty, I simply asked. Since DestroyTwitter has been around for a while (for a Twitter app), they were able to make an exception. If you haven’t done so already, go ahead and follow the @destroytwitter account—and keep an eye out over the next few weeks.

Escaping single quotes in SQLite

 

I’m working on storing all tweets viewed in DestroyTwitter into a local SQLite database to improve performance with filtering and paging. I’ve already been using databases in order for Groups to work, but to avoid characters that might be trouble for the SQLite queries, I would simply run the escape() method to URL-encode the string. Lately, I’ve been on this testing-high, making sure every bit of code I write is the most efficient to my knowledge. After testing escape() vs String.replace(), I realized that the latter is ten times faster. Of course, it makes perfect sense.

My lazy self months ago used escape() without thinking, but now that I know the incredible speed difference, I’ve created an addSlashes() method to use a regular expression to prefix each single quote with a slash (\). This resulted in an error. After a bit of research aka Googling, I came across a mail archive that said that SQLite escapes single quotes a bit differently. Instead of a slash, you must escape it with another single quote. In all honesty, this makes no sense to me, but it works. Here are examples of what works and what doesn’t:

// Wrong – unescaped apostrophe
INSERT INTO tablename (id, name, text) VALUES (1, ‘Jonnie’, ‘That’s what she said’);

// Wrong – incorrectly escaped apostrophe
INSERT INTO tablename (id, name, text) VALUES (1, ‘Jonnie’, ‘That\’s what she said’);

// Correct – unescaped apostrophe
INSERT INTO tablename (id, name, text) VALUES (1, ‘Jonnie’, ‘That’’s what she said’);

Please note that the correct query above uses two separate single quotes, not one double quote.

Do you use regular expressions with Include/Exclude keywords in DestroyTwitter?

 

If you answer yes, please comment what regular expression you use.

DestroyTwitter in-app photo viewing within the main window or in its own?

 

I’ve decided to rethink things a bit in DestroyTwitter, so I’ll be conducting a survey over the next few weeks. Today’s question is whether in-app photo viewing is working within the main window or should it be its own window? There are benefits to both, but what do you think?

Which window chrome setting do you use in DestroyTwitter and why?

 

If there any other answers not listed here, feel free to fill up the comments. Also, if you’d like to extend your answer, further commenting is encouraged.

Icon memory usage in DestroyTwitter

 

Icon memory usage

In the next release of DestroyTwitter, I’m introducing a new icon preference. It lets the user choose whether they want small icons, big icons, or none at all. The choice is not entirely a visual one, but also one of resource usage.

The above profiler tests show the memory usage between the three options. As you can see, there’s a startling difference between DestroyTwitter when it has icons compared to when it doesn’t. That was expected to some degree, but what’s also interesting is the how slight the difference is between small and big icon memory usage. Since the big icons have 33% more bitmap data than the small ones, I assumed the margin would be greater than 641 kb.

Throughout development of DestroyTwitter, an option for bigger icons has always been high on the list of most requested features. I always pushed it to the side, claiming it would use a considerable amount of memory compared to the current size. After performing these tests, it’s safe to say that the difference is minimal. If you prefer a larger icon, you’re not going take a hit. With the option for no icons, however, are you tempted to go for text only?

Sync DestroyTwitter settings with Dropbox

 

Dropbox in DestroyTwitter

In the latest release of DestroyTwitter, you have the ability to choose where your settings are saved. Because of this, you can use Dropbox to keep your settings synced across multiple computers. Dropbox is a free, cross-platform application and service that gives you 2gb of space to sync over multiple computers, devices, and on the web. If you don’t already have Dropbox, download it here.

Dropbox in DestroyTwitter

Once you have Dropbox installed, go into DestroyTwitter and click the link next to “Settings directory” in the Preferences canvas. This prompts the window browser where you can select your Dropbox folder.

Dropbox in DestroyTwitter

In the window browser, you can make a new folder for your settings or simply select the root Dropbox folder. Whichever folder you select, a folder titled, “DestroyTwitter,” will be created and the settings files are written within that.

If you want to retain your current settings, you can do so by moving the default settings folder located at /[user]/Documents/DestroyToday/DestroyTwitter and placing it in your new location. Upon startup of DestroyTwitter, you will recognize the same settings you had before, but now they are synced through your Dropbox account.

DestroyTwitter 1.7.2 Beta release

 

Another day, another DestroyTwitter update. This one fixes a few more bugs, so hopefully they’re all flattened. Let me know if there are any difficulties with anything—you know I’m quick to draw.

Read Messages marked as unread in DestroyTwitter

 

There’s a bug in DestroyTwitter 1.7.1 Beta where some direct messages are marked as unread when they shouldn’t be. This is caused by the fix to Groups and Exclude where I lowercased all usernames. Unfortunately, I forgot to lowercase direct message usernames. If you’re getting this bug, it’s because your username has a capital letter in it. It’s already fixed and will be part of the next release.