Sorting Property Sheet Entries

The easiest way I've figured out to do this is by modifying the PropertySheetEntry used for your page.

The GEF Setup

GEF supplies a custom PropertySheetEntry called UndoablePropertySheetEntry, and you can just subclass it. This is significantly easier than the straight Eclipse version, because Eclipse's PropertySheetEntry defines createChildEntries() as PRIVATE; you cannot override it. The GEF UndoablePropertySheetEntry defines it as PROTECTED.

(Note: See my "Rules of Reuse" article at http://www.javadude.com/articles for why private methods are evil. This is a prime example of a great place to override, killed by a method being made private).

First, define your subclass. It overrides:

getDisplayName()
removes colon-based prefixes before returning the name to display
createChildEntry()
tells the property sheet entry logic to use instances of your subclass so any kid entries sort the same way
(hooray for the factory method pattern!)

Figure 1: CustomSortPropertySheetEntry

import org.eclipse.gef.commands.CommandStack;

import org.eclipse.gef.internal.ui.properties.UndoablePropertySheetEntry;



/**

 * Overridden to allow specific ordering of properties.

 * Order can be forced by prepending text followed by a ':'

 * for example:

 * 

 * a1:id

 * a2:x

 * a3:y

 * a4:width

 * a5:height

 * 

 * forces the above order.

 * 

 * When the name is displayed, the getDisplayName method removes the prefix.

 * 

 * Any number of colons maybe used, for example:

 * 

 * bean:property:x

 * bean:eventset:action

 * bean:property:y

 * 

 * (not a real, applicable example, but it gets the idea across)

 * 

 */



public class CustomSortPropertySheetEntry extends UndoablePropertySheetEntry {

    public CustomSortPropertySheetEntry() {}

    public CustomSortPropertySheetEntry(CommandStack stack) {

        super(stack);

    }



    protected PropertySheetEntry createChildEntry() {

        return new CustomSortPropertySheetEntry();

    }

    

    public String getDisplayName() {

        String displayName = super.getDisplayName();

        int colon = displayName.lastIndexOf(':');

        if (colon != -1)

            displayName = displayName.substring(colon + 1);

        return displayName;

    }

}

You then install this in your getAdapter() for whatever you need to display (like an editor's content)

Figure 2: Sample getAdapter()

public Object getAdapter(Class type) {

    if (type == IPropertySheetPage.class) {

        PropertySheetPage page = new PropertySheetPage();

        page.setRootEntry(new CustomSortPropertySheetEntry(getCommandStack()));

        return page;

    }

    return super.getAdapter(type);

}

The Non-GEF Setup

[I've entered feature request 24694 for putting createChildEntry() in Eclipse's PropertySheetEntry the same way they do in GEF's UndoablePropertySheetEntry -- that'll make the non-GEF version much simpler]

If you can't/don't want to use GEF, you must create your own PropertySheetEntry class to do this function. The easiest way to do this is to copy Eclipse's PropertySheetEntry and inside its createChildEntries() method REPLACE the following line

Figure 3: Creating property sheet entry

PropertySheetEntry entry = new PropertySheetEntry(); 

with a creation of your own class

Figure 4: Creating custom sort property sheet entry

CustomSortPropertySheetEntry entry = new CustomSortPropertySheetEntry(); 

You install this the same way you would use the GEF version.

Doing your custom sort

Now all you need to do is prefix your property descriptor display names to set up the sort order. For example, if you want the order to be

Figure 5: Fields in the order you want

id

x

y

width

height

then you can use

Figure 6: Prefixed property descriptor entries

a1:id

a2:x

a3:y

a4:width

a5:height

as the actual display names of the property descriptors. The PropertySheetEntry will perform a sort on the display names, but call (your overridden) getDisplayName() which chops the prefix before it's actually displayed.