Tuesday, August 21, 2007

Oh, I just want it to work as, you know, in Explorer

"I mean, is it too much to ask" said my product manager. All she wanted is to be able to rename an element in the tree viewer we have in our application. "Just like in Windows Explorer", she said.

Right.

In Explorer, when you click an element and then click it again, after some time, an in place editor is opened allowing you to rename the file or directory. But if you click fast enough, the system recognizes this as double click and performs the associated operation (i.e. opens a file or enters a directory). We wanted to do the same in our tree control.

At first it looked easy, the Internet is full of examples of how to add an in place editor to the SWT Tree control. However, problems began when we tried to determine when the editor should be activated. It should be when the same element is selected twice in a row, but not it should not happen when the element is double clicked.

Now, I have to admit, I am a little confused since there are two different types of events. There is a Selection event, which can handle both single and double click operations. There is also a MouseDown event, which also can be used for this purpose. In addition it is possible to monitor events that occur in the jFace TreeViewer or the underlying SWT Tree control itself. Very confusing.

First attempts left us with buggy, inconsistent behavior, nowhere near our Explorer ideal. We had problems with activation, the double click still activated the editor. We also had different problems with TRAVERSE_ESCAPE event due to the fact that we did not know how to correctly handle FocusOut. It was really frustrating.

I would like to present a solution which seems to satisfy all our requirements, though I admit it is not a peak of beauty. It does seem to work, however, which in our line of business is a plus.

The solution is based on a single SelectionListener implementation attached directly to the Tree which handles both single and double clicks (through widgetSelected and widgetDefaultSelected methods). In addition we remember the last selected element and whenever a double click is recognized we raise a special flag. The purpose of this flag is to avoid entering the editor in case an already selected element is double clicked.

Each time widgetSelected is called, it updates the last selected element and then waits for about half a second. It then checks whether a double click flag is up, and if it is not, opens the rename editor. After the editor exits, the flag is reset.

I really hope there is a better and shorter solution which provides the same functionality, I did not check Eclipse 3.3 yet, I hope it is there. In any case, if you need this solution add comment with your email and I will send you the source. It will also be available for download from here as a part of the new RadView Reporter. Look for version 10, it should be there in about two weeks. You will be able to find this code in the TemplatesView class.

No comments: