GEF实践总结(五)大小调整、按键监听、撤销重做

一. 目标

  1. 能够选中Table,移动Table的位置,调整Table的大小。
  2. 可以支持撤销Undo和重做Redo。


二. 给DataBase书写XYLayoutEditPolicy
书写一个DataBaseXYLayoutEditPolicy 类继承与XYLayoutEditPolicy

public class DataBaseXYLayoutEditPolicy extends XYLayoutEditPolicy {
@Override
protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
return null;
}
@Override
protected Command getCreateCommand(CreateRequest request) {
return null;
}
}

 

将其注册于DataBaseEditPart

@Override
protected void createEditPolicies() {
installEditPolicy(EditPolicy.LAYOUT_ROLE, new DataBaseXYLayoutEditPolicy());
}
 


启动后查看效果:


好了,就这么简单,已经可以选中Table了,选中后会出现边框,而且边框还有8个可用于调整大小的瞄点出现。


问题一: 为什么为了操作Table,而去给DataBase注册LayoutEditPolicy呢?
这是由于LayoutEditPolicy是用于对它上面的子EditPart而言的,这就SWT中给Composite设置GridLayout或FillLayout,具体怎么布局也是对于Composite上的子控件而言的。


问题二: 为什么注册了LayoutEditPolicy就会有选择框呢?
关心的话,可以去看ConstrainedLayoutEditPolicy.createChildEditPolicy的具体方法。


三. 书写Table执行调整大小的Command

public class TableChangeConstraitCommand extends Command {
private TableModel table;
private Rectangle oldRect;
private Rectangle newRect;
public TableChangConstraitCommand(TableModel table, Rectangle newRect) {
this.table = table;
this.newRect = newRect;
}
@Override
public void execute() {
oldRect = new Rectangle(table.getX(), table.getY(), table.getW(), table.getH());
table.setXYWH(newRect.x, newRect.y, newRect.width, newRect.height);
}
@Override
public void undo() {
table.setXYWH(oldRect.x, oldRect.y, oldRect.width, oldRect.height);
}
}
 



Command 用于具体执行对模型的修改:

  1. execute() 执行操作,在这里就是执行大小或位置调整,并保存旧的现场。
  2. undo()    撤销操作,其实就是从前面保存的现场,恢复到原来的大小和位置。
  3. redo()    重新执行 (如果不覆盖,其实就是执行execute方法)


这就是设计模型里面的Command模式,Command对象在被执行后,会保存在EditDomain CommandStack 中,用以支持Ctrl+Z的undo撤销操作,或者Ctry+Y的redo重新执行。

四. 改写DataBase的XYLayoutEditPolicy,支持大小调整

public class DataBaseXYLayoutEditPolicy extends XYLayoutEditPolicy {
@Override
protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
TableModel table = (TableModel) child.getModel();
Rectangle rect = (Rectangle) constraint;

TableChangeConstraitCommand command = new TableChangeConstraitCommand(table, rect);
return command;
}
让DataBaseXYLayoutEditPolicy在createChangeConstraintCommand方法中返回一个TableChangeConstraitCommand即可。
 


五. 启动,查看效果



六. 给GraphicalViewer注册KeyHandle

        KeyHandler keyHandler = new KeyHandler();
        graphicalViewer.setKeyHandler(new GraphicalViewerKeyHandler(graphicalViewer).setParent(keyHandler));
        keyHandler.put(KeyStroke.getPressed(SWT.F1, SWT.NONE), new RedoAction(this));
        keyHandler.put(KeyStroke.getPressed(SWT.F2, SWT.NONE), new UndoAction(this));


KeyHandle :是对于按键的监听
KeyHandle可以使用setParent方法将多个KeyHandle组成按键的监听链,按键的监听从最下面一个KeyHandle一直往上遍历,只要其中一个KeyHandle对某一按键监听了,就执行对应的Action。
KeyHandler通过KeyStorke(按键、复合按键) 和 Action进行对应。
注意: 按键有按下(getPressed)和弹起(getReleased)的区别。

  1. Command在执行后,都会被放入CommandStack。
  2. UndoAction其实就是在CommandStack中,找到最后执行过的Command,调用其Undo方法。
  3. 同样的,RedoAction就是在CommandStatck中,找到最后一次Undo的Command,执行其redo方法。


七. 为ViewPart返回CommandStack

由于RedoAction UndoAction 需要依赖CommandStack ,通过ViewPart.getAdapter(CommandStack.class) 获得CommandStack对象,于是,我们需要给ViewPart返回CommandStack 对象,而它又存在于在EditDomain 中。

    @Override
    public Object getAdapter(Class adapter)
    {
        if ( CommandStack.class.equals(adapter) )
        {
            return this.graphicalViewer.getEditDomain().getCommandStack();
        }
        return super.getAdapter(adapter);
    }

 

好了,完成了,在你调整完了Table的大小后,可以使用F1、F2进行撤销和重做。

八. 改用ActionRegistry
由于在其他地方还需要使用RedoAction UndoAction ,那么你可以考虑使用ActionRegister ,将Action对象初始化完毕后,再缓存在ActionRegister 里面。

        //
        actionRegistry.registerAction(new RedoAction(this));
        IAction action = actionRegistry.getAction(ActionFactory.REDO.getId());
        keyHandler.put(KeyStroke.getPressed(SWT.F1, SWT.NONE), action);
       
        actionRegistry.registerAction(new UndoAction(this));
        action = actionRegistry.getAction(ActionFactory.UNDO.getId());
        keyHandler.put(KeyStroke.getPressed(SWT.F2, SWT.NONE), action);
    }
   
    private ActionRegistry actionRegistry = new ActionRegistry();
 



九. 其他
问题: 为什么按键选用F1和F2,而不是通常的Ctrl+Z和Ctrl+Y
是由于复合按键比单按键复杂,可以见我的另一篇博客。

十. 总结

  1. 认识了XYLayoutEditPolicy和简单的Command
  2. 认识了和Action想关的KeyHandle、KeyStroke、CommandStack、ActionRegistry

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值