gef中编者图中添加背景图片原理以及实现

gef中编辑图中添加背景图片原理以及实现

  GEFRootEditPart对应的Figure是一个由多个Layer组成的LayeredPane,每个Layer负责包含不同类型的图形元素,如节点、连接、网格线等等。所以要让图形编辑器显示一个图片作为背景,可以在它们其中一个层里绘制这个图片,也可以添加一个层专门放置背景图片。gef中所有的图形元件继承自Figure类。实现背景色和背景图的更改的必须实现Figure中部分类。

由源代码:

 

/**用于绘制元件和元件内的子元件系列

 * Paints this Figure and its children.

 * @param graphics The Graphics object used for painting

 * @see #paintFigure(Graphics)

 * @see #paintClientArea(Graphics)

 * @see #paintBorder(Graphics)

 */

public void paint(Graphics graphics) {

    if (getLocalBackgroundColor() != null)

       graphics.setBackgroundColor(getLocalBackgroundColor());

    if (getLocalForegroundColor() != null)

       graphics.setForegroundColor(getLocalForegroundColor());

    if (font != null)

       graphics.setFont(font);

 

    graphics.pushState();

    try {

       paintFigure(graphics);

       graphics.restoreState();

       paintClientArea(graphics);

       paintBorder(graphics);

    } finally {

       graphics.popState();

    }

}

/**用于绘制边框border对象

 * Paints the border associated with this Figure, if one exists.

 * @param graphics The Graphics used to paint

 * @see Border#paint(IFigure, Graphics, Insets)

 * @since 2.0

 */

protected void paintBorder(Graphics graphics) {

    if (getBorder() != null)

       getBorder().paint(this, graphics, NO_INSETS);

}

/**用于绘制所有子元件对象

 * Paints this Figure's children. The caller must save the state of the graphics prior to

 * calling this method, such that <code>graphics.restoreState()</code> may be called

 * safely, and doing so will return the graphics to its original state when the method was

 * entered.

 * <P>

 * This method must leave the Graphics in its original state upon return.

 * @param graphics the graphics used to paint

 * @since 2.0

 */

protected void paintChildren(Graphics graphics) {

    IFigure child;

 

    Rectangle clip = Rectangle.SINGLETON;

    for (int i = 0; i < children.size(); i++) {

       child = (IFigure)children.get(i);

       if (child.isVisible() && child.intersects(graphics.getClip(clip))) {

           graphics.clipRect(child.getBounds());

           child.paint(graphics);

           graphics.restoreState();

       }

    }

}

/**绘制子元件区域对象

 * Paints this Figure's client area. The client area is typically defined as the anything

 * inside the Figure's {@link Border} or {@link Insets}, and by default includes the

 * children of this Figure. On return, this method must leave the given Graphics in its

 * initial state.

 * @param graphics The Graphics used to paint

 * @since 2.0

 */

protected void paintClientArea(Graphics graphics) {

    if (children.isEmpty())

       return;

 

    boolean optimizeClip = getBorder() == null || getBorder().isOpaque();

 

    if (useLocalCoordinates()) {

       graphics.translate(

           getBounds().x + getInsets().left,

           getBounds().y + getInsets().top);

       if (!optimizeClip)

           graphics.clipRect(getClientArea(PRIVATE_RECT));

       graphics.pushState();

       paintChildren(graphics);

       graphics.popState();

       graphics.restoreState();

    } else {

       if (optimizeClip)

           paintChildren(graphics);

       else {

           graphics.clipRect(getClientArea(PRIVATE_RECT));

           graphics.pushState();

           paintChildren(graphics);

           graphics.popState();

           graphics.restoreState();

       }

    }

}

/** 绘制元件的背景等信息

 * Paints this Figure's primary representation, or background. Changes made to the

 * graphics to the graphics current state will not affect the subsequent calls to {@link

 * #paintClientArea(Graphics)} and {@link #paintBorder(Graphics)}. Furthermore, it is safe

 * to call <code>graphics.restoreState()</code> within this method, and doing so will

 * restore the graphics to its original state upon entry.

 * @param graphics The Graphics used to paint

 * @since 2.0

 */

protected void paintFigure(Graphics graphics) {

    if (isOpaque())

       graphics.fillRectangle(getBounds());

    if (getBorder() instanceof AbstractBackground)

       ((AbstractBackground) getBorder()).paintBackground(this, graphics, NO_INSETS);

}

由上面的源代码可以看出:

 

   /**

    * 用来定制GraphicalViewer的各种信息

    * 在这两个方法里我们配置了RootEditPart、用于创建 EditPartEditPartFactory

    * ContentsDiagram对象和增加了拖放支持,拖动目标是当前 EditPartViewer,后面会看到拖动源就是调色板。

    */

   /**

    * 用来定制GraphicalViewer的各种信息

    * 在这两个方法里我们配置了RootEditPart、用于创建 EditPartEditPartFactory

    * ContentsDiagram对象和增加了拖放支持,拖动目标是当前 EditPartViewer,后面会看到拖动源就是调色板。

    */

   @Override

   protected void configureGraphicalViewer() {

      super.configureGraphicalViewer();

      //添加背景图片

      this.getGraphicalViewer().setRootEditPart(new ScalableFreeformRootEditPart(){

          //可以注入自己设定的层

      @Override      

      protected LayeredPane createPrintableLayers(){

          LayeredPane layeredPane= super.createPrintableLayers();

          layeredPane.add(new FreeformLayer(),PRIMARY_LAYER);

          //可以添加自定一的层layer接口定义

          layeredPane.add(new FreeformLayer(),CONNECTION_LAYER);

          return layeredPane;

      }

          //添加背景色和背景图

          @Override

          protected void createLayers(LayeredPane layeredPane) {

           Layer layer=new FreeformLayer(){

               protected