gef图形显示机制

来源:互联网 发布:模拟基金软件推荐 编辑:程序博客网 时间:2024/05/21 00:17

-----------------------------------------------------------
本文系本站原创,欢迎转载!

转载请注明出处:http://sjj0412.cublog.cn/

-----------------------------------------------------------

gef是eclipse中图形绘制插件,它是基于draw2d,下面来看下它的机制

先看一个draw2d程序,

要有一个LightweightSystem,然后给这个LightweightSystemsetcontents函数传递一个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();

}

ScrollingGraphicalViewercreateControl,完成lwscomposite的关联。

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关联了。

LightweightSystemsetcontents在哪呢:

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创建时就创建了;

RootfigureRootEditPartcreatefigure创建的。

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);

}

 

当然GraphicalViewerrooteditpart可以通过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了。这个就是GraphicalViewersetcontens的作用。

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);

}

下面这个是rooteditpartsetcontents.

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在最上面。

}

这样就添加了,也就是说contentfigurerootfigurechild.

比如我们使用:

  getGraphicalViewer().setContents(this.diagram);

 

然后contentmodelchildemode对应的editpartfigure如何添加到contentfigue的呢?

当这Contentfigure(一个Layer)的载体contentseditpartmodel添加一个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里。

到此完成了所有editpartfigure

Rooteditpartfigure是一个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;                                                                                                            

    }

 

下面说下画图系统的各个层关系:

rootEditPartfigureviewport,下面:

 

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_LAYERSGRID_LAYER, SCALED_FEEDBACK_LAYER

PRINTABLE_LAYERS又:

 

 protected LayeredPane getPrintableLayers() {

    if (printableLayers == null)<span lang="EN-US" style="font-size:10.0pt; font-family%3