zoukankan      html  css  js  c++  java
  • RCP学习:GEF编辑器的鼠标的hover policy以及一个预览窗口效果

    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添加一个预览策略及内容。
  • 相关阅读:
    每日随笔
    每日随笔
    每日随笔
    JavaSE 类加载机制
    MySQL 索引
    JavaSE 线程的生命周期
    JVM堆内存(heap)详解
    Redis 学习笔记(三)哨兵模式配置高可用和集群
    sqlserver数据库连接数相关问题
    多项式多点求值
  • 原文地址:https://www.cnblogs.com/anrainie/p/2651978.html
Copyright © 2011-2022 走看看