GEF功能增强之创建助手

用过GMF就知道,GMF默认生成的editor有一个悬浮的创建助手功能:当把鼠标移动到某个editpart上,稍停,则会出现一个提示条,上面列出当前位置的editpart上可以新建的子元素,直接选择某项进行新建而无需Palette的参与。

 

就像之前那篇连接助手一样,使用此功能可以大大方便新建过程。所以这里就和大家讨论一下这个功能的自我实现。

 

没有详细的研究过GMF中这个功能的实现代码,大家有兴趣的可以去参考GMF的实现,这里我只聊聊我自己的想法。

 

这里我以实现一个很简单的UML图为例,假设只能有以下模型:

  • 工程:作为根,可以含有包
  • 包:可以含有子包和类
  • 类:可以含有变量和方法
  • 变量
  • 方法

OK,这样模型结构就定义完了,最后我希望出现以下图样:

 GEF功能增强之创建助手

                         Figure 1: Project Creation Helper

GEF功能增强之创建助手

                       Figure 2: Package Creation Helper

GEF功能增强之创建助手

                Figure 3: Class Method Creation Helper

GEF功能增强之创建助手

              Figure 4: Class Field Creation Helper

 

当鼠标悬停在某个Editpart之上时,对应的创建助手条就会出现,当鼠标在某个项上滑过的时候,该项会高亮,且有虚线围绕。如果此时点击,则在对应位置就会创建出一个新对象。

 

要实现创建助手条,不用说,大家都能想到:

  1. 需要知道当前对象上可创建的子项
  2. 需要知道每个子项的图标
  3. 需要知道创建坐标
  4. 最后当然就是画单个项目和画整条提示条了

为了知道每个对象上可创建的子项,我定义了一个接口:IHoverHelper,它只有一个方法:getHoverChildren(),为简单起,我让这方法只要返回一个Class对象数组即可。然后,显然每个需要助手功能的模型都需要实现这个接口。

 

除此之外,为了知道每个对象对应的图标,我也定义了一个工厂,用来定义模型-图标对,当需要某个对象的图标时,就从这个工厂取。

 

下面就是在适当的时候让助手条显示出来了。

 

之前已经说过,悬停的时候出现,所在我让模型的editpart实现MouseMouseListner,然后把这个Listener安装在模型对应的figure上。这样,一个事件触器就定义好了。

 

假设我们有一个类CreationPopupBarFigure就是用来显示这个助手条。那么,我们就需要在mouseHover()方法里把它显示出来;显然,我们不能让它一直呆在那,所以还需要在mouseMoved()方法里让它消失。

 

这里有几点需要考虑的:

 

         1.助手条显示图加在谁上的问题

            我们知道,一个Figure需要加在某个已经显示出来的Figure上,才能被看到。那我这个提示条加在谁上呢?我就想到RootEditPart的那几个层,有一点可以肯定的就是这个提示条一旦出现,就不应该被什么东西挡住对吧?那它的层次应该比较高。一开始我是想加在FeedBack层,但是发现它对鼠标滑过没反应,最后就加在了Handle层了。

 

         2.对象声明的问题

            应该可以肯定,同一时间不可能出现多个提示条对吧?如果是的放,那就是思路出问题了。所以整个程序中应该只有一个提示条出现才对。所以我们可以声明一个static的提示条变量来避免创建多个提示条。

 

          3.消失的问题

             之前已经说过了,在mouseHover()方法里显示,在mouseMoved()方法里消失。所以我们首先要让提示条出现的位置在紧挨着鼠标悬停的位置;其次,我们还要空许一些额外的空间,就像一条连接线,也会有一些额外的空间来表示在线的范围内。这样做的目的是避免用户一移动,提示条就消失。

 

OK,大致实现过程就结束了。最后就到了CreationPopupBarFigure。

 

大致创建已经讲了,就是显示在handle层上,显示在挨着鼠标的当前位置上。

 

还有一些需要补充的:

 

1.自动消失的问题

如果鼠标不动,让它一直显示在那也是不好的。所以我加了一个两秒的消失时间。

 

2.不自动消失的情况

上面已经说了两种消失情况:鼠标移动、定时消失。想像这样一种情形,我们鼠标正在提示条上滑动以进行选择,结果消失了。这肯定让人很气愤,对吧?

所以还要有一种不消失的情况,那就是在鼠标在条上滑动进行选择的时候。因此我们的提示条和它上面的子项都需要加一个鼠标监听,来确保当鼠标在它们之上移动时,就让提示条一直显示。

 

 

OK,最后当鼠标在某项上点击时,创建出一个新对象,大致可以如下写:

		CreateRequest createRequest = new CreateRequest(modelClass);
		createRequest.setLocation(new Point(x, y));
		createRequest.setFactory(new SimpleFactory(modelClass));
		createRequest.setType(RequestConstants.REQ_CREATE);
		Command command = host.getCommand(createRequest);
		host.getViewer().getEditDomain().getCommandStack().execute(command);

 

试试新功能,我觉得挺好的,不用再点palette了。

 

 

 

 

 

 

 

 

你可能感兴趣的:(UML)