Source code for this tutorial is available on googlecode as a single zip archive, as a Team Project Set or you can checkout the SVN projects directly.
Preparations: Initial project
As a starting point I use a simple view with a TreeViewer. You can grab the initial source from my repository.
Run the plug-in com.example.decorators as an eclipse application and activate the Code & Me/Decorator Sample View to see that everything works.
Step 1: A simple icon decorator
To add an overlay icon decorator open you plugin.xml file and switch to the Extensions tab. Add a new extension of type org.eclipse.ui.decorators. The decorator needs its unique id and a nice label.
Decorators may be enabled/disabled by the user through Preferences/General/Appearance/Label Decorations. The state flag indicates the initial enablement of our decorator.
Set lightweight to true as we have a declarative decorator. Finally provide an icon and a location where the icon should be placed regarding the base image. Unfortunately you cannot use platform:/plugin/... style paths for your icon until bug 232171 is resolved. Instead you have to copy it to your own plug-in. The icon should be exactly 7x8 pixels (for overlays).
As you run your application you can see that your decorator is applied to the Project Explorer (if you created any projects there) but not to our sample view. To enable decorators within a viewer we need to adapt the LabelProvider. Open SampleView.java and change createPartControl to:
@Override public void createPartControl(Composite parent) { TreeViewer treeViewer = new TreeViewer(parent, SWT.BORDER); tree = treeViewer.getTree(); treeViewer.setContentProvider(new SampleTreeContentProvider()); SampleTreeLabelProvider baseLabelprovider = new SampleTreeLabelProvider(); ILabelDecorator decorator = PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator(); treeViewer.setLabelProvider(new DecoratingLabelProvider(baseLabelprovider, decorator)); ...
Run your application again to see the decorator in action.
Step 2: Enablements for decorators
Our decorator will be visible for all viewers in our RCP. Typically that is not what we want. To bind a decorator to certain types we use enablements. To bind our decorator to String objects within viewers we can use:
<extension point="org.eclipse.ui.decorators"> <decorator icon="images/warning_ovr.gif" id="com.example.decorators.decorator" label="Demo decorator" lightweight="true" location="TOP_RIGHT" state="true"> <enablement> <objectClass name="java.lang.String"> </objectClass> </enablement> </decorator> </extension>I am sure you will create more powerful enablements than I did.
Step 3: Text decorations
If we want to add text to viewer elements (like the team provider plug-ins do) we need to create an implementation of ILightweightLabelDecorator. Create a new class com.example.decorators.DemoDecorator
package com.example.decorators; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ILightweightLabelDecorator; public class DemoDecorator implements ILightweightLabelDecorator { @Override public void decorate(Object element, IDecoration decoration) { decoration.addSuffix(" [decorated]"); } @Override public void addListener(ILabelProviderListener listener) { } @Override public void dispose() { // nothing to do } @Override public boolean isLabelProperty(Object element, String property) { return false; } @Override public void removeListener(ILabelProviderListener listener) { } }and add the class to your decorator definition in plugin.xml. When you run your code you will see the suffix added to each element in our sample view. Unfortunately the overlay image is gone. By providing a class taking care of the decoration our declarative parameters will not be honored anymore.
To get back our overlay, we need to add it programmatically by adding/updating our decorator:
private static final ImageDescriptor WARNING; static { WARNING = AbstractUIPlugin.imageDescriptorFromPlugin("com.example.decorators", "images/warning_ovr.gif"); } @Override public void decorate(Object element, IDecoration decoration) { decoration.addSuffix(" [decorated]"); decoration.addOverlay(WARNING, IDecoration.BOTTOM_RIGHT); }
Alternatively you could extend LightWeightDecorator, a default implementation of an ILightweightLabelDecorator that honors delarative image settings. Get it from my repository, it is available under EPL.
Step 4: Text decorations with different color
Our text suffix is rendered using the same color as the main text. If you remove the decorator enablement, you can see that the decorated text looks differently in the Project Explorer. The color used can be adjusted in Preferences/General/Appearance/Colors and Fonts under Basic/Decoration color.
To achieve the same behavior we need to use the same code as NavigatorDecoratingLabelProvider. Unfortunately it is an internal class, so access is discouraged. Our best option is to copy over the code and put it into our own class. Create a new class DecoratedLabelProvider and copy over the code from NavigatorDecoratingLabelProvider. Do not forget to adjust the name of the constructor.
Afterwards we can use our new provider in our SampleView:
@Override public void createPartControl(Composite parent) { TreeViewer treeViewer = new TreeViewer(parent, SWT.BORDER); tree = treeViewer.getTree(); treeViewer.setContentProvider(new SampleTreeContentProvider()); SampleTreeLabelProvider baseLabelprovider = new SampleTreeLabelProvider(); ILabelDecorator decorator = PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator(); treeViewer.setLabelProvider(new DecoratedLabelProvider(baseLabelprovider));
Step 5: Using custom colors & fonts
To add custom colors to our main label text we can extend SampleTreeLabelProvider and implement IColorProvider (code contains only the changed parts):
public class SampleTreeLabelProvider extends LabelProvider implements IColorProvider{ @Override public Color getForeground(Object element) { return Display.getDefault().getSystemColor(SWT.COLOR_DARK_BLUE); } @Override public Color getBackground(Object element) { return Display.getDefault().getSystemColor(SWT.COLOR_YELLOW); }
For custom fonts let SampleTreeLabelProvider implement IFontProvider:
public class SampleTreeLabelProvider extends LabelProvider implements IFontProvider{ @Override public Font getFont(Object element) { return new Font(Display.getDefault(), new FontData("Arial", 12, SWT.BOLD)); } }You have to use DecoratedLabelProvider to make custom fonts and colors visible.
Remember to use registries for frequently used system resources like fonts or colors.
Further reading
Check out Understanding Decorators in Eclipse and the FAQ topics.
Amazing ! This is cool!
ReplyDeleteOther good articles on Jface Tree Viewer –
ReplyDeletehttp://www.vogella.com/articles/EclipseJFaceTree/article.html
http://www.buggybread.com/2013/11/java-jface-treeviewer-steps-to-create.html
http://www.programcreek.com/java-api-examples/index.php?api=org.eclipse.jface.viewers.TreeViewer