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!)
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)
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
PropertySheetEntry entry = new PropertySheetEntry();
with a creation of your own class
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
id x y width height
then you can use
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.