RCP学习:GEF编辑器的鼠标的hover policy以及一个预览窗口效果

简介: GEF编辑器遵循MVC模式。在这里Controller既是org.eclipse.gef.EditPart。它的行为是可以被一系列的策略(org.eclipse.gef.EditPolicy)确定的,见AbstractEditPolicy的方法: /** * Creates...

GEF编辑器遵循MVC模式。在这里Controller既是org.eclipse.gef.EditPart。它的行为是可以被一系列的策略(org.eclipse.gef.EditPolicy)确定的,见AbstractEditPolicy的方法:

    /**
     * Creates the initial EditPolicies and/or reserves slots for dynamic ones.
     * Should be implemented to install the inital EditPolicies based on the
     * model's initial state. <code>null</code> can be used to reserve a "slot",
     * should there be some desire to guarantee the ordering of EditPolcies.
     * 
     * @see EditPart#installEditPolicy(Object, EditPolicy)
     */
    protected abstract void createEditPolicies();

 

我们自己定义的Policy可以在这个位置添加。

下面来定义一个鼠标移动到节点上即可以做某些事情的Policy,该Policy要实现如下功能:

1、鼠标移动到节点上的时候,绘制handle

2、鼠标点击任何位置,handle消失

3、鼠标移动到其他节点,绘制新的handle,之前的handle消失。

先看下效果图:

1、这是一个普通的GEF节点,红色和绿色手型标示着连线的端点

2、当鼠标移动到节点上,并且停留数秒的时候,绘制一个橙色手型覆盖红色手型:

3、当鼠标点击该橙色手型,则出现可拖拽的连线提示(该部分功能由handle实现,暂不讨论):

 

先来看看Policy的实现:

/**
 * 
 * @author caiyu
 * 
 */
public abstract class CommonHoverEditPolicy extends GraphicalEditPolicy {
    public static final String ROLE = "CommonLineAssistantEditPolicy";

    protected IFigure handleLayer;
    /* the List of handles */
    protected List<Handle> handles;

    /* the Hover Listener */
    private MouseMotionListener hoverListener;

    /* listener for every handle */
    private MouseMotionListener handleListener;

    private LayoutListener removeListener;

    private Timer timer;

    private boolean hovering = false;

    protected int TIME_INTERVAL = 1000;

  
public void activate() { super.activate(); addHoverListener(); addHandleListener(); } private void addHandleListener() { handleListener = new MouseMotionListener() { public void mouseDragged(MouseEvent me) { } public void mouseEntered(MouseEvent me) { } public void mouseExited(MouseEvent me) { cancelTimer(); startTimer(); } public void mouseHover(MouseEvent me) { } public void mouseMoved(MouseEvent me) { } }; } protected void addHoverListener() { final IFigure figure = getHostFigure(); hoverListener = new MouseMotionListener() { public void mouseDragged(MouseEvent me) { } public void mouseEntered(MouseEvent me) { } public void mouseExited(MouseEvent me) { startTimer(); } public void mouseHover(MouseEvent me) { cancelTimer(); addHoverHandles(); hovering = true; } public void mouseMoved(MouseEvent me) { } }; /** * 被删除的时候清除监听 */ removeListener = new LayoutListener() { @Override public void invalidate(IFigure container) { } @Override public boolean layout(IFigure container) { return false; } @Override public void postLayout(IFigure container) { } @Override public void remove(IFigure child) { if (child == figure) { clearHoverHandles(); cancelTimer(); figure.getParent().removeLayoutListener(removeListener); } } @Override public void setConstraint(IFigure child, Object constraint) { } }; if (figure != null) { figure.addMouseMotionListener(hoverListener); if (figure.getParent() != null) figure.getParent().addLayoutListener(removeListener); } } /** * Adds the handles to the handle layer. */ protected void addHoverHandles() { clearHoverHandles(); handleLayer = getLayer(LayerConstants.HANDLE_LAYER); handles = createHoverHandles(); for (int i = 0; i < handles.size(); i++) { IFigure handle = (IFigure) handles.get(i); handleLayer.add(handle); handle.addMouseMotionListener(handleListener); } } protected void clearHoverHandles() { if (handles == null) return; if (handleLayer == null) handleLayer = getLayer(LayerConstants.HANDLE_LAYER); for (int i = 0; i < handles.size(); i++) { IFigure handle = (IFigure) handles.get(i); try { handleLayer.remove(handle); } catch (Exception e) { e.printStackTrace(); } if (handleListener != null) handle.removeMouseMotionListener(handleListener); } handles = null; } protected void cancelTimer() { if (timer != null) { timer.cancel(); } } protected void startTimer() { if (!hovering) return; if (timer != null) { timer.cancel(); } timer = new Timer(true); timer.schedule(new TimerTask() { public void run() { Display.getDefault().syncExec(new Runnable() { public void run() { clearHoverHandles(); } }); } }, TIME_INTERVAL); } protected abstract List<Handle> createHoverHandles(); }

 

代码有点多,不熟悉Policy的话,可以先从activate()方法读起。这个Policy的作用是为hostFigure(就是MVC中的Viewer部分,也是该policy的宿主)添加监听,通过一个Timer来控制handle的展示和消失。

该类为abstract类型,其实现子类需要提供createHoverHandles()的实现,该方法返回一个List<Handle>。

如此,就可以把handle的效果和这个Policy结合起来了。

 

 

下面再提供一个利用CommonHoverEditPolicy实现预览效果的例子。

先看效果图:

1、这是一个普通的GEF编辑器:

 

 

2、其中的每一个节点内容是被另一个表格编辑器所确定的:

 

3、当鼠标移动到节点上,稍作停留,便会弹出一个预览框:

 

该预览框具备之前的表格编辑器的所有浏览功能,可以点击,可以切换子页。

实现方式:

1、重写CommonHoverEditPolicy的createHoverHandles()方法。

TablePreviewDialog dialog = null;

    @Override
    protected List<Handle> createHoverHandles() {
        if (dialog != null && !dialog.close()) {
            dialog.close();
        }
        try {
            BtdFormEditor editor = new BtdFormEditor(false);
            ModelEditorInput input = new ModelEditorInput(
                    (IBaseModel) getHost().getModel());
            IWorkbenchWindow dw = PlatformUI.getWorkbench()
                    .getActiveWorkbenchWindow();
            editor.init(new MultiPageEditorSite((MultiPageEditorPart) dw
                    .getActivePage().getActiveEditor(), editor), input);
            dialog = TablePreviewDialog.getTablePreviewDialog(editor);
            dialog.open();
        } catch (PartInitException e) {
            e.printStackTrace();
        }
        return new ArrayList<Handle>();
    }

可以看到,这里并没有提供可用的Handle(List<Handle>的内容是空的)。但是我们提供了一个Dialog,该Dialog为单例模式,通过对它的close和open控制,来实现handle一样的效果。使用dialog而非handle的主要原因是,handle是基于draw2d的,内容需要绘制,但是我们需要的内容是一个SWT\Jface构成的表格编辑器。所以使用dialog比较合适。

 

TablePreviewDialog定义如下:
/**
 * 表格内容预览
 * 
 * @author caiyu
 * @date 2012-8-17
 */
public class TablePreviewDialog extends Dialog {
    private static TablePreviewDialog INSTANCE = null;

    public static TablePreviewDialog getTablePreviewDialog(FormEditor editor) {
        if (INSTANCE != null) {
            INSTANCE.setEditor(editor);
            return INSTANCE;
        }
        INSTANCE = new TablePreviewDialog(editor);
        return INSTANCE;
    }

    private int x;
    private int y;
    private int width = 560;
    private int height = 420;

    private FormEditor editor;

    private TablePreviewDialog(FormEditor editor) {
        super(Display.getDefault().getActiveShell());
        this.editor = editor;
        setRectangle(getRectangle());
    }

    protected Control createContents(Composite parent) {
        // create the top level composite for the dialog
        Composite composite = new Composite(parent, 0);
        GridLayout layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        layout.verticalSpacing = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
        applyDialogFont(composite);
        // initialize the dialog units
        initializeDialogUnits(composite);
        // create the dialog area and button bar
        dialogArea = createDialogArea(composite);

        getShell().addShellListener(new ShellAdapter() {
            public void shellDeactivated(ShellEvent e) {
                close();
            }
        });
        return composite;
    }

    protected Rectangle getRectangle() {
        Rectangle rectangle = Display.getCurrent().getBounds();
        rectangle.x = Display.getCurrent().getCursorLocation().x;
        rectangle.y = Display.getCurrent().getCursorLocation().y;
        return rectangle;
    }

    public void setEditor(FormEditor editor) {
        this.editor = editor;
        setRectangle(getRectangle());
    }

    public void setRectangle(Rectangle rectangle) {
        this.x = rectangle.x;
        this.y = rectangle.y;
        int max_width = rectangle.width;
        int max_height = rectangle.height;
        if (x + width > max_width) {
            x = x - width;
        }
        if (y + height > max_height) {
            y = y - height;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets
     * .Composite)
     */
    protected Control createDialogArea(Composite parent) {
        parent.setLayout(new GridLayout(1, false));

        parent.addMouseListener(new MouseAdapter() {
            public void mouseUp(MouseEvent e) {
                // okPressed();
            }
        });
        parent.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent e) {
                if (e.keyCode == SWT.ESC)
                    okPressed();
            }
        });

        Composite client = new Composite(parent, SWT.NONE);
        client.setLayout(new FillLayout());
        client.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        editor.createPartControl(client);
        return parent;
    }

    protected Point getInitialLocation(Point initialSize) {
        return new Point(x, y);
    }

    protected Point getInitialSize() {
        return new Point(width, height);
    }

    protected int getShellStyle() {
        return SWT.NO_TRIM;
    }

    protected void createButtonsForButtonBar(Composite parent) {

    }

    protected void okPressed() {
        // toolkit.dispose();
        super.okPressed();
    }

    public void dispose() {
        okPressed();
    }
}

 

以上,即完成了为GEF添加一个预览策略及内容。

 

目录
相关文章
|
7月前
|
Shell Linux Apache
学习Nano编辑器:入门指南、安装步骤、基本操作和高级功能
学习Nano编辑器:入门指南、安装步骤、基本操作和高级功能
1006 0
|
4月前
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
|
4月前
|
Unix Linux 程序员
【Linux学习】vim编辑器的使用
【Linux学习】vim编辑器的使用
196 0
|
6月前
|
IDE 编译器 开发工具
C语言学习准备-编辑器选择
本来是想给大家继续更新C语言经典案例,但是有朋友反应C语言编辑器的选择,刚好我自己也是想更换一下C语言的编辑器,跟大家分享一下之前的使用感受,以及目前新的一些感受。
60 0
C语言学习准备-编辑器选择
|
Go
Go安装及编辑器配置【我的go学习第一课】
Go安装及编辑器配置【我的go学习第一课】
110 0
|
存储 移动开发 JSON
如何实现H5可视化编辑器的实时预览和真机扫码预览功能
所见即所得的设计理念在WEB IDE领域里一直是备受瞩目的功能亮点, 也能极大的提高** web coder的编程体验和编程效率. 笔者接下来就将对H5可视化编辑器的实时预览和真机扫码预览**功能做一次方案剖析, 为大家在设计类似产品的时候提供一些思路. 我们还是基于笔者开发的 H5-Dooring可视化编辑器作为案例来分析上述功能实现.
315 0
使用HBuilder X编辑器安装终端窗口插件未响应的解决方案
使用HBuilder X编辑器安装终端窗口插件未响应的解决方案
|
前端开发 Windows
JavaWeb学习之路(11)--VSCode来了,超好用的代码编辑器,详细安装过程
本文目录 1. 编辑器 2. 编辑器是干啥的 3. VSCode编辑器的特长 4. VSCode下载与安装 5. VSCode安装 6. 小结
259 0
|
JavaScript 前端开发
技能学习:学习使用Node.js + Vue.js,开发前端全栈网站-10.vue的富文本编辑器(vue2-editor)
文章的发布功能中,我们希望像写文档一样发布一整篇带标题、分段、加粗等效果的文章,而不是单纯的一段文本,这时就需要用到富文本编辑器。富文本编辑器有很多版本,他们样式不同,使用方法不同。 本篇这里我们在npm下载并使用vue相关的富文本编辑器:vue2-editor。
289 0
技能学习:学习使用Node.js + Vue.js,开发前端全栈网站-10.vue的富文本编辑器(vue2-editor)
|
Unix Linux 开发工具
Linux 学习VI编辑器
命令模式、插入模式 :wq u 回退 :q! :w /root/file 保存到别的地方 执行系统指令 :!rm xxxx :!df -h :!ls /tmp 移动:hjkl 4l 设置行距::set wm=10 :0 :$ :set nu 显示...
1144 0