昨天讨论了在图形元素上显示工具条的方法,应该说工作的还不是很完美,因为在选定了创建Connection的工具后,并不能像使用palette那样,在鼠标移动的过程中,有一个连接动态跟随,当鼠标释放后,如果释放位置在一个图形元素之上,那么将建立这个Connection,如果不在,那么这个连接将自动消失;今天想讨论一下如何实现这个功能;

我们知道GEF是以Draw2D的LightweightSystem作为实现的基础的,在LightweightSystm中对于mouseDown和mouseMove的实现如下:

事件发布
 1         /** @see MouseListener#mouseDoubleClick(MouseEvent) */
 2         public void mouseDoubleClick(MouseEvent e) {
 3             getEventDispatcher().dispatchMouseDoubleClicked(e);
 4         }
 5
 6         /** @see MouseListener#mouseDown(MouseEvent) */
 7         public void mouseDown(MouseEvent e) {
 8             getEventDispatcher().dispatchMousePressed(e);
 9         }
10
11         /** @see MouseTrackListener#mouseEnter(MouseEvent) */
12         public void mouseEnter(MouseEvent e) {
13             getEventDispatcher().dispatchMouseEntered(e);
14         }
15
16         /** @see MouseTrackListener#mouseExit(MouseEvent) */
17         public void mouseExit(MouseEvent e) {
18             getEventDispatcher().dispatchMouseExited(e);
19         }
20
21         /** @see MouseTrackListener#mouseHover(MouseEvent) */
22         public void mouseHover(MouseEvent e) {
23             getEventDispatcher().dispatchMouseHover(e);
24         }
25
26         /** @see MouseMoveListener#mouseMove(MouseEvent) */
27         public void mouseMove(MouseEvent e) {
28             getEventDispatcher().dispatchMouseMoved(e);
29         }
30
31         /** @see MouseListener#mouseUp(MouseEvent) */
32         public void mouseUp(MouseEvent e) {
33             getEventDispatcher().dispatchMouseReleased(e);
34         }
35
36         /** @see DisposeListener#widgetDisposed(DisposeEvent) */
37         public void widgetDisposed(DisposeEvent e) {
38             getUpdateManager().dispose();
39         }
40
由此可见,Draw2D对于鼠标事件的处理是由Event Dispacher进行派发的。那么这些派发的事件是怎么处理的呢?在org.eclipse.gef.tools.AbstractTool类中有很多相应的handleXXX方法,例如:handleDoubleClick、handleDrag方法等等,这就是处理这些鼠标事件的位置,当然这些方法在这个类中,没有做什么处理,仅仅返回了false;但是如果我们继续向下查找的话,会发现其子类AbstractConnectionCreationTool重写了一些handle方法,其中之一就是handleDrag,而handleDrag调用了handleMove;

handleXXX的实现
/**
     * @see org.eclipse.gef.tools.AbstractTool#handleDrag()
     */
    protected boolean handleDrag() {
        if (isInState(STATE_CONNECTION_STARTED))
            return handleMove();
        return false;
    }

/**
     * @see org.eclipse.gef.tools.AbstractTool#handleDragInProgress()
     */
    protected boolean handleDragInProgress() {
        if (isInState(STATE_ACCESSIBLE_DRAG_IN_PROGRESS))
            return handleMove();
        return false;
    }

/**
     * @see org.eclipse.gef.tools.AbstractTool#handleFocusLost()
     */
    protected boolean handleFocusLost() {
        if (isInState(STATE_CONNECTION_STARTED)) {
            eraseSourceFeedback();
            eraseTargetFeedback();
            setState(STATE_INVALID);
            handleFinished();
        }
        return super.handleFocusLost();
    }

/**
     * @see org.eclipse.gef.tools.TargetingTool#handleHover()
     */
    protected boolean handleHover() {
        if (isInState(STATE_CONNECTION_STARTED))
            updateAutoexposeHelper();
        return true;
    }

/**
     * @see org.eclipse.gef.tools.TargetingTool#handleInvalidInput()
     */
    protected boolean handleInvalidInput() {
        eraseSourceFeedback();
        setConnectionSource(null);
        return super.handleInvalidInput();
    }

/**
     * @see org.eclipse.gef.tools.AbstractTool#handleMove()
     */
    protected boolean handleMove() {
        if (isInState(STATE_CONNECTION_STARTED) && viewer != getCurrentViewer())
            return false;
        if (isInState(STATE_CONNECTION_STARTED | STATE_INITIAL
                | STATE_ACCESSIBLE_DRAG_IN_PROGRESS)) {
            updateTargetRequest();
            updateTargetUnderMouse();
            showSourceFeedback();
            showTargetFeedback();
            setCurrentCommand(getCommand());
        }
        return true;
    }
看到handleMove中的那个showSourceFeedback()方法了吧,其实我们今天讨论的问题,在GEF框架中就是通过它实现的;爬源码,我们可以知道这个方法事实上是调用了AbstractEditPart的showSourceFeedback()方法,而后者又调用了GraphicalNodeEditPolicy的showSourceFeedback方法,这个方法又调用了showCreationFeedback方法;

/**
     * Shows feedback during a creation.
     *
     * @param request
     *            CreateConnectionRequest
     */
    protected void showCreationFeedback(CreateConnectionRequest request) {
        FeedbackHelper helper = getFeedbackHelper(request);
        Point p = new Point(request.getLocation());
        helper.update(getTargetConnectionAnchor(request), p);
    }

/**
     * calls {@link #showCreationFeedback(CreateConnectionRequest)} when
     * appropriate.
     *
     * @see org.eclipse.gef.EditPolicy#showSourceFeedback(Request)
     */
    public void showSourceFeedback(Request request) {
        if (REQ_CONNECTION_END.equals(request.getType()))
            showCreationFeedback((CreateConnectionRequest) request);
    }

这下我们就明白了,我们只要照猫画虎,在我们的工具条的mouse move方法中实现上面的那个showCreationFeedback方法就行了;以下就是我们的实现:

1 public void mouseDragged(MouseEvent me) {
 3     request = new CreateConnectionRequest();
 4     ScalableFreeformRootEditPart root = (ScalableFreeformRootEditPart) getSourceEditPart().getRoot();
 5     double zoom = root.getZoomManager().getZoom();
 6
 7     request.setLocation(new Point(hoverX * zoom, hoverY * zoom));
 8     request.setType("connection start");
 9
10     FeedbackHelper feedbackHelper = new FeedbackHelper();
11     Point p = new Point(me.x, me.y);
12     Connection connectionFeedback = FigureFactory.createNewWorkflowPath(null);
13
14     connectionFeedback.setConnectionRouter(((ConnectionLayer) getLayer(LayerConstants.CONNECTION_LAYER)).getConnectionRouter());
15     connectionFeedback.setSourceAnchor(getSourceConnectionAnchor(request));
16     feedbackHelper.setConnection(connectionFeedback);
17
18     IFigure figure = getLayer(LayerConstants.FEEDBACK_LAYER);
19     for (int i = 0; i < figure.getChildren().size(); i++) {
20         if (figure.getChildren().get(i) instanceof Connection) {
21             figure.remove((IFigure) figure.getChildren().get(i));
22         }
23     }
24     getLayer(LayerConstants.FEEDBACK_LAYER).add(connectionFeedback);
25     request.setLocation(new Point(me.x * zoom, me.y * zoom));
26     feedbackHelper.update(null, new Point(me.x + offsetX * zoom, me.y + offsetY * zoom));
27 }
28
至此,我们的问题就解决了。但是还有一个问题,那就是,如果鼠标被释放了,那么这个被放置在反馈层的Connection应该被擦除掉,而同时还应该根据鼠标的位置决定是不是应该创建Connection;所以我们还应该再改一下mouse released方法,增加如下处理:
IFigure feedBackLayer = getLayer(LayerConstants.FEEDBACK_LAYER);
feedBackLayer.getChildren().clear();

通过以上的处理,我们就可以实现类似于palette中Connection Tool的功能了。当我们在一个图形元素上Hover时,首先程序先将与悬停位置最近的锚点作为源锚点,并显示工具条,当我们点击工具条上的Connection图标时,随着鼠标的拖动,一个Connection将动态跟随鼠标的移动被画出来,随着鼠标的释放,Connection将根据释放位置决定是否建立一个Connection,还是将这个动态的Connection清除掉;

关注技术文章飞秋:http://www.freeeim.com/,24小时专业转载。

【飞秋】进一步完善 -- GEF创建助手工具条相关推荐

  1. 新浪微博客户端(42)-完善表情键盘的工具条

    DJEmotionTabBar.m // // DJEmotionTabBar.m // 微博 // // Created by 海月高 on 16/11/26. // Copyright © 201 ...

  2. 公布旗下(飞秋)系列软件工作原理

    即时通讯11版,(飞秋)发表<局域网通信>,公布旗下(飞秋)系列软件工作原理,呼吁软件同行透明化.很快QQ的产品团队做出了反应,对外声明"关于某公司诬蔑腾讯QQ'窥视用户隐私'的 ...

  3. MFC的工具条和状态栏

     Windows控制窗口 Windows (Windows95或者以上版本) 提供了系列通用控制窗口,其中包括工具条(ToolBar).状态栏(StatusBar).工具条提示窗口(ToolTip ...

  4. 自定义报表预览控制工具条

    说明:原有的VFP的打印预览用多了感觉真的不是很方便,在某些特定的要求下,她就显得很笨拙,尤其那个打印工具条上的打印机按纽,一点就打印了,有时候我们需要在那个时候进行有选择性的打印而不是全盘的打出来, ...

  5. 为Autodesk Viewer添加自定义工具条

    如果你参加过我们近期的活动,你就会频繁的听到我们现在正在做的Autodesk Viewer大模型浏览器,这是一个不需要下载任何插件,基于WebGL技术的浏览器,可以支持几十种数据格式.同时viewer ...

  6. 在ARX中通过COM在ACAD中添加菜单和工具条

    转载地址:http://blog.csdn.net/habit2/article/details/438318 代码如下: extern "C" AcRx::AppRetCode  ...

  7. 【转载】在ARX中通过COM在ACAD中添加菜单和工具条

    科技创新项目需要结题了,现在只有一个标注剪切的功能,同张老师商量了一下,张老师叫我再加上一两个功能,同时要做出有对话框.菜单或者工具条之类的UI界面.刚好碰巧当天晚上就看到有人在二次开发群里讲添加菜单 ...

  8. 利用TCP/UDP 协议制作一个飞秋聊天工具

    视频操作演示: 利用TCP/UDP 协议制作一个飞秋聊天工具演示视频 int udp_broadcast(char const*argv[]) {//1.创建对象udp_socket = socket ...

  9. 【飞秋】使用C++语言创建Silverlight中的VisualState

    Silverlight中的VisualState(可视状态)是一个非常重要的概念,使用VisualState,可以将界面的各个状态进行有效的区隔开,并进行单独的设计,并且可以在状态切换时实现动画效果, ...

最新文章

  1. PC 时代旧神隐没,互联网的新二十年开始了
  2. python水平条形图_如何在Bokeh(Python)中绘制水平条形图
  3. PPT模板中的”书签”
  4. Arduino 笔记。开篇
  5. ant design pro取消登录_JeecgBoot实战按需加载 Ant-Design-Vue和Icon
  6. 2.15 更改所有者和所属组chown
  7. VUE $SET源码
  8. 2021年第3周人工智能方向的周报
  9. ElasticSearch5.1 基本概念和配置
  10. 【C#】使用OWIN创建Web API
  11. ModelSim ALTERA 6.5b 下载安装以及使用
  12. 带你玩转 Visual Studio——带你跳出坑爹的 Runtime Library 坑
  13. 超级超级实用的整个网页截图技巧
  14. linux表示虚拟字符终端,终端,控制台,虚拟终端分别指什么
  15. 借助WinPE进行Windows系统安装
  16. 手机自动下载当天voa听力
  17. html图片指定refere,前端解决第三方图片防盗链的办法 - html referrer 访问图片资源 403 问题...
  18. 5G通信名词释义详解【5G通信技术基础篇---istrangeboy精品博文】
  19. 虚拟直播与光学动作捕捉技术
  20. 网易蓝牙耳机怎么切换双耳_解放双耳,抛开手机,南卡Runner Pro骨传导耳机体验_蓝牙耳机...

热门文章

  1. html5 indexeddb 排序,html5 – 在IndexedDB中,有没有办法进行排序复合查询?
  2. MyCat介绍与配置(精)
  3. ElasticSearch的Object数据类型
  4. SpringCloud 入门教程(五): Ribbon实现客户端的负载均衡
  5. 互联网晚报 | 4月13日 星期三 | 阿里云人事大变动;老坛酸菜方便面重返超市货架;工信部:加快5G全连接工厂建设...
  6. 互联网晚报 | 10月5日 星期二 | 爱奇艺、腾讯、优酷宣布取消超前点播;蜜雪冰城冲刺A股上市;吴京主演电影票房超200亿...
  7. 2021快手电商数据报告
  8. bool 取反_dataframe根据bool值高效地进行多重条件筛选的
  9. 新书推荐 |《5G安全技术与标准》
  10. 大数据系统软件创新平台与生态建设