-----------------------------------------------------------
本文系本站原创,欢迎转载!
转载请注明出处:http://sjj0412.cublog.cn/
-----------------------------------------------------------
gef是eclipse中图形绘制插件,它是基于draw2d,下面来看下它的机制
先看一个draw2d程序,
要有一个LightweightSystem,然后给这个LightweightSystem的setcontents函数传递一个figure,这个figure就是LightweightSystem的根figure了。
public static void main(String args[])
{
final Label label = new Label("Press a button!");
Shell shell = new Shell();
LightweightSystem lws = new LightweightSystem(shell);
Figure parent = new Figure();
parent.setLayoutManager(new XYLayout());
lws.setContents(parent);
Clickable above = new CheckBox("I'm above!");
parent.add(above, new Rectangle(10,10,80,20));
ButtonModel aModel = new ToggleModel();
aModel.addChangeListener(new ChangeListener()
{
public void handleStateChanged(ChangeEvent e)
{
label.setText("Above");
}
});
above.setModel(aModel);
Clickable below = new CheckBox("I'm below!");
parent.add(below, new Rectangle(10,40,80,20));
ButtonModel bModel = new ToggleModel();
bModel.addChangeListener(new ChangeListener()
{
public void handleStateChanged(ChangeEvent e)
{
label.setText("Below");
}
});
below.setModel(bModel);
ButtonGroup bGroup = new ButtonGroup();
bGroup.add(aModel);
bGroup.add(bModel);
bGroup.setDefault(bModel);
parent.add(label, new Rectangle(10,70,80,20));
shell.setSize(130,120);
shell.open();
shell.setText("Example");
Display display = Display.getDefault();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep ();
}
那在gef中如何实现上面这一个过程的呢。
public abstract class GraphicalEditor
extends EditorPart
implements CommandStackListener, ISelectionListener
{
public void createPartControl(Composite parent) {
createGraphicalViewer(parent);
}
protected void createGraphicalViewer(Composite parent) {
GraphicalViewer viewer = new ScrollingGraphicalViewer();
viewer.createControl(parent);
setGraphicalViewer(viewer);
configureGraphicalViewer();
hookGraphicalViewer();
initializeGraphicalViewer();
}
ScrollingGraphicalViewer的createControl,完成lws和composite的关联。
public final Control createControl(Composite parent) {
FigureCanvas canvas = new FigureCanvas(parent, getLightweightSystem());
setControl(canvas);
installRootFigure();
return canvas;
}
protected LightweightSystem getLightweightSystem() {
return lws;
}
private final LightweightSystem lws = createLightweightSystem();
这样就创建一个LightweightSystem了,并和composite关联了。
那LightweightSystem得setcontents在哪呢:
在installRootFigure这个函数:
private void installRootFigure() {
if (getFigureCanvas() == null)
return;
if (rootFigure instanceof Viewport)
getFigureCanvas().setViewport((Viewport)rootFigure);
else
getFigureCanvas().setContents(rootFigure);
}
public void setViewport(Viewport vp) {
if (viewport != null)
unhookViewport();
viewport = vp;
lws.setContents(viewport);
hookViewport();
}
也就是说viewport就是rootifigure.
那这个rootfigure是哪来的呢:
这个是在GraphicalViewer创建时就创建了;
Rootfigure是RootEditPart的createfigure创建的。
GraphicalViewer继承GraphicalViewerImpl
public GraphicalViewerImpl () {
createDefaultRoot();
setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.NONE),
MouseWheelDelegateHandler.SINGLETON);
}
protected void createDefaultRoot() {
setRootEditPart(new ScalableRootEditPart());
}
public void setRootEditPart(RootEditPart editpart) {
super.setRootEditPart(editpart);
setRootFigure(((GraphicalEditPart)editpart).getFigure());
}
protected void setRootFigure(IFigure figure) {
rootFigure = figure;
getLightweightSystem().setContents(rootFigure);
}
当然GraphicalViewer的rooteditpart可以通过setrooteditpart函数改。
public void setRootEditPart(RootEditPart editpart) {
super.setRootEditPart(editpart);
setRootFigure(((GraphicalEditPart)editpart).getFigure());
}
public void setRootEditPart(RootEditPart editpart) {
if (rootEditPart != null) {
if (rootEditPart.isActive())
rootEditPart.deactivate();
rootEditPart.setViewer(null);
}
rootEditPart = editpart;
rootEditPart.setViewer(this);
if (getControl() != null)
rootEditPart.activate();
}
protected void setRootFigure(IFigure figure) {
rootFigure = figure;
getLightweightSystem().setContents(rootFigure);
}
当然设置后会覆盖原来的。
比如我们使用:
getGraphicalViewer().setRootEditPart(rooteditpart);
到此LightweightSystem的构建完成,关键是怎么往rootfigure加其他figure了。这个就是GraphicalViewer的setcontens的作用。
public void setContents(Object contents) {
Assert.isTrue(getEditPartFactory() != null,
"An EditPartFactory is required to call setContents(Object)");//$NON-NLS-1$
setContents(getEditPartFactory().
createEditPart(null, contents));
}
public void setContents(EditPart editpart) {
getRootEditPart().setContents(editpart);
}
下面这个是rooteditpart的setcontents.
public void setContents(EditPart editpart) {
if (contents == editpart)
return;
if (contents != null)
removeChild(contents);
contents = editpart;
//只能有一个contents.
if (contents != null)
addChild(contents, 0);
//注意这个0,表示contentsfigure在最上面。
}
这样就添加了,也就是说contentfigure是rootfigure的child.
比如我们使用:
getGraphicalViewer().setContents(this.diagram);
然后contentmodel的childemode对应的editpart的figure如何添加到contentfigue的呢?
当这Contentfigure(一个Layer)的载体contentseditpart的model添加一个child时就要通知
Contenteditpart,然后Contenteditpart执行refreshchildren;
protected void refreshChildren() {
int i;
EditPart editPart;
Object model;
Map modelToEditPart = new HashMap();
List children = getChildren();
for (i = 0; i < children.size(); i++) {
editPart = (EditPart)children.get(i);
modelToEditPart.put(editPart.getModel(), editPart);
}
List modelObjects = getModelChildren();
for (i = 0; i < modelObjects.size(); i++) {
model = modelObjects.get(i);
//Do a quick check to see if editPart[i] == model[i]
if (i < children.size()
&& ((EditPart) children.get(i)).getModel() == model)
continue;
//Look to see if the EditPart is already around but in the wrong location
editPart = (EditPart)modelToEditPart.get(model);
if (editPart != null)
reorderChild (editPart, i);
else {
//An editpart for this model doesn't exist yet. Create and insert one.
editPart = createChild(model);
//
addChild(editPart, i);
}
}
List trash = new ArrayList();
for (; i < children.size(); i++)
trash.add(children.get(i));
for (i = 0; i < trash.size(); i++) {
EditPart ep = (EditPart)trash.get(i);
removeChild(ep);
}
}
protected EditPart createChild(Object model) {
return getViewer().getEditPartFactory().createEditPart(this, model);
}
protected void addChild(EditPart child, int index) {
Assert.isNotNull(child);
if (index == -1)
index = getChildren().size();
if (children == null)
children = new ArrayList(2);
children.add(index, child);
child.setParent(this);
addChildVisual(child, index);
child.addNotify();
if (isActive())
child.activate();
fireChildAdded(child, index);
}
protected void addChildVisual(EditPart childEditPart, int index) {
IFigure child = ((GraphicalEditPart)childEditPart).getFigure();
//getfigure会调用createfigure。
getContentPane().add(child, index);
}
public IFigure getContentPane() {
return getFigure();
}
这样就把一个child添加到primary layer里。
到此完成了所有editpart的figure。
Rooteditpart的figure是一个ScalableRootEditPart
public ScalableRootEditPart() {
zoomManager =
new ZoomManager((ScalableLayeredPane)getScaledLayers(), ((Viewport)getFigure()));
}
/**
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
*/
protected IFigure createFigure() {
Viewport viewport = createViewport();
innerLayers = new LayeredPane();
createLayers(innerLayers);
viewport.setContents(innerLayers);
return viewport;
}
public void setContents(IFigure figure) {
if (view == figure)
return;
if (view != null)
remove(view);
view = figure;
if (view != null)
add(figure);
}
protected void createLayers(LayeredPane layeredPane) {
layeredPane.add(getScaledLayers(), SCALABLE_LAYERS);
layeredPane.add(new Layer() {
public Dimension getPreferredSize(int wHint, int hHint) {
return new Dimension();
}
}, HANDLE_LAYER);
layeredPane.add(new FeedbackLayer(), FEEDBACK_LAYER);
layeredPane.add(new GuideLayer(), GUIDE_LAYER);
}
然后inerlayer添加了EEDBACK_LAYER等层。
其实在lightwigetsystem里,layer就是composite(所有figure都是)的感觉,只不过它是透明的,即没有背景色,而Label这些不行。
Contenteditpart就是一个layer.
protected IFigure createFigure() {
// TODO Auto-generated method stub
Layer figure = new Layer();
figure.setLayoutManager(new XYLayout());
return figure;
}
下面说下画图系统的各个层关系:
rootEditPart的figure是viewport,下面:
Class FreeformGraphicalRootEditPart:
protected IFigure createFigure() {
FreeformViewport viewport = new FreeformViewport();
innerLayers = new FreeformLayeredPane();
createLayers(innerLayers);
viewport.setContents(innerLayers);
return viewport;
}
protected void createLayers(LayeredPane layeredPane) {
layeredPane.add(getScaledLayers(), SCALABLE_LAYERS);
layeredPane.add(new FreeformLayer(), HANDLE_LAYER);
layeredPane.add(new FeedbackLayer(), FEEDBACK_LAYER);
layeredPane.add(new GuideLayer(), GUIDE_LAYER);
}
protected ScalableFreeformLayeredPane createScaledLayers() {
ScalableFreeformLayeredPane layers = new ScalableFreeformLayeredPane();
layers.add(createGridLayer(), GRID_LAYER);
layers.add(getPrintableLayers(), PRINTABLE_LAYERS);
layers.add(new FeedbackLayer(), SCALED_FEEDBACK_LAYER);
return layers;
}
所以viewport添加了innerLayers,而其又添加几个层。
PRINTABLE_LAYERS,GRID_LAYER, SCALED_FEEDBACK_LAYER
PRINTABLE_LAYERS又:
protected LayeredPane getPrintableLayers() {
if (printableLayers == null)<span lang="EN-US" style="font-size:10.0pt; font-family%3