- 浏览: 298692 次
- 性别:
- 来自: 广州
-
文章分类
最新评论
-
M大米饭:
19774279 写道xj1990129 写道PackageF ...
Eclipse插件开发之获得当前项目 -
zhongmin2012:
AST抽象的java语法树 -
wd3389:
好可惜,你写的文章很有帮助,谢谢!
关于博客更新 -
zxjlwt:
http://surenpi.com/2015/07/13/e ...
eclipse扩展点清单 -
zxjlwt:
学习了。http://surenpi.com
Console 控制台扩展(一)
EditPart是整个gef的核心层,如果想更好的扩展它,必须了解它的生命周期。
1.物理结构:
整个编辑器从物理结构上来说,其实就是多个EditPartViewer组成,而从展现上来说EditPartViewer提供给编辑器的是一个SWT控件,而不是Figure(Figure也是由SWT发展而来)。对于不同的EditPartViewer会由不同的选中,其中GraphicalViewerImpl的选择就是所有的子组件必须是Figure。
public Control createControl(Composite composite) { setControl(new Canvas(composite, SWT.NO_BACKGROUND)); return getControl(); }
大家应该清楚Canvas与LightweightSystem的渊源。
我们只关心GraphicalViewerImpl的话会发现,其实从物理结构上来说。整个编辑器的展现层都是由一个GraphicalViewerImpl,和它的若干个EditPart来展现的,而这若干EditPart都是装在一个ScalableRootEditPart里面的,EditPart本身不是展现,但是它的Figure展现。
在GraphicalViewerImpl中会new一个LightweightSystem对象,然后在看看下面这段代码就清楚了。
public void setRootEditPart(RootEditPart editpart) { super.setRootEditPart(editpart); setRootFigure(((GraphicalEditPart) editpart).getFigure()); }
protected void setRootFigure(IFigure figure) { rootFigure = figure; getLightweightSystem().setContents(rootFigure); }
ScalableRootEditPart会把自己的Figure放到LightweightSystem里面进行管理。这也是很多书上都会说,我们自己创建的rootFigure不是真正的root。至于LightweightSystem的内部如何管理Figure不在本文详述。除了创建以外,销毁也是这GraphicalViewerImpl里面实现的。
2.操作:
除了生命周期以外,GraphicalViewerImpl里面还有很多对EditPart的操作。常用的像,获取鼠标选中的EditPart,获取光标所在的EditPart,以及选中一个EditPart。凡是对EditPart操作比较粗粒度的处理,都是在GraphicalViewerImpl里面进行处理的。
这个也扯出一个问题,就如同我之前碰到的一个问题,如何选中一个EditPart在编辑器里面。最开始的时候,我是直接用EditPart调用自己的setSelected(int value);。但是事实上,这个只是一种选中的状态,而不是真正的选中了。仔细想想也是,自己能选中自己吗?自己应该只能标记自己的选中状态才对,选中的操作应该由别人发起。事实上,通过GraphicalViewerImpl选中EditPart,属性视图和大纲都会同步。
3.EditPart的内部周期:侧重对IFigure 的描述
上述的一些,只能很浅显的描述一下GraphicalViewerImpl和EditPart的关系,很多时候只知道这些是不够的。在前面的文章,由描述整个gef的事件触发过程,这些事件触发后最终会归结到模型和界面的改变。模型的改变挺容易理解,这里讲一下界面的改变。
1.ScalableRootEditPart:rootPart
首先需要搞清楚ScalableRootEditPart,因为根part相对来说比较特殊。
The layer structure (top-to-bottom) for this root is: Root Layered Pane ├ Guide Layer ├ Feedback Layer ├ Handle Layer └ Scalable Layers (ScalableLayeredPane) ├ Scaled Feedback Layer ├ Printable Layers ├ Connection Layer └ Primary Layer └ Grid Layer
从注释上看,可以知道整个编辑器的最底层,是建立了多个Layer的,每个Layer都有其特定的作用。Primary Layer是我们的组件实体显示的位置。GraphicalEditPart的getFigure();就显示在这层。每个层具体是干嘛的,自己研究。
protected IFigure createFigure() { Viewport viewport = createViewport(); innerLayers = new LayeredPane(); createLayers(innerLayers); viewport.setContents(innerLayers); return viewport; }
知道这个Viewport是干嘛的吗?这个是有一个概念的,视图和视角,整个编辑器是可以无限大的,而我们看到的部分却是有限的,我们看到的就是 Viewport,Viewport还跟侧滑条的实现相关。
protected ScalableLayeredPane createScaledLayers() { ScalableLayeredPane layers = new ScalableLayeredPane(); layers.add(createGridLayer(), GRID_LAYER); layers.add(getPrintableLayers(), PRINTABLE_LAYERS); layers.add(new FeedbackLayer(), SCALED_FEEDBACK_LAYER); return layers; }
滚动层的创建。
了解ScalableRootEditPart最大的意义就是,你知道了你的Figure具体展现在那一层,那个位置。
2.GraphicalEditPart:
我们关注的是图形化界面,所以需要重点关注一下这个接口。其中有三个方法是需要重点关注的:
IFigure getFigure(); IFigure getContentPane(); void setLayoutConstraint(EditPart child, IFigure figure, Object constraint);
getFigure与getContentPane的区别:getFigure是EditPart界面的root,是EditPart向上提供的Figure。ContentPane,是一个容器,用来装EditPart孩子的Figure的容器,默认情况下这两个是同一个。
public void setLayoutConstraint(EditPart child, IFigure childFigure, Object constraint) { childFigure.getParent().setConstraint(childFigure, constraint); }
这个是setLayoutConstraint的默认实现,也就是说在调用这个方法之前,childFigure是肯定有父的。
public void setConstraint(IFigure child, Object constraint) { if (child.getParent() != this) throw new IllegalArgumentException("Figure must be a child"); //$NON-NLS-1$ if (layoutManager != null) layoutManager.setConstraint(child, constraint); revalidate(); }
其实最终也就是把EditPart里面子的约束,传递给父的Figure的Layout里面了,这样也是为啥第二个参数是Object的原因,因为不同的 Layout,需要的值不一样。
3.AbstractGraphicalEditPart:
protected void addChildVisual(EditPart childEditPart, int index) { IFigure child = ((GraphicalEditPart) childEditPart).getFigure(); getContentPane().add(child, index); }
添加子的界面,这个是在添加子EditPart调用的,默认实现如上。
protected IFigure getLayer(Object layer) { LayerManager manager = (LayerManager) getViewer().getEditPartRegistry() .get(LayerManager.ID); return manager.getLayer(layer); }
获取layer的方法,传递的ID,到Viewer里面去找。
public void refresh() { refreshVisuals(); refreshChildren(); refreshSourceConnections(); refreshTargetConnections(); }
刷新界面的时候的刷新顺序,如上。
4.内部周期(Add过程):
(1)编辑器会通过setinput获取到文件,然后加载为模型。而GraphicalViewerImpl在构造的时候已经构造了一个ScalableRootEditPart。
(2)获取到文件后,会加载以下内容,其中getGraphicalViewer()就是GraphicalViewerImpl对象,而他的setContents(roots);会获取到模型的root。
@Override protected void configureGraphicalViewer() { super.configureGraphicalViewer(); RootEditPart rootEditPart = new ScalableFreeformRootEditPart(); getGraphicalViewer().setRootEditPart(rootEditPart); getGraphicalViewer().setEditPartFactory(new ContextEditPartFactory()); getGraphicalViewer().setContents(roots); getGraphicalViewer().setContextMenu(createContextMenuProvider()); getGraphicalViewer().setKeyHandler(getKeyHandler()); }
(3)在setContents内部其实就是调用EditPartFactory创建的EditPart,然后添加到RootEditPart。
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); }
(4)为了关注RootEditPart是如何添加的,我们看看SimpleRootEditPart里面的实现:
public void setContents(EditPart editpart) { if (contents == editpart) return; if (contents != null) removeChild(contents); contents = editpart; if (contents != null) addChild(contents, 0); }
它会把editpart添加为子:
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); }
这个过程中,它会把child的界面元素添加到自己的界面元素里面去addChildVisual(child, index);
protected void addChildVisual(EditPart childEditPart, int index) { IFigure child = ((GraphicalEditPart) childEditPart).getFigure(); getContentPane().add(child, index); }
这个就是我们刚才说的默认实现。子添加子的子也是这个顺序。整个过程怎么没使用setLayoutConstraint方法呢?是因为这个方法跟添加无关,跟刷新相关。
5.内部周期(刷新):
(1)首先我们得明白,刷新的源头在那,也就是刷新的这个请求是谁发起的?是模型,模型改变了,是我们自己用代码触发的刷新。我们一般的做法是在自己的EditPart类实现PropertyChangeListener,当属性改变时,我们刷新界面。
@Override public void propertyChanged(ModelElement element, String propertyName, Object oldValue, Object newValue) { refresh(); }
假设全部刷新,我们会调用refresh方法。
(2)刷新过程:
public void refresh() { refreshVisuals(); refreshChildren(); refreshSourceConnections(); refreshTargetConnections(); }refreshVisuals这个刷新自己,也就是自己创建的IFigure,refreshChildren刷新子,refreshSourceConnections和refreshTargetConnections是刷新线的,这里只关注refreshVisuals和refreshChildren。refreshVisuals的默认实现未空,需要自己进行扩展,没啥好说的就是重新画一遍。
@Override protected void refreshVisuals() { ((AbstractGraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), model.getBounds()); super.refreshVisuals(); }上述是比较常见的处理方式,意思就是把自己再塞到父里面去一次。
protected void refreshChildren() { int i; EditPart editPart; Object model; List children = getChildren(); int size = children.size(); Map modelToEditPart = Collections.EMPTY_MAP; if (size > 0) { modelToEditPart = new HashMap(size); for (i = 0; i < 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); } } // remove the remaining EditParts size = children.size(); if (i < size) { List trash = new ArrayList(size - i); for (; i < size; i++) trash.add(children.get(i)); for (i = 0; i < trash.size(); i++) { EditPart ep = (EditPart) trash.get(i); removeChild(ep); } } }
上述是刷新子的默认实现,大致就是变量一下,比较关键的一个句代码reorderChild(editPart, i);
protected void reorderChild(EditPart child, int index) { // Save the constraint of the child so that it does not // get lost during the remove and re-add. IFigure childFigure = ((GraphicalEditPart) child).getFigure(); LayoutManager layout = getContentPane().getLayoutManager(); Object constraint = null; if (layout != null) constraint = layout.getConstraint(childFigure); removeChildVisual(editpart); List children = getChildren(); children.remove(editpart); children.add(index, editpart); addChildVisual(editpart, index); setLayoutConstraint(child, childFigure, constraint); }先删除,再添加,然后调用一下setLayoutConstraint进行刷新。关于setLayoutConstraint里面的流程前面已经说了,最终是layout添加了一遍 child。
发表评论
-
Feedback(反馈)详述一
2012-05-13 22:29 1320Feedback用于对gef编辑器操作的反馈,最常见的是一些鬼 ... -
gef编辑器详述
2012-05-13 21:56 2971工作以来一直都在做IDE,写篇文章记录下自己对gef的理解,再 ... -
DragTracker拖拽跟踪
2012-05-11 01:17 1347DragTracker接口是gef中用 ... -
EditPart的选中
2012-05-10 14:20 1123EditPart的选中状态: 在EditPart里面可以通过 ... -
增加Palette的拖放支持
2012-05-14 01:13 1148注意:这篇文章是从刘刚的博客中获取的,主要是考虑到自己碰 ... -
Feedback(反馈)
2011-12-19 11:42 1210Feedback(反馈): 所谓反馈,是指操作时显示的 ... -
Palette面板
2011-12-13 15:13 1541Palette(面板):作为图形化编辑器的一部分而普片存在。一 ... -
Policy策略
2011-12-07 16:22 1596Policy:最基本的功能就是接收Request(请求),然后 ... -
gef中默认提供的RootEditPart
2011-12-07 12:57 1349在我们实现一个gef编辑器的时候,会重新configureGr ... -
Viewport视口
2011-12-07 11:36 1027Viewport视口:编辑器中 ...
相关推荐
EditPart有特定的生命周期,包括创建、初始化、显示、更新和销毁等阶段。理解这些事件对于有效地处理用户交互和图形更新至关重要。 5. **工具和绘图板**: GEF支持多种用户交互,如鼠标和键盘操作,以及与工作台...
视图(View)则利用Draw2D系统来展示模型,而控制器(Controller)通常表现为EditPart。EditPart作为模型和视图之间的桥梁,负责处理用户操作和模型更新之间的交互。 MVC模式在GEF中的工作流程如下:用户对视图进行...
InfoJet EditPart 是一系列用于在浏览器中编辑SharePoint中InfoPath表单的Web Parts。 InfoJet EditPart使用InfoJet Service作为InfoPath表单Web编辑引擎。在SharePoint中使用InfoJet EditPart无需编写任何程序。...
3. **EditPart**: EditPart是模型和视图之间的适配器,它负责将模型的变化反映到视图上,反之亦然。 4. **Command**: 命令模式是GEF中的一个重要概念,用于管理用户的编辑操作,确保可撤销/重做功能。 **四、GEF...
它由几个关键组件组成,包括Model(模型)、View(视图)、EditPart(编辑部分)、Figure(图形)和Command(命令)。Model代表数据模型,是业务逻辑的载体;View是模型的可视化表示,通过EditPart进行管理;...
GEF主要由几个关键组件构成:Model(模型)、View(视图)、EditPart(编辑部件)和Figure(图形)。模型是数据结构的抽象,负责存储和管理数据;视图则将模型的数据转换为用户可见的图形表示;EditPart是视图和模型...
Command代表可撤销/重做的操作,Model表示数据模型,View负责显示图形,EditPart作为模型和视图之间的桥梁,而Figure则是实际在屏幕上绘制的对象。 2. **实例代码结构分析** 在" GefExample "这个压缩包中,通常会...
3. **插件生命周期**:解释插件的启动、运行和停止过程,以及如何响应Eclipse事件。 4. **扩展点和扩展**:介绍如何定义和使用Eclipse的扩展点来扩展Eclipse的功能。 5. **插件间通信**:讲述服务定位、事件广播和...
4. **EditParts**:编辑部件是视图中的可编辑单元,每个EditPart对应一个模型元素。 5. **Commands**:命令模式用于处理图形编辑操作,确保操作的可撤销/重做。 6. **Connectors**:连接器用于创建和管理图形元素...
GEF提供`EditPart`类作为视图的基础,开发者可以通过继承`EditPart`并重写相关方法来创建自定义视图。 4. **控制器(Controller)** 控制器处理用户输入,将它们转化为对模型的更改。GEF的`Command`机制允许开发者...
3. **EditPart(编辑部件)**:EditPart是GEF中实现图形化编辑的关键组件,它负责将模型对象映射到图形元素,并处理用户交互。EditPart包含了一个图形化表示(figure)和对模型的操作逻辑。 4. **Command(命令)**...
2. 在Content页面,勾选"Generate an activator",以便管理插件的生命周期。同时,务必选择"Create an RCP application",这是创建GEF应用的关键。 3. 在Templates页面,选择最小的模板,然后点击"Finish",这样就...
- **编辑部分(EditPart)**:编辑部分是视图中的可编辑组件,每个图形元素都有对应的EditPart,负责渲染和处理用户输入。 - **命令(Command)**:Gef使用命令模式来实现可撤销/重做的功能,每个编辑操作对应一个...
- **控制器(Controller)**:在GEF中,控制器由一组EditPart对象组成,每个模型对象对应一个EditPart。EditPartFactory负责根据模型创建EditPart实例。RootEditPart作为容器,将EditPartViewer与contents(通常是...
主要是对自己做的项目的一些总结,包括如何自动添加图元、删除图元,建立连线,获得编辑器的EditPart,不打开编辑器,获取编辑器的EditPart,属性居中,自动保存图片等功能的实现。另外还有一些参考资料
- 实现EditPart:将模型转换为可视化的EditPart,处理绘图和事件。 - 创建Part:定义Part类,关联EditPart和View。 - 实现Command:定义可撤销/重做的操作。 - 配置和启动:在Eclipse插件的启动配置中添加新的...
- **EditPart**: 视图中的表示层,负责将Figure与模型关联,处理用户交互。 - **Model**: 数据模型,存储图形的结构和属性信息。 - **Command**: 操作命令,封装了对模型的修改,支持撤销/重做操作。 **3. GEF工作...
GEF MVC (Mode, Figure, EditPart) (交互层,模型与图形元素映射,工作台交互处理) View: Draw2d 图形化界面 Control 核心 mode 用户设计 (绘图,着色,图形布局管理,图形缩放控制) SWT 画布 Canvas,处理...
- `org.eclipse.gef.editpolicies`包下的类:提供了各种编辑策略,如连接策略、布局策略等,它们决定了EditPart如何响应特定请求。 - `org.eclipse.gef.handles`包下的类:用于创建图形元素的手柄,用户可以通过手柄...
2. **EditPart**: EditPart是GEF中的核心组件,它连接模型和视图。EditPart负责将模型的变化反映到视图上,同时也处理用户对视图的操作,更新模型。 3. **Figure**: Figure是视图的基本元素,它可以是简单的形状,...