Need something in SWT?

2. January, 2011

When the guys at SWT can’t be bothered, there is now an alternative: A little project to create drop in replacements for stuff that you want in SWT. Check it out here.

In the same place, you can find a slightly modified version of StyledText. When I say “slightly modified”, then I mean “at the API level”. I’m currently heavily refactoring the code inside to make it maintainable and more easily extendable.

Some achievements from the latest hacking session:

  • It’s now possible to write tests that verify the rendering of StyledText
  • Bullets are managed and rendered in their own special classes. Same goes for StyleRanges. That reduced the size from 1’700 lines to just about 1’100 lines – not that much but a good start. This also means I can write tests that just check the management of StyleRanges – without bothering with a main loop, resource management, etc.
  • There are a bunch of helper methods to debug the model behind your text. They can dump the text in readable form.

What’s next? I’m really starting to think about turning StyleRange and TextStyle into independent classes. Right now, the former inherits from the latter which means there is some really ugly code when it comes to reusing styles, merging styles, font handling, etc. One effect is that the current implementation violates the contract of equals() and hashCode(): equals() takes the range into account while hashCode() doesn’t. While that may not have an effect (StyleRanges with the same style just pile up in a hash map), it’s still a sign of a skewed API.

The API would be much more clean if there was a style manager (which you could dispose to free all fonts, colors, etc, at once) and when StyleRanges were just tiny classes that contain a range and a pointer to a style. That would allow to get rid of the ranges int array, we could use Set and List to manage style ranges, etc.

Something that I’ve been testing is hierarchical styles (i.e. styles that inherit from other styles). Works like in word processors where you define a basic style and then derive from that. I’m not happy with the performance right now but I’ve got some ideas.

How to use my version? Simple: Clone the StyledText project and install it. Check the POM to see which dependencies you need in your project. Now replace

import org.eclipse.swt.custom.*;

with

import de.pdark.styledtext.*;

That’s it.


When you’re right, there is no middle ground

15. January, 2010

Yesterday, I attended a talk by Tom Schindl (he’s the guy behind UFaceKit and Qooxdoo, QxWT, etc.) And he’s working on e4.

During our little conversation after the talk, he stressed the fact many people aren’t willing to pay for bugfixes in Eclipse. He’d be willing to work on many of them but someone has to pay the bills. I nodded like everyone else. And we talked about Eugene Ostroukhov and his complaint ““Participate in community!” they said…“. And I immediately saw a parallel in my own history. I had a similar, painful experience with Ed Merks a while ago. That was about EMF and how badly it sucks. And that he didn’t listen to me.

I was mad because I was right and he just didn’t get it.

Yesterday, on the train home, I understood.

I’d like to introduce two new categories of programmers. Both are passionate and enthusiastic about software. The difference is that one group is pragmatic and the other idealistic.

Ed and Tom are pragmatics. They think: “Great feature, I like it, how much will it cost?” If it’s too expensive, they don’t get upset. They think about it, mull it around, consider their options. If there just is no viable way to do it, they can accept that. These people get money to write software.

I’m an idealistic programmer. I get money to stop writing software. That is, I get money to stop writing the software in my head and to start writing the software someone else wants. Not getting what I envision drives me up the wall.

Things can get pretty ugly when those two kinds meet. Because both are egoistic and both are right. It would make sense to make all the changes to EMF that I want. For me and probably a few others. It would cause quite a few problems for Ed, though (mostly because he’d get a lot of complaints by those people who are happy right now).

I’m asking for changes because I have problems. I’m not complaining about petty things. I need to bend EMF and SWT more than the API allows. To solve my problems, I just can’t accept the status quo. The API has to move. But my solution would cause problems for many other people.

Right now, I’m writing software which doesn’t have a lot of customers, so a stable, reliable API is not one of my goals. I can change my API at a whim and no one bothers. Eclipse has millions of customers and every change to any API will cause a tremendous amount of pain around the globe. Say 0.1% have a problem now? That would be at least 1’000 people complaining. One happy, 1’000 after your head. At least. How big is the pressure on Ed to make me happy?

So how to win? I think Linux has the best solution that you can get today. Linux has several release streams that strive in parallel. It’s not a bunch of forks, it’s a bunch of branches. People can hand in stuff that really isn’t ready for prime time. It can be incomplete. It can break other APIs. It can be an experiment. It can evolve. In Linux, there is the next tree.

In Eclipse, evolution is hard. You have to get new features and patches past people you don’t know, who have more experience in evolving APIs, little time and little incentive to hurt themselves. API in Eclipse is hard to evolve because IBM pays many of the core developers. If someone wants some obscure API and the Lotus Notes team will have a problem with that, who will win? The bug report (even with a patch) or your next pay check? There are only a few big commercial products on Linux. Eclipse, OTOH, was created to form the basis for commercial products (hence the EPL). Products that have life cycles between five and ten years. Ten years ago, we had Linux 2.2, KDE 1.0 and SuSE 6.3.

For IBM and SAP, the one year release cycle of Eclipse is way too fast. They have to spend a lot of money on developers just to keep up with all the changes going on in Eclipse and this is for things that can’t be sold to customer (i.e. which don’t earn any money).

So I agree with Bjorn Freeman-Benson that Eclipse needs a set of public git repositories and a low-barrier entry to these repositories (which means one-click install for the build system, no IP checking). It should be a playground, a place where ideas can grow. Not all of them will make it into the mainstream but at least, people can solve their problems without hurting too many others.

At the same time, I’m afraid what will happen when this comes true. But then, I’m an idealistic programmer. I believe that time will tell who was right and that we shouldn’t bother too much upfront.


ePen 0.7

31. December, 2009

I’ve started to work on ePen again. This time, I’m using Java and SWT/JFace. Python Traits was nice but too slow for my purpose, especially the editor.

This is the main window. As you can see, there is an outline with all characters, places, items, wiki pages and books (with chapters and scenes). The whole thing is meant to save all the information in one place so you can easily find and use them.

Do you see all those nice links? The editor will create them for you from names of characters and other things. If you click on them, you’ll jump right to the meat. I’m thinking of a hover mode where you get a summary but there is a bug somewhere.

The other feature is: No save button. The editor will save your work as you type. If it crashes or your whole computer crashes or there is a power failure? No sweat. Worked for an hour and forgot to save? Won’t happen again. I’m still working on automated backups plus a client/server mode so you can have automatic off-site backups, too.

Right now, I’m shaving off a few rough edges. Then, I’ll drop it on sourceforge.

[EDIT] The project home page is at http://sourceforge.net/projects/epen/


SWT Tree and tooltips

26. December, 2009

If you need tooltips for elements in an SWT Tree or JFace TreeViewer, you had to jump through some hoops as Snippet 125 shows.

Since SWT/JFace 3.3, you should use a TreeViewer, a ColumnLabelProvider (which has all those cool getTooltip() methods) and this line of code:

ColumnViewerToolTipSupport.enableFor (viewer);

That’s it. There is a catch, though: The tooltip doesn’t wrap automatically. If you have long lines of text, you need commons-lang and this piece of code:

    private String wrap (String s)
    {
        StringBuilder buffer = new StringBuilder ();
        
        String delim = "";
        for (String line: s.trim ().split ("\n"))
        {
            buffer.append (delim);
            delim = "\n";
            buffer.append (WordUtils.wrap (line, 60, "\n", true));
        }
        
        return buffer.toString ();
    }

Note that this code is only necessary if you have several lines of text in the tooltip. For single long lines, WordUtils.wrap() alone is enough.

Link to the JFace snippet.


How to make Eclipse 3.5 work on gtk2 2.18

24. December, 2009

If you’re using Eclipse in Linux with gtk2, then you might have run into this issue: Buttons don’t work when you click on them, tree views are initially empty, icons are missing or not drawn correctly. To fix this, just run this command before you start Eclipse:

export GDK_NATIVE_WINDOWS=1

I suggest that you put it into a little wrapper script. With this option enabled, Eclipse works like it should, even on Linux/gtk.

It’s a good example of the pain when working with Eclipse developers: Everyone agrees that it’s a bug and it’s pretty clear what needs to be done. The fix apparently even exists and “just” needs to be copied from the 3.6 sources to 3.5. And nothing happens because the release process is so involved that it just takes too much time and the workaround (adding the line above or control Eclipse with the keyboard) is too simple.

I can’t say on which side I’m on here. I understand why nothing happens but it still freaks me out.


Traits for Groovy/Java

25. June, 2009

I’m again toying with the idea of traits for Java (or rather Groovy). Just to give you a rough idea if you haven’t heard about this before, think of my Sensei application template:

class Knowledge {
    Set tags;
    Knowledge parent;
    List children;
    String name;
    String content;
}
class Tag { String name; }
class Relation { String name; Knowledge from, to;

A most simple model but it contains everything you can encounter in an application: Parent-child/tree structure, 1:N and N:M mappings. Now the idea is to have a way to build a UI and a DB mapping from this code. The idea of traits is to implement real properties in Java.

So instead of fields with primitive types, you have real objects to work with:

    assert "name" == Knowledge.name.getName()

These objects exist partially at the class and at the instance level. There is static information at the class level (the name of the property) and there is instance information (the current value). But it should be possible to add more information at both levels. So a DB mapper can add necessary translation information to the class level and a Hibernate mapper can build on top of that.

Oh, I hear you cry “annotations!” But annotations can suck, too. You can’t have smart defaults with annotations. For example, you can’t say “I want all fields called ‘timestamp’ to be mapped with an java.sql.Timestamp“. You have to add the annotation to each timestamp field. That violates DRY. It quickly gets really bad when you have to do this for several mappers: Database, Hibernate, JPA, the UI, Swing, SWT, GWT. Suddenly, each property would need 10+ annotations!

I think I’ve found a solution which should need relatively few lines of code with Groovy. I’ll let that stew for a couple of days in by subconscious and post another article when it’s well done 🙂


Stop Auto-Scrolling in SWT When The User Grabs The Scrollbar

3. February, 2009

Imagine you have a console widget in an SWT app. The app is doing some background work and dumps lots of text in the console. Something catches the eye of the user and she desperately tries to keep it in view while the console jumps to the bottom all of the time. Here is a simple solution how to notice that the user has grabbed the scrollbar.

    private AtomicBoolean userHoldsScrollbar
                = new AtomicBoolean ();

        control.getVerticalBar ().addSelectionListener (new SelectionListener () {
            public void widgetDefaultSelected (SelectionEvent e)
            {
                // NOP
            }

            public void widgetSelected (SelectionEvent e)
            {
                if (e.detail == SWT.DRAG)
                    userHoldsScrollbar.set (true);
                else if (e.detail == SWT.NONE)
                    userHoldsScrollbar.set (false);
            }
        });

In your auto-scroll code, check whether userHoldsScrollbar.get() is true.