Thamwo QuickCompressor

Werbung
Tutorial
Graphical Editor
Rich Client Platform
Original
Thamwo QuickCompressor
Alle Beispiele sind mit eclipse version keppler erstellt und getestet worden. Die Lizensbestimmungen
von eclipse werden durch dieses Buch nicht in Frage gestellt. Kopie und Verwendung von Quellcode
und Text geschieht auf eigene Gefahr. Jede Gewährleistung wird ausgeschlossen.
Fehler in den Quellcodes und in den Texten können nicht ausgeschlossen werden. Für die Richtigkeit
besteht keinerlei Gewähr.
Copyright© 2014, thamwo
[2]
Thamwo QuickCompressor
Inhalt
Einführung ............................................................................................................................................... 4
Eclipse .................................................................................................................................................. 4
Rich Client Platform (RCP) ................................................................................................................... 4
Quick Graphical Editor............................................................................................................................. 5
Beschreibung ....................................................................................................................................... 5
Package mygef..................................................................................................................................... 7
Package editor ..................................................................................................................................... 8
Package model .................................................................................................................................. 13
Package factory ................................................................................................................................. 18
Package picture ................................................................................................................................. 20
Package rectangle.............................................................................................................................. 22
Package commands ........................................................................................................................... 26
Package tree ...................................................................................................................................... 28
MANIFEST.MF .................................................................................................................................... 31
plugin.xml .......................................................................................................................................... 32
Ergänzung weiterer Elemente ........................................................................................................... 34
[3]
Thamwo QuickCompressor
Einführung
Eclipse
Eclipse ist ein Framework, welches für die verschiedensten Umgebungen eine speziell angepasste
Umgebung liefert, kurz eine DIE.
IDE – Integrated Development Environment
Aber Eclipse ist keine IDE, sondern ein Framework, dh. ein Werkzeugkasten für verschieden
Anwendungen. Eine davon ist das Integrated Development Environment (IDE). Eine weiter ist eine
Umgebung zur Erstellung eigener Anwendungen, auch Application genannt. Diese Umgebung ist die
RCP – Rich Client Platform
Die Komponenten dieser Rich Client Platform sind durch das Framework vorgegeben und sind wie
folgt definiert.
Workbench – ist ein Fenster/Window mit verschiedenen Elementen
Rich Client Platform (RCP)
Die Rich Client Platform, kurz RCP, ist eine Bezeichnung für ein Produkt, welches auf Eclipse basiert.
Applikationen können aus Eclipse als RCP exportiert werden. Damit wird eine auslieferbare,
transportable Version erzeugt, welche dann zum Beispiel auf einem PC installiert werden kann.
[4]
Thamwo QuickCompressor
Quick Graphical Editor
Beschreibung
In diesem Tutorial wird ein graphischer Editor unter GEF implementiert. Im Editorbereich können
Rechtecke erzeugt und gelöscht werden. Im ContentOutline View wird ein Tree mit den Namen der
Rechtecke angezeigt. Durch Doppelklick auf das Element im Tree oder im Editorbereich wird das
Property Sheet geöffnet und der Name des Elements kann geändert werden.
Alle Funktionen sind vollständig als Beispiel in den Packages abgelegt. So befinden sich unter mygef
der Code der Perspektive. Im Package editor sind die Sourcen für die Editorfunktionen zu finden. Das
Packages model beinhalten die Sourcen für Abstrakte, während unter factory die Beispiele für
Elemente zusammengeführt werden. Schließlich folgen unter picture und rectangle die konkreten
Beispiele für die Realisierung von Zeichenelementen. Zuletzt kommen Kommandos und der Code für
den TreeViewer im ContentOutline View.
Nun folgt eine kurze Anweisung für die Erstellung des Projektes:
1. Anlegen einen neuen leeren Projektes als RCP als mygef
2. Einfügen der folgenden Packages unter Dependencies (via Add Button Required Plug Ins):
org.eclipse.gef
org.eclipse.draw2d
3. Einfügen der folgenden Packages unter Dependencies (via Add Button Imported Packages):
[5]
Thamwo QuickCompressor
org.eclipse.views.contentoutline
org.eclipse.views.properties
4. Anlegen der folgenden Packages unter src:
mygef (wurde beim Anlegen des Projektes automatisch erzeugt)
editor
model
factory
picture
rectangle
commands
tree
5. Erzeugen der folgenden Packages mit den beinhalteten Klassen. Alle Sourcen sind vollständig
und bilden zusammen das gesamte Projekt.
Alternativ ist das Projekt als Zip-File abgelegt und kann so unter Downloads gefunden werden.
[6]
Thamwo QuickCompressor
Package mygef
Im package mygef befindet sich die RCP Applikation. Für den graphischen Editor muss lediglich eine
Klasse geändert werden. Diese teilt der Applikation mit welche Views angelegt werden sollen und
wie der EditorPart behandelt werden soll.
Perspective.java
package mygef;
import org.eclipse.ui.IFolderLayout;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;
public class Perspective implements IPerspectiveFactory {
private static final String ID_TABS_FOLDER = "folder";
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(true);
IFolderLayout tabs = layout.createFolder(ID_TABS_FOLDER, IPageLayout.LEFT,
0.3f, editorArea);
/********************************************/
/*
Outline und Property Sheet
*/
/********************************************/
tabs.addView(IPageLayout.ID_OUTLINE);
tabs.addPlaceholder(IPageLayout.ID_PROP_SHEET);
}
}
[7]
Thamwo QuickCompressor
Package editor
Nun kommen die Grundlagen für den Editor. Diese bestehen aus drei Komponenten. Dem Input für
die Definition des Editorinhalts. Dem eigentlichen Editor für die Definition der Editorfunktionen und
der Definiton der ActionBar.
MyEditorInput.java
package editor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IPersistableElement;
public class MyEditorInput implements IEditorInput {
public String name = null;
public MyEditorInput(String name) {
this.name = name;
}
@Override
public boolean exists() {
return (this.name != null);
}
public boolean equals(Object o) {
if (!(o instanceof MyEditorInput))
return false;
return ((MyEditorInput)o).getName().equals(getName());
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageDescriptor.getMissingImageDescriptor();
}
@Override
public String getName() {
return this.name;
}
@Override
public IPersistableElement getPersistable() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getToolTipText() {
return this.name;
}
@Override
public Object getAdapter(Class adapter) {
// TODO Auto-generated method stub
return null;
}
}
[8]
Thamwo QuickCompressor
Der eigentliche Editor startet einen Graphical Viewer zur Darstellung der graphischen Elemente.
Optional wurde die Funktion ZOOM und SELECTION unter configureGraphicalViewer hinzugefügt.
Ferner wurde, wie in der Perspektive vorbereitet, der View ContentOutline definiert. Diese besteht
aus einem Treeviewer und einer Miniatur.
In getPaletteRoot wird die Palette definiert, die die Werkzeuge für die graphische Bearbeitung
anbietet.
MyGraphicalEditor.java
package editor;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.util.ArrayList;
org.eclipse.core.runtime.IProgressMonitor;
org.eclipse.draw2d.LightweightSystem;
org.eclipse.draw2d.Viewport;
org.eclipse.draw2d.parts.ScrollableThumbnail;
org.eclipse.gef.DefaultEditDomain;
org.eclipse.gef.GraphicalViewer;
org.eclipse.gef.LayerConstants;
org.eclipse.gef.editparts.ScalableRootEditPart;
org.eclipse.gef.editparts.ZoomManager;
org.eclipse.gef.palette.CreationToolEntry;
org.eclipse.gef.palette.MarqueeToolEntry;
org.eclipse.gef.palette.PaletteGroup;
org.eclipse.gef.palette.PaletteRoot;
org.eclipse.gef.palette.PaletteSeparator;
org.eclipse.gef.palette.SelectionToolEntry;
org.eclipse.gef.ui.actions.ZoomInAction;
org.eclipse.gef.ui.actions.ZoomOutAction;
org.eclipse.gef.ui.parts.ContentOutlinePage;
org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
org.eclipse.gef.ui.parts.TreeViewer;
org.eclipse.jface.viewers.ISelectionChangedListener;
org.eclipse.jface.viewers.SelectionChangedEvent;
org.eclipse.swt.SWT;
org.eclipse.swt.custom.SashForm;
org.eclipse.swt.events.DisposeEvent;
org.eclipse.swt.events.DisposeListener;
org.eclipse.swt.graphics.GC;
org.eclipse.swt.graphics.Image;
org.eclipse.swt.graphics.ImageData;
org.eclipse.swt.graphics.ImageLoader;
org.eclipse.swt.widgets.Canvas;
org.eclipse.swt.widgets.Composite;
org.eclipse.swt.widgets.Control;
org.eclipse.ui.IEditorPart;
org.eclipse.ui.views.contentoutline.IContentOutlinePage;
factory.MyEditPartFactory;
factory.ElementCreationFactory;
picture.Picture;
rectangle.RectElement;
tree.TreeEditPartFactory;
public class MyGraphicalEditor extends GraphicalEditorWithPalette {
public static final String ID = "grapheditid";
private Picture picFrame;
private boolean dirty;
public MyGraphicalEditor() {
setEditDomain(new DefaultEditDomain(this));
dirty = true;
}
[9]
Thamwo QuickCompressor
protected void configureGraphicalViewer() {
double[] zoomLevels;
ArrayList<String> zoomContributions;
super.configureGraphicalViewer();
GraphicalViewer viewer = getGraphicalViewer();
viewer.setEditPartFactory(new MyEditPartFactory());
/********************************************/
/*
ZOOM
*/
/********************************************/
ScalableRootEditPart rootEditPart = new ScalableRootEditPart();
viewer.setRootEditPart(rootEditPart);
ZoomManager manager = rootEditPart.getZoomManager();
getActionRegistry().registerAction(new ZoomInAction(manager));
getActionRegistry().registerAction(new ZoomOutAction(manager));
zoomLevels = new double[] {0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0,
10.0, 20.0};
manager.setZoomLevels(zoomLevels);
zoomContributions = new ArrayList<String>();
zoomContributions.add(ZoomManager.FIT_ALL);
zoomContributions.add(ZoomManager.FIT_HEIGHT);
zoomContributions.add(ZoomManager.FIT_WIDTH);
manager.setZoomLevelContributions(zoomContributions);
/********************************************/
/*
Selection
*/
/********************************************/
viewer.addSelectionChangedListener(new ISelectionChangedListener
() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
System.out.println ("Selection");
}
});
}
@Override
public void doSave(IProgressMonitor monitor) {
GraphicalViewer viewer = getGraphicalViewer();
GC gc = new GC(viewer.getControl());
Image image = new Image(viewer.getControl().getDisplay(), viewer
.getControl().getSize().x, viewer.getControl().getSize().y);
gc.copyArea(image, 0, 0);
ImageLoader loader = new ImageLoader();
loader.data = new ImageData[] { image.getImageData() };
loader.save("d:/user/pic.bmp", SWT.IMAGE_BMP);
gc.dispose();
System.out.println("Save");
dirty = false;
firePropertyChange(IEditorPart.PROP_DIRTY);
}
/****************************************************/
/*
org.eclipse.gef.ui.parts.ContentOutlinePage
*/
/****************************************************/
public class OverviewContentPage extends ContentOutlinePage {
private
private
private
private
SashForm sash;
ScrollableThumbnail thumbnail;
DisposeListener disposeListener;
GraphicalViewer viewer;
public OverviewContentPage() {
super (new TreeViewer ());
}
@Override
public void createControl(Composite parent) {
sash = new SashForm(parent, SWT.VERTICAL);
[10]
Thamwo QuickCompressor
/********************************************/
/*
org.eclipse.gef.ui.parts.TreeViewer
*/
/********************************************/
getViewer().createControl(sash);
getViewer().setEditDomain(getEditDomain());
getViewer().setEditPartFactory(new TreeEditPartFactory());
getViewer().setContents(picFrame);
getSelectionSynchronizer().addViewer(getViewer());
/********************************************/
/*
Miniatur
*/
/********************************************/
Canvas canvas = new Canvas(sash, SWT.BORDER);
LightweightSystem lws = new LightweightSystem(canvas);
thumbnail = new ScrollableThumbnail((Viewport) ((ScalableRootEditPart)
getGraphicalViewer().getRootEditPart()).getFigure());
thumbnail.setSource(((ScalableRootEditPart)
getGraphicalViewer().getRootEditPart()).getLayer(LayerConstant
s.PRINTABLE_LAYERS));
lws.setContents(thumbnail);
disposeListener = new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (thumbnail != null) {
thumbnail.deactivate();
thumbnail = null;
}
}
};
getGraphicalViewer().getControl().addDisposeListener(disposeListener);
}
@Override
public void dispose() {
if(viewer != null) {
if (viewer.getControl() != null && !viewer.getControl().isDisposed())
viewer.getControl().removeDisposeListener(disposeListener);
super.dispose();
}
}
@Override
public Control getControl() {
return sash;
}
}
@Override
protected PaletteRoot getPaletteRoot() {
PaletteRoot root = new PaletteRoot();
PaletteGroup manipGroup = new PaletteGroup("Work");
root.add(manipGroup);
SelectionToolEntry selectionToolEntry = new SelectionToolEntry();
manipGroup.add(selectionToolEntry);
manipGroup.add(new MarqueeToolEntry());
PaletteSeparator sep2 = new PaletteSeparator();
root.add(sep2);
PaletteGroup instGroup = new PaletteGroup("Create new elements");
root.add(instGroup);
instGroup.add(new CreationToolEntry("Rectangle", "Create new rectangle",
new ElementCreationFactory(RectElement.class), null, null));
root.setDefaultEntry(selectionToolEntry);
return root;
}
[11]
Thamwo QuickCompressor
public
void setDirty () {
dirty = true;
firePropertyChange(IEditorPart.PROP_DIRTY);
}
@Override
public boolean isDirty () {
return dirty;
}
public Picture CreatePicture(){
picFrame = new Picture();
picFrame.setName("Picture");
return picFrame;
}
protected void initializeGraphicalViewer() {
GraphicalViewer viewer = getGraphicalViewer();
viewer.setContents(CreatePicture());
}
@Override
public Object getAdapter(Class type) {
if(type == IContentOutlinePage.class) return new
OverviewContentPage(/*getGraphicalViewer()*/);
if (type == ZoomManager.class) return ((ScalableRootEditPart)
getGraphicalViewer().getRootEditPart()).getZoomManager();
return super.getAdapter(type);
}
}
Korrespondierend zum Editor warden die Controls in der ActionBar eingerichtet.
MyGraphicalEditorActionBarContributor.java
package editor;
import
import
import
import
import
import
import
import
import
org.eclipse.gef.ui.actions.ActionBarContributor;
org.eclipse.gef.ui.actions.DeleteRetargetAction;
org.eclipse.gef.ui.actions.GEFActionConstants;
org.eclipse.gef.ui.actions.ZoomComboContributionItem;
org.eclipse.gef.ui.actions.ZoomInRetargetAction;
org.eclipse.gef.ui.actions.ZoomOutRetargetAction;
org.eclipse.jface.action.IToolBarManager;
org.eclipse.jface.action.Separator;
org.eclipse.ui.actions.ActionFactory;
public class MyGraphicalEditorActionBarContributor extends ActionBarContributor {
@Override
protected void buildActions() {
addRetargetAction(new ZoomInRetargetAction());
addRetargetAction(new ZoomOutRetargetAction());
addRetargetAction(new DeleteRetargetAction());
}
public void contributeToToolBar(IToolBarManager toolBarManager) {
toolBarManager.add(new Separator());
toolBarManager.add(getAction(GEFActionConstants.ZOOM_IN));
toolBarManager.add(getAction(GEFActionConstants.ZOOM_OUT));
toolBarManager.add(new ZoomComboContributionItem(getPage()));
toolBarManager.add(getAction(ActionFactory.DELETE.getId()));
}
@Override
[12]
Thamwo QuickCompressor
protected void declareGlobalActionKeys() {}
}
Package model
Als nächstes muss das Modell festgelegt werden. Dieses besteht aus einem Root Element und dessen
rekursiven Children. Dafür wird zunächst ein abstraktes Element definiert. Dazu muss noch das
abstrakte Layout und der abstrakte EditPart definiert werden. Optional kann ein Property Sheet
ergänzt werden, wie es schon in der Perspektive vorgeleistet wurde.
Das eigentliche Root Element wird erst später unter Picture festgelegt. Es ist eine einfache Instanz
des abstrakten Elements.
AbstractElement.java
package model;
import
import
import
import
import
import
import
import
import
import
import
java.beans.PropertyChangeListener;
java.beans.PropertyChangeSupport;
java.util.ArrayList;
java.util.List;
org.eclipse.core.runtime.IAdaptable;
org.eclipse.draw2d.geometry.Rectangle;
org.eclipse.ui.IEditorPart;
org.eclipse.ui.PlatformUI;
org.eclipse.ui.views.properties.*;
rectangle.RectElement;
editor.MyGraphicalEditor;
public class AbstractElement implements IAdaptable {
private String name;
private Rectangle layout;
private List<AbstractElement> children;
private AbstractElement parent;
private PropertyChangeSupport listeners;
public static final String PROPERTY_LAYOUT = "NodeLayout";
public static final String PROPERTY_NAME = "NODE";
public static final String PROPERTY_ADD = "NodeAddChild";
public static final String PROPERTY_REMOVE = "NodeRemoveChild";
private IPropertySource propertySource = null;
public AbstractElement(){
this.name = "Unknown";
this.layout = new Rectangle(10, 10, 100, 100);
this.children = new ArrayList<AbstractElement>();
[13]
Thamwo QuickCompressor
this.parent = null;
this.listeners = new PropertyChangeSupport(this);
}
public PropertyChangeSupport getListeners() {
return listeners;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
listeners.removePropertyChangeListener(listener);
}
public void setName(String name) {
String oldName = null;
this.name = name;
getListeners().firePropertyChange(PROPERTY_NAME, oldName, name);
}
public String getName() {
return this.name;
}
public void setLayout(Rectangle newLayout) {
Rectangle oldLayout = this.layout;
this.layout = newLayout;
getListeners().firePropertyChange(PROPERTY_LAYOUT, oldLayout, newLayout);
IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().
getActivePage().getActiveEditor();
((MyGraphicalEditor) editor).setDirty ();
}
public Rectangle getLayout() {
return this.layout;
}
public boolean addChild(AbstractElement child) {
boolean b = this.children.add(child);
if (b) {
child.setParent(this);
getListeners().firePropertyChange(PROPERTY_ADD, null, child);
}
return b;
}
public boolean removeChild(AbstractElement child) {
boolean b = this.children.remove(child);
if (b)
getListeners().firePropertyChange(PROPERTY_REMOVE, child, null);
IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().
getActivePage().getActiveEditor();
((MyGraphicalEditor) editor).setDirty ();
return b;
}
public List<AbstractElement> getChildrenArray() {
return this.children;
}
public void setParent(AbstractElement parent) {
this.parent = parent;
}
public AbstractElement getParent() {
return this.parent;
}
public boolean contains(RectElement child) {
return children.contains(child);
}
/********************************************/
[14]
Thamwo QuickCompressor
/*
Property Sheet
*/
/********************************************/
@Override
public Object getAdapter(Class adapter) {
if (adapter == IPropertySource.class) {
if (propertySource == null)
propertySource = new AbstractElementPropertySource(this);
return propertySource;
}
return null;
}
}
AbstractLayoutCommand.java
package model;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.commands.Command;
public abstract class AbstractLayoutCommand extends Command
public abstract void setConstraint(Rectangle rect);
public abstract void setModel(Object model);
}
{
In AbstractEditPart wird das Property Sheet behandelt. Beim Doppelklick wird der entsprechende
View geöffnet. Außerdem werden die Listerner gestartet, damit Änderungen jeweils an die anderen
Bereiche mitgeteilt.
AbstractEditPart.java
package model;
import
import
import
import
import
import
import
import
java.beans.PropertyChangeListener;
org.eclipse.gef.Request;
org.eclipse.gef.RequestConstants;
org.eclipse.gef.editparts.AbstractGraphicalEditPart;
org.eclipse.ui.IPageLayout;
org.eclipse.ui.IWorkbenchPage;
org.eclipse.ui.PartInitException;
org.eclipse.ui.PlatformUI;
public abstract class AbstractEditPart extends AbstractGraphicalEditPart implements
PropertyChangeListener {
/********************************************/
/*
Listener for Property Sheet
*/
/********************************************/
public void activate() {
super.activate();
((AbstractElement) getModel()).addPropertyChangeListener(this);
}
public void deactivate() {
super.deactivate();
((AbstractElement) getModel()).removePropertyChangeListener(this);
}
/********************************************/
/*
Open Property Sheet (douple click) */
/********************************************/
@Override
public void performRequest(Request req) {
if (req.getType().equals(RequestConstants.REQ_OPEN)) {
try {
[15]
Thamwo QuickCompressor
IWorkbenchPage page = PlatformUI.getWorkbench().
getActiveWorkbenchWindow().getActivePage();
page.showView(IPageLayout.ID_PROP_SHEET);
}
catch (PartInitException e) {
e.printStackTrace();
}
}
}
}
Nun wird der Inhalt des Property Sheets festgelegt. Es wird bestimmt, welche Properties angezeigt
werden und welche editierbar sind.
AbstractElementPropertySource.java
package model;
import
import
import
import
import
import
import
java.util.ArrayList;
org.eclipse.ui.views.properties.IPropertyDescriptor;
org.eclipse.ui.views.properties.IPropertySource;
org.eclipse.ui.views.properties.PropertyDescriptor;
org.eclipse.ui.views.properties.TextPropertyDescriptor;
picture.Picture;
rectangle.RectElement;
public class AbstractElementPropertySource implements IPropertySource {
private AbstractElement element;
public AbstractElementPropertySource(AbstractElement node) {
this.element = node;
}
@Override
public Object getEditableValue() { return null; }
@Override
public IPropertyDescriptor[] getPropertyDescriptors() {
ArrayList<IPropertyDescriptor> properties = new ArrayList<IPropertyDescriptor>();
if (element instanceof Picture)
properties.add(new PropertyDescriptor(RectElement.PROPERTY_NAME, "Name"));
if (element instanceof RectElement) {
// editable TextPropertyDescriptor
properties.add(new TextPropertyDescriptor(RectElement.PROPERTY_NAME, "Name"));
// not editable PropertyDescriptor
properties.add(new PropertyDescriptor(RectElement.PROPERTY_ATTR, "Attribut"));
}
return properties.toArray(new IPropertyDescriptor[0]);
}
@Override
public Object getPropertyValue(Object id) {
if (id.equals(RectElement.PROPERTY_NAME)) return element.getName();
if (id.equals(RectElement.PROPERTY_ATTR)) return ((RectElement) element).getAttr();
return null;
}
@Override
public boolean isPropertySet(Object id) { return false; }
@Override
[16]
Thamwo QuickCompressor
public void resetPropertyValue(Object id) {
}
@Override
public void setPropertyValue(Object id, Object value) {
if (id.equals(RectElement.PROPERTY_NAME)) element.setName((String)value);
if (id.equals(RectElement.PROPERTY_ATTR)) ((RectElement) element)
.setAttr((String)value);
}
}
[17]
Thamwo QuickCompressor
Package factory
Nachdem das abstrakte Element, Layout und EditPart definiert wurden müssen alle konkreten
Variationen in Factories behandelt werden. Dafür gibt es eine LayoutPolicy, eine
ElementCreationFactory und eine MyEditPartFactory.
LayoutPolicy.java
package factory;
import
import
import
import
import
import
import
import
import
import
import
model.AbstractLayoutCommand;
org.eclipse.draw2d.geometry.Rectangle;
org.eclipse.gef.EditPart;
org.eclipse.gef.commands.Command;
org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
org.eclipse.gef.requests.CreateRequest;
picture.PicturePart;
rectangle.RectMoveCommand;
rectangle.RectCreateCommand;
rectangle.RectFigure;
rectangle.RectPart;
public class LayoutPolicy extends XYLayoutEditPolicy {
/********************************************/
/*
Move Element/Rectangel
*/
/********************************************/
@Override
protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
AbstractLayoutCommand command = null;
if (child instanceof RectPart) {
command = new RectMoveCommand();
}
command.setModel(child.getModel());
command.setConstraint((Rectangle)constraint);
return command;
}
/********************************************/
/*
Create Element
*/
/********************************************/
@Override
protected Command getCreateCommand(CreateRequest request) {
if (request.getType() == REQ_CREATE && getHost() instanceof PicturePart)
{
/*
Create Rectangle
*/
RectCreateCommand cmd = new RectCreateCommand();
cmd.setFrame(getHost().getModel());
cmd.setNode(request.getNewObject());
Rectangle constraint = (Rectangle)getConstraintFor(request);
constraint.x = (constraint.x < 0) ? 0 : constraint.x;
constraint.y = (constraint.y < 0) ? 0 : constraint.y;
constraint.width = (constraint.width <= 0) ?
RectFigure.SERVICE_FIGURE_DEFWIDTH : constraint.width;
constraint.height = (constraint.height <= 0) ?
RectFigure.SERVICE_FIGURE_DEFHEIGHT : constraint.height;
cmd.setLayout(constraint);
return cmd;
}
return null;
}
}
[18]
Thamwo QuickCompressor
ElementCreationFactory.java
package factory;
import org.eclipse.gef.requests.CreationFactory;
import rectangle.RectElement;
public class ElementCreationFactory implements CreationFactory
{
private Class<?> template;
public ElementCreationFactory(Class<?> t) {
this.template = t;
}
@Override
public Object getNewObject() {
if (template == null)
return null;
if (template == RectElement.class)
{
RectElement element = new RectElement();
element.setName("Element");
System.out.println("New Child");
return element;
}
return null;
}
@Override
public Object getObjectType() {
return template;
}
}
MyEditPartFactory.java
package factory;
import
import
import
import
import
import
import
org.eclipse.gef.EditPart;
org.eclipse.gef.EditPartFactory;
org.eclipse.gef.editparts.AbstractGraphicalEditPart;
picture.Picture;
picture.PicturePart;
rectangle.RectElement;
rectangle.RectPart;
public class MyEditPartFactory implements EditPartFactory {
@Override
public EditPart createEditPart(EditPart context, Object model) {
AbstractGraphicalEditPart part = null;
if (model instanceof Picture) {
part = new PicturePart();
} else if (model instanceof RectElement) {
part = new RectPart();
}
part.setModel(model);
return part;
[19]
Thamwo QuickCompressor
}
}
Package picture
Nun kommt das Root Element. Hier heißt es einfach Picture.
Picture.java
package picture;
import model.AbstractElement;
public class Picture extends AbstractElement {}
PictureFigure.java
package picture;
import
import
import
import
import
import
org.eclipse.draw2d.ColorConstants;
org.eclipse.draw2d.Figure;
org.eclipse.draw2d.Label;
org.eclipse.draw2d.LineBorder;
org.eclipse.draw2d.XYLayout;
org.eclipse.draw2d.geometry.Rectangle;
public class PictureFigure extends Figure {
private Label labelName = new Label();
private XYLayout layout;
public PictureFigure() {
layout = new XYLayout();
setLayoutManager(layout);
labelName.setForegroundColor(ColorConstants.blue);
add(labelName);
setConstraint(labelName, new Rectangle(5, 5, -1, -1));
setForegroundColor(ColorConstants.black);
setBorder(new LineBorder(5));
}
public void setLayout(Rectangle rect) {
setBounds(rect);
}
public void setName(String text) {
labelName.setText(text);
}
}
PicturePart.java
package picture;
import
import
import
import
import
import
import
import
java.beans.PropertyChangeEvent;
java.util.List;
model.AbstractElement;
model.AbstractEditPart;
org.eclipse.draw2d.IFigure;
org.eclipse.gef.EditPolicy;
rectangle.RectElement;
factory.LayoutPolicy;
[20]
Thamwo QuickCompressor
public class PicturePart extends AbstractEditPart {
@Override
protected IFigure createFigure() {
IFigure figure = new PictureFigure();
return figure;
}
@Override
protected void createEditPolicies() {
installEditPolicy(EditPolicy.LAYOUT_ROLE, new LayoutPolicy());
}
protected void refreshVisuals(){
PictureFigure figure = (PictureFigure)getFigure();
Picture model = (Picture)getModel();
figure.setName(model.getName());
}
public List<AbstractElement> getModelChildren() {
return ((Picture)getModel()).getChildrenArray();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(RectElement.PROPERTY_LAYOUT))
refreshVisuals();
if (evt.getPropertyName().equals(RectElement.PROPERTY_ADD))
refreshChildren();
if (evt.getPropertyName().equals(RectElement.PROPERTY_REMOVE))
refreshChildren();
if (evt.getPropertyName().equals(RectElement.PROPERTY_NAME))
refreshChildren();
}
}
[21]
Thamwo QuickCompressor
Package rectangle
Ein weiteres konkretes Element ist das Rechteck. Analog zu Picture gibt es eine Definition, ein Layout
und einen EditPart. Ergänzend kommen zwei Kommandos hinzu, um ein Rechteck hinzuzufügen und
zu bewegen.
RectElement.java
package rectangle;
import model.AbstractElement;
public class RectElement extends AbstractElement {
public static final String PROPERTY_ATTR = "ATTRIBUT";
private String attribut;
public RectElement(){
this.attribut = "Unknown";
}
public String getAttr() {
return this.attribut;
}
public void setAttr(String attribut) {
this.attribut = attribut;
}
}
RectFigure.java
package rectangle;
import
import
import
import
import
import
import
import
org.eclipse.draw2d.ColorConstants;
org.eclipse.draw2d.Figure;
org.eclipse.draw2d.Label;
org.eclipse.draw2d.LineBorder;
org.eclipse.draw2d.ToolbarLayout;
org.eclipse.draw2d.XYLayout;
org.eclipse.draw2d.geometry.Rectangle;
org.eclipse.swt.graphics.Color;
public class RectFigure extends Figure {
private Label labelName = new Label();
public static final int SERVICE_FIGURE_DEFWIDTH = 250;
public static final int SERVICE_FIGURE_DEFHEIGHT = 150;
public RectFigure() {
XYLayout layout = new XYLayout();
setLayoutManager(layout);
labelName.setForegroundColor(ColorConstants.darkGray);
add(labelName, ToolbarLayout.ALIGN_CENTER);
setConstraint(labelName, new Rectangle(5, 17, -1, -1));
/** Random color **/
setForegroundColor(new Color(null, (new Double(Math.random() *
128)).intValue() ,(new Double(Math.random() * 128)).intValue(),
(new Double(Math.random() * 128)).intValue()));
setBackgroundColor(new Color(null, (new Double(Math.random() *
128)).intValue() + 128 , (new Double(Math.random() * 128))
.intValue() + 128 , (new Double(Math.random() * 128))
.intValue() + 128 ));
setBorder(new LineBorder(1));
setOpaque(true);
[22]
Thamwo QuickCompressor
}
public void setName(String text) {
labelName.setText(text);
}
public void setLayout(Rectangle rect) {
getParent().setConstraint(this, rect);
}
}
RectPart.java
package rectangle;
import
import
import
import
import
import
import
import
import
import
import
java.beans.PropertyChangeEvent;
java.util.List;
model.AbstractElement;
model.AbstractEditPart;
org.eclipse.draw2d.IFigure;
org.eclipse.gef.EditPolicy;
org.eclipse.ui.IEditorPart;
org.eclipse.ui.PlatformUI;
commands.DeletePolicy;
editor.MyGraphicalEditor;
factory.LayoutPolicy;
public class RectPart extends AbstractEditPart {
@Override
protected IFigure createFigure() {
IFigure figure = new RectFigure();
IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage().getActiveEditor();
((MyGraphicalEditor) editor).setDirty ();
return figure;
}
@Override
protected void createEditPolicies() {
installEditPolicy(EditPolicy.LAYOUT_ROLE, new LayoutPolicy());
installEditPolicy(EditPolicy.COMPONENT_ROLE,new DeletePolicy());
}
protected void refreshVisuals(){
RectFigure figure = (RectFigure)getFigure();
RectElement model = (RectElement)getModel();
figure.setName(model.getName());
figure.setLayout(model.getLayout());
}
public List<AbstractElement> getModelChildren() {
return ((RectElement)getModel()).getChildrenArray();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(RectElement.PROPERTY_LAYOUT))
refreshVisuals();
if (evt.getPropertyName().equals(AbstractElement.PROPERTY_NAME))
refreshVisuals();
}
}
RectCreateCommand.java
[23]
Thamwo QuickCompressor
package rectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.commands.Command;
import picture.Picture;
public class RectCreateCommand extends Command {
private Picture fr;
private RectElement nd;
public RectCreateCommand() {
super();
fr = null;
nd = null;
}
public void setNode(Object s) {
if (s instanceof RectElement){
this.nd = (RectElement)s;
}
}
public void setFrame(Object e) {
if (e instanceof Picture){
this.fr = (Picture)e;
}
}
public void setLayout(Rectangle r) {
if (nd == null)
return;
nd.setLayout(r);
}
@Override
public boolean canExecute() {
if (nd == null || fr == null)
return false;
return true;
}
@Override
public void execute() {
fr.addChild(nd);
}
@Override
public boolean canUndo() {
if (fr == null || nd == null)
return false;
return fr.contains(nd);
}
@Override
public void undo() {
fr.removeChild(nd);
}
}
RectMoveCommand.java
package rectangle;
import model.AbstractLayoutCommand;
import org.eclipse.draw2d.geometry.Rectangle;
/********************************************/
/*
Move Rectangle
*/
/********************************************/
[24]
Thamwo QuickCompressor
public class RectMoveCommand extends AbstractLayoutCommand {
private RectElement model;
private Rectangle layout;
public void execute() {
model.setLayout(layout);
}
public void setConstraint(Rectangle rect) {
this.layout = rect;
}
public void setModel(Object model) {
this.model = (RectElement)model;
}
}
[25]
Thamwo QuickCompressor
Package commands
Damit ist der graphische Editor fertig. Rechtecke können zum Bild hinzugefügt und wieder gelöscht
werden. Der Name des Rechtecks kann im Property Sheet geändert werden. Die folgenden Packages
ergänzen den Editor, sind aber nicht erforderlich.
newHandler.java
package commands;
import
import
import
import
import
import
import
org.eclipse.core.commands.ExecutionEvent;
org.eclipse.core.commands.ExecutionException;
org.eclipse.core.commands.AbstractHandler;
org.eclipse.ui.IWorkbenchPage;
org.eclipse.ui.PlatformUI;
editor.MyEditorInput;
editor.MyGraphicalEditor;
public class newHandler extends AbstractHandler {
public newHandler () {}
public Object execute(ExecutionEvent event) throws ExecutionException {
try {
IWorkbenchPage page =
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
page.openEditor(new MyEditorInput("Mygef"), MyGraphicalEditor.ID, false);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
DeleteCommand.java
package commands;
import model.AbstractElement;
import org.eclipse.gef.commands.Command;
public class DeleteCommand extends Command {
private AbstractElement model;
private AbstractElement parentModel;
public void execute() {
this.parentModel.removeChild(model);
}
public void setModel(Object model) {
this.model = (AbstractElement)model;
}
public void setParentModel(Object model) {
parentModel = (AbstractElement)model;
}
public void undo() {
this.parentModel.addChild(model);
}
}
[26]
Thamwo QuickCompressor
DeletePolicy.java
package commands;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.ComponentEditPolicy;
import org.eclipse.gef.requests.GroupRequest;
public class DeletePolicy extends ComponentEditPolicy {
protected Command createDeleteCommand(GroupRequest deleteRequest) {
DeleteCommand command = new DeleteCommand();
command.setModel(getHost().getModel());
command.setParentModel(getHost().getParent().getModel());
return command;
}
}
[27]
Thamwo QuickCompressor
Package tree
Durch die folgenden vier Klassen wird im ContentOutline View ein Tree angezeigt, in dem alle
Children des Root Elements Picture angezeigt werden. Durch Doppelklick auf ein Element wird das
entsprechende Rechteck im Editorbereich ausgewählt und das dazugehörige Property Sheet geöffnet.
MyAbstractTreeEditPart.java
package tree;
import
import
import
import
import
import
import
import
import
import
import
java.beans.PropertyChangeListener;
model.AbstractElement;
org.eclipse.gef.DragTracker;
org.eclipse.gef.Request;
org.eclipse.gef.RequestConstants;
org.eclipse.gef.editparts.AbstractTreeEditPart;
org.eclipse.gef.tools.SelectEditPartTracker;
org.eclipse.ui.IPageLayout;
org.eclipse.ui.IWorkbenchPage;
org.eclipse.ui.PartInitException;
org.eclipse.ui.PlatformUI;
public abstract class MyAbstractTreeEditPart extends AbstractTreeEditPart implements
PropertyChangeListener {
/********************************************/
/*
Listener for Property Sheet
*/
/********************************************/
public void activate() {
super.activate();
((AbstractElement) getModel()).addPropertyChangeListener(this);
}
public void deactivate() {
((AbstractElement) getModel()).removePropertyChangeListener(this);
super.deactivate();
}
@Override
public DragTracker getDragTracker(Request req) {
return new SelectEditPartTracker(this);
}
/********************************************/
/*
Open Property Sheet (douple click) */
/********************************************/
@Override
public void performRequest(Request req) {
if (req.getType().equals(RequestConstants.REQ_OPEN)) {
try {
IWorkbenchPage page = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
page.showView(IPageLayout.ID_PROP_SHEET);
}
catch (PartInitException e) {
e.printStackTrace();
}
}
}
}
TreeEditPartFactory.java
package tree;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
[28]
Thamwo QuickCompressor
import rectangle.RectElement;
import picture.Picture;
public class TreeEditPartFactory implements EditPartFactory {
@Override
public EditPart createEditPart(EditPart context, Object model) {
EditPart part = null;
if (model instanceof Picture)
part = new PictureTreeEditPart();
else if (model instanceof RectElement)
part = new RectTreeEditPart();
if (part != null)
part.setModel(model);
return part;
}
}
PictureTreeEditPart.java
package tree;
import
import
import
import
java.beans.PropertyChangeEvent;
model.AbstractElement;
picture.Picture;
java.util.List;
public class PictureTreeEditPart extends MyAbstractTreeEditPart {
protected List<AbstractElement> getModelChildren() {
return ((Picture)getModel()).getChildrenArray();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(AbstractElement.PROPERTY_ADD))
refreshChildren();
if(evt.getPropertyName().equals(AbstractElement.PROPERTY_REMOVE))
refreshChildren();
if(evt.getPropertyName().equals(AbstractElement.PROPERTY_NAME))
refreshChildren();
}
}
RectTreeEditPart.java
package tree;
import
import
import
import
import
import
import
import
java.beans.PropertyChangeEvent;
model.AbstractElement;
rectangle.RectElement;
java.util.List;
org.eclipse.gef.EditPolicy;
org.eclipse.ui.ISharedImages;
org.eclipse.ui.PlatformUI;
commands.DeletePolicy;
public class RectTreeEditPart extends MyAbstractTreeEditPart {
protected List<AbstractElement> getModelChildren() {
return ((RectElement)getModel()).getChildrenArray();
}
@Override
protected void createEditPolicies() {
[29]
Thamwo QuickCompressor
installEditPolicy(EditPolicy.COMPONENT_ROLE,new DeletePolicy());
}
public void refreshVisuals(){
RectElement model = (RectElement)getModel();
setWidgetText(model.getName());
System.out.println(model.getName());
setWidgetImage(PlatformUI.getWorkbench().getSharedImages()
.getImage(ISharedImages.IMG_DEF_VIEW));
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals(AbstractElement.PROPERTY_ADD))
refreshChildren();
if(evt.getPropertyName().equals(AbstractElement.PROPERTY_REMOVE))
refreshChildren();
if(evt.getPropertyName().equals(AbstractElement.PROPERTY_NAME))
refreshVisuals();
}
}
[30]
Thamwo QuickCompressor
MANIFEST.MF
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Mygef
Bundle-SymbolicName: mygef;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: mygef.Activator
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.gef;bundle-version="3.9.0",
org.eclipse.draw2d
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Import-Package: org.eclipse.ui.views.contentoutline,
org.eclipse.ui.views.properties
[31]
Thamwo QuickCompressor
plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension
id="application"
point="org.eclipse.core.runtime.applications">
<application>
<run
class="mygef.Application">
</run>
</application>
</extension>
<extension
point="org.eclipse.ui.perspectives">
<perspective
name="RCP Perspective"
class="mygef.Perspective"
id="mygef.perspective">
</perspective>
</extension>
<extension
point="org.eclipse.ui.editors">
<editor
class="editor.MyGraphicalEditor"
contributorClass="editor.MyGraphicalEditorActionBarContributor"
default="true"
id="grapheditid"
name="mygraphedit">
</editor>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
id="newid"
name="newfile">
</command>
<command
id="saveid"
name="savefile">
</command>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="commands.newHandler"
commandId="newid">
</handler>
</extension>
<extension
point="org.eclipse.ui.menus">
<menuContribution
allPopups="false"
locationURI="menu:org.eclipse.ui.main.menu">
<menu
commandId="newid"
id="menuid"
label="File">
<command
commandId="newid"
id="ncomid"
label="New"
style="push">
</command>
<command
commandId="org.eclipse.ui.file.save"
id="scomid"
label="Save"
style="push">
</command>
[32]
Thamwo QuickCompressor
</menu>
</menuContribution>
<menuContribution
allPopups="false"
locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
<toolbar
id="mygef.toolbar"
label="op">
<command
commandId="newid"
icon="icons/alt_window_16.gif"
id="New"
style="push">
</command>
<command
commandId="org.eclipse.ui.file.save"
label="Save"
style="push">
</command>
</toolbar>
</menuContribution>
</extension>
</plugin>
[33]
Thamwo QuickCompressor
Ergänzung weiterer Elemente
1. Anlegen eines Packages, z.B. triangle
2. Erzeugen von 5 Klassen analog wie unter rectangle
3. Ergänzen von triangle in allen Klassen unter factory
Uns schon ist ein weiteres Element verfügbar.
[34]
Thamwo QuickCompressor
Von der leeren RCP mit View zum Jpeg Compressor
Dieses Turorial zeigt auf, wie mit Eclipse eine kleine Anwendung erstellt
werden kann. Die Rich Client Platform wird als Aufsetzpunkt gewählt, um
einen simplen graphischen Editor zu erstellen.
Grundlage ist hier GEF. Somit ist diese Tutorial auch ein ausgezeichneter
Einstieg in die Programmierung mit dieser Umgebung.
[35]
Herunterladen