gef中编辑图中添加背景图片原理以及实现
? GEF的RootEditPart对应的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、用于创建 EditPart的EditPartFactory、
??? * Contents即Diagram对象和增加了拖放支持,拖动目标是当前 EditPartViewer,后面会看到拖动源就是调色板。
??? */
?? /**
??? * 用来定制GraphicalViewer的各种信息
??? * 在这两个方法里我们配置了RootEditPart、用于创建 EditPart的EditPartFactory、
??? * Contents即Diagram对象和增加了拖放支持,拖动目标是当前 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