1       GEF辅助功能
 
 
在图形编辑区,有时需要借助标尺和网格的功能来定位图形的位置。对于标尺和网格GEF都提供了相应的实现,可以通过学习Gef自带的logic例子来学习。如何预览GEF自带的例子,方法很简单,在现有项目中new一个Flow/Logic/Shapes Diagram文件,双击该文件即可的得到Example的演示。如果想对查看其源码,活在在实例上做二次开发,这可以选择下图中的“Gef(Graphical Editing Framework) Plug-ins”来创建一个插件项目,其运行与一般插件项目完全相同。
 

 

GEF企业应用开发之--辅助功能_休闲

 

 
在调度系统中,需要用到类似标尺的功能,节纵坐标来表示泊位,纵坐标表示预计靠泊日期,或许你现在对这些也去概念有些迷惑,不用着急,本文描述的方法适合一般的添加标尺的方法。或者你可以看一下本节的末截图,即可了解横纵坐标的含义。
本文修改了GEF自带的Ruler组件,并放到了“org.jport.gef.component.rulers”包中,你可以在随书的源码中找到对应的源码。
第一步:在model中定义ruler属性
 

package org.jport.gef.berth.model;
import org.eclipse.draw2d.PositionConstants;
public class DiagramModel extends BaseModel{
    private BaseRuler leftRuler, topRuler;
    // 标尺是否可见
    private boolean rulersVisibility = true;
    //return ruler type
    public BaseRuler getRuler(int orientation) {
       BaseRuler result = null;
       switch (orientation) {
           case PositionConstants.NORTH :
              if(topRuler==null)
              topRuler = new BaseRuler(true);
              result = topRuler;
              break;
           case PositionConstants.WEST :
              if(leftRuler==null)
              leftRuler=new BaseRuler(false);
              result = leftRuler;
              break;
       }
       return result;
    }
    public boolean getRulerVisibility() {
       return rulersVisibility;
    }
    public void setRulerVisibility(boolean newValue) {
       rulersVisibility = newValue;
    }
    public BaseRuler getTopRuler() {
       return topRuler;
    }
 
    public void setTopRuler(BaseRuler topRuler) {
       this.topRuler = topRuler;
    }
}

在BerthGraphicalEditor中添加标尺支持:

// 定义标尺
    private JportRulerComposite rulerComp;
@Override
    protected void createGraphicalViewer(Composite parent) {
       rulerComp = new JportRulerComposite(parent, SWT.NONE);
       super.createGraphicalViewer(rulerComp);
       rulerComp
              .setGraphicalViewer((ScrollingGraphicalViewer) getGraphicalViewer());
    }
protected Control getGraphicalControl() {
       return rulerComp;
    }

在BerthGraphicalEditor配置Ruler:
 

 protected void loadProperties() {
       // BerthUtil.CURRENt_COMPANY=getCompanyId();
       BaseRuler ruler = getModel().getRuler(PositionConstants.WEST);
       RulerProvider provider = null;
       if (ruler != null) {
           provider = new BerthRulerProvider(ruler);
       }
    getGraphicalViewer().setProperty(RulerProvider.PROPERTY_VERTICAL_RULER,
              provider);
       ruler = getModel().getRuler(PositionConstants.NORTH);
       provider = null;
       if (ruler != null) {
           provider = new BerthRulerProvider(ruler);
       }
       getGraphicalViewer().setProperty(
              RulerProvider.PROPERTY_HORIZONTAL_RULER, provider);
       getGraphicalViewer().setProperty(
              RulerProvider.PROPERTY_RULER_VISIBILITY,
              new Boolean(getModel().getRulerVisibility()));
…………
}

在本例中对标尺的实现作了修改,通过个性化配置了标尺,具体配置如下:
 

 /**
 * 泊位标尺
 * @param graphics 绘图对象
 * @param dotsPerDivision 放缩比例,在目前的方法实现中并没有使用
 */
private void drawBerthLine(Graphics graphics,double dotsPerDivision) {
    // TODO Auto-generated method stub
    int berthSum=0;
    //画线的位置*放缩比例d
    int drawLine_x=0;
   
    List<Berth> berthList=DataService.getInstances().getBerthList();
    for(Berth berth:berthList)
    {
       drawLine_x=berthSum+berth.getBerthLenth();
              graphics.setForegroundColor(ColorConstants.red);
       graphics.drawLine(drawLine_x,10,drawLine_x,45);
      
       int midPos=berthSum+(drawLine_x-berthSum)/2;
       //在泊位中点画出泊位的名称
       drawText(graphics,berth.getBerthName(),midPos,10);
       berthSum=drawLine_x;
        
    }
}

GEF自带ruler实现:
 

GEF企业应用开发之--辅助功能_ruler_02 

JPort定义的ruler实现:
 
GEF企业应用开发之--辅助功能_ruler_03
 
在绘图工具中Zoom是不可或缺的功能,在GEF中添加Zoom功能,只需在Editor中做简单的配置即可。但是要实现工具条上的按钮的放缩按钮稍微麻烦一点。
添加缩放功能:

protected void configureGraphicalViewer() {
       ScalableRootEditPart root = new ScalableRootEditPart();
       // all the figure attach to this root have the zoom ablity
       double[] zoomLevels = new double[] { 0.25, 0.5, 0.75, 1.0, 1.25, 1.5,1.75, 2.0, 2.5, 2.5, 10 };
       root.getZoomManager().setZoomLevels(zoomLevels);
       IAction zoomIn = new ZoomInAction(root.getZoomManager());
       IAction zoomOut = new ZoomOutAction(root.getZoomManager());
       getActionRegistry().registerAction(zoomIn);
       getActionRegistry().registerAction(zoomOut);
       getSite().getKeyBindingService().registerAction(zoomIn);
       getSite().getKeyBindingService().registerAction(zoomOut);
……
    }
 
public Object getAdapter(Class type) {
        if (type == ZoomManager.class)
           return ((ScalableRootEditPart) getGraphicalViewer()
                  .getRootEditPart()).getZoomManager();
……
}

配置“contributorClass”,在contributorClass创建了在工具栏上显示的工具按钮。

<extension
         point="org.eclipse.ui.editors">
      <editor
            class="org.jport.gef.berth.ui.BerthGraphicalEditor"
            contributorClass="org.jport.gef.berth.action.DiagramActionBarContributor"
            default="true"
            icon="icons/sample.gif"
            id="org.jport.gef.berth.ui.BerthGraphicalEditor"
            name="泊位调度">
      </editor>
   </extension>

类DiagramActionBarContributor的具体实现,请参照随书源码。
注意要能让工具条显示,在“ApplicationWorkbenchWindowAdvisor”中设置

@Override
    public void preWindowOpen() {
       IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
       configurer.setInitialSize(new Point(400, 300));
   //要让工具栏显示,应设为true
       configurer.setShowCoolBar(true);
       configurer.setShowStatusLine(false);
       configurer.setTitle("GEF 企业应用");
    }

 

GEF企业应用开发之--辅助功能_zoom _04

此时再运行project,在工具条上可以看到放缩按钮和放缩比例下拉框,如上图所示,并且通过ctrl+鼠标滚轮可是实现放缩功能。
 
在BerthGraphicalEditor中定义OutlinePage,
 

// 定义大纲视图
    public OutlinePage outlinePage;

由于OutlinePage使用到了BerthGraphicalEditor中的许多属性,作为单独的类提出来要传递大量的参数,所以做成了是一个内部类。
 

public class OutlinePage extends ContentOutlinePage implements IAdaptable {
       // 用Logic example 的现实方式,把outline和oview放到pageBook中显示
       private PageBook pageBook;
       //大纲视图类
       private Control outline;
       //用来显示缩微图的画布
       private Canvas overview;
       // 缩微图实现类
       private Thumbnail thumbnail;
……
}

与overview不同,需要告诉Outline如何来显示所绘图形的结构,包括父子结构、节点名称、节点图标等,其实就是一个树结构的实现。大纲视图结构的实现,可以在随书源代码“org.jport.gef.berth.part.tree”包中找到。
 

GEF企业应用开发之--辅助功能_企业应用_05

 
属性视图的实现有两种方式:
1. 传统列表方式
 

GEF企业应用开发之--辅助功能_企业应用_06 

2. Tabbed方式,这种方式可以使用SWT的各种组件来展现对象的属性。如下图所示。GEF企业应用开发之--辅助功能_休闲_07
 
 
实现的Tabbed步骤
1、加入插件依赖:org.eclipse.ui.views.properties.tabbed。
2、配置plugin.xml

<extension
         point="org.eclipse.ui.views.properties.tabbed.propertyContributor">
      <propertyContributor
       typeMapper="org.jport.gef.berth.properties.tabbed.ElementTypeMapper"
       contributorId="org.jport.gef.berth.ui.BerthGraphicalEditor"
       labelProvider="org.jport.gef.berth.properties.tabbed.BerthElementLabelProvider"
       >
         <propertyCategory category="berth"/>
      </propertyContributor>
   </extension>
<extension
         point="org.eclipse.ui.views.properties.tabbed.propertyTabs">
      <propertyTabs contributorId="org.jport.gef.berth.ui.BerthGraphicalEditor">
       <propertyTab
               category="berth"
               id="shipTab"
               label="船舶基本信息"/>
      </propertyTabs>
   </extension>

配置说明:
typeMapper:Tabbed显示的类,类型过滤。
contributorId:为edior的id
labelProvider:Tabbed的Lable实现,如上图中的1部分。这不是实现Tabbed必须的,可也不实现。
propertyCategory与propertyTab中的category有对应关系,propertyTab的id必须唯一,label配置项即为途中的2部分。
3、配置propertySection

<extension
         point="org.eclipse.ui.views.properties.tabbed.propertySections">
      <propertySections contributorId="org.jport.gef.berth.ui.BerthGraphicalEditor">
       <propertySection
               class="org.jport.gef.berth.properties.tabbed.ShipInfoSection"
               id="shipInfoSection"
               tab="shipTab">
                <input
                  type="org.jport.gef.berth.model.ShipModel">
            </input>
         </propertySection>
      </propertySections>
</extension>

配置说明:
1、在三部分的Tabbed配置中,contributorId均是editor的id。
2、ShipInfoSection是Tabbed的主要部分,控制Section的生命周期。
3、input 输入ShipInfoSection显示的模型。
Palette工具箱可以提供便捷的图形编辑支持,Palette作为GEF自带的功能,实现起来也比较简单。先看一下,我们将实现的效果:
 

 

GEF企业应用开发之--辅助功能_GEF_08

 

1、让editor继承父类GraphicalEditorWithFlyoutPalette,实现方法:

    @Override
    protected PaletteRoot getPaletteRoot() {
       // TODO Auto-generated method stub
       if( paletteRoot == null ){
           paletteRoot =PaletteFactory.createPalette();
       }
       return paletteRoot;
    }

1.       PaletteFactory是自定义类,负责创建Palette。

……
private static PaletteContainer createComponentsDrawer() {
       // TODO Auto-generated method stub
       PaletteDrawer drawer = new PaletteDrawer("操作工具", ImageDescriptor
              .createFromFile(Activator.class, "icons/comp.gif"));
       List entries = new ArrayList();
       CombinedTemplateCreationEntry combined = new CombinedTemplateCreationEntry(
              "预报信息", "添加预报信息", new SimpleFactory(ShipModel.class),
              ImageDescriptor.createFromFile(Activator.class,
                     "icons/ship16.gif"),  
              ImageDescriptor.createFromFile(Activator.class,
                     "icons/ship24.gif")
       );
       entries.add(combined);
       drawer.addAll(entries);
       return drawer;
    }
……

2.       实现protected Command getCreateCommand(CreateRequest request) {}方法,

 @Override
    protected Command getCreateCommand(CreateRequest request) {
       if (request.getType() == REQ_CREATE && getHost() instanceof DiagramPart) {
           ShipCreateCommand cmd = new ShipCreateCommand();
           cmd.setDiagramModel(getHost().getModel());
           cmd.setShipModel(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) ? BerthConstants.SHIP_LENGTH : constraint.width;
           constraint.height = (constraint.height <= 0) ? BerthConstants.SHIP_WIDTH: constraint.height;
           cmd.setLayout(constraint);
           return cmd;
       }
       return null;
    }

3.       创建ShipCreateCommand.java

 package org.jport.gef.berth.command;
 
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.commands.Command;
import org.jport.gef.berth.model.DiagramModel;
import org.jport.gef.berth.model.ShipModel;
 
 
public class ShipCreateCommand extends Command
{
     
    private ShipModel ship;
    private DiagramModel diagram;
   
    public ShipCreateCommand() {
       super();
       ship = null;
       diagram= null;
    }
    public void setShipModel(Object s)
    {
       if (s instanceof ShipModel)
           this.ship = (ShipModel)s;
    }
    public void setDiagramModel(Object e) {
       if (e instanceof DiagramModel)
           this.diagram = (DiagramModel)e;
    }
   
    public void setLayout(Rectangle r) {
       if (ship == null)
           return;
       ship.setLayout(r);
    }
    @Override
    public boolean canExecute() {
       if (ship == null || diagram == null)
           return false;
       return true;
    }
   
    @Override
    public void execute() {
       diagram.addChild(ship);
    }
   
    @Override
    public boolean canUndo() {
       if (ship == null || diagram == null)
           return false;
       return diagram.contains(ship);
    }
    @Override
    public void undo() {
       diagram.removeChild(ship);
    }
}