[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[整理]RCP开发,笔记整理

上一篇:[整理]不停ping一个IP地址的VB代码。
下一篇:[转帖]Key Bindings in Eclipse Editors

添加日期:2012/11/23 11:02:00 快速返回   返回列表 阅读8623次
------------------------------------
RCP,Rich Client Platform

这里特指eclipse RCP开发
------------------------------------------
Eclipse是核心+一堆插件构成的,所谓的RCP开发
类似于在Eclipse核心的基础上进行扩展,
开发出的程序具有Eclipse的界面风格,可以独立运行。
当然仍然需要Java运行环境。
------------------------------------------
Application,是可运行程序,是一个应用程序的入口,相当于一个类的main方法。
一个RCP可以有多个Application,但是运行时,仍然要指定运行哪个。
Application是org.eclipse.core.runtime.applications的扩展点。

----------------
public class Application implements IApplication {
  public Object run(Object args) throws Exception {
Display display = PlatformUI.createDisplay();
    try {
int returnCode = PlatformUI.createAndRunWorkbench(
display, new ApplicationWorkbenchAdvisor());
      if (returnCode == PlatformUI.RETURN_RESTART) {
        return IApplication.EXIT_RESTART;
      return IApplication.EXIT_OK;
    } finally {
      display.dispose();
    }
  } 
}
----------------
默认生成的代码,是创建了一个Display对象,打开了一个窗口界面。使用了ApplicationWorkbenchAdvisor。
也可以不创建界面,想写什么就写什么。

------------------------------------------
ApplicationWorkbenchAdvisor,工作台顾问,
指定初始化使用的透视图perspective,即窗口布局。
指定使用哪个ApplicationWorkbenchWindowAdvisor。
------------------------------------------
Perspective,透视图,即窗口布局
public class Perspective implements IPerspectiveFactory {
    public void createInitialLayout(IPageLayout layout) {
        
        String area = layout.getEditorArea();
        layout.addView("vvvvv", IPageLayout.LEFT, 0.5f, area);
    }
}
实现IPerspectiveFactory接口,
透视图ID和类的对应关系,在plugin.xml中定义。
一个RCP程序可以有多个透视图,但同一时刻只能使用一个。
-------------------------------------------
ApplicationWorkbenchWindowAdvisor,窗口顾问,
在某些时机操作窗口,如窗口打开之前,窗口要关闭时,创建窗口内容时,等等……
类似于窗口事件触发的方法都在这里。

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {

    public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
        super(configurer);
    }

    public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
        return new ApplicationActionBarAdvisor(configurer);
    }
    
    public void preWindowOpen() {
        IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
        configurer.setInitialSize(new Point(400, 300));
        configurer.setShowCoolBar(false);
        configurer.setShowStatusLine(false);
        configurer.setTitle("Hello RCP"); //$NON-NLS-1$
    }
}
------------------------------------------
ActionBarAdvisor,动作条顾问,
通过workbenchWindowAdvisor的createActionBarAdvisor()方法创建。

public class ApplicationActionBarAdvisor extends ActionBarAdvisor {
  public ApplicationActionBarAdvisor(IActionBarConfigurer c) {
    super(configurer);
  }
  protected void makeActions(IWorkbenchWindow window) {
  }
  protected void fillMenuBar(IMenuManager menuBar) {
  } 
}
----------------------------------------------
记住窗口的位置和大小。
在ApplicationWorkbenchAdvisor中覆盖WorkbenchAdvisor类的initialize方法。
public void initialize(IWorkbenchConfigurer configurer) {
    configurer.setSaveAndRestore(true);
}
即可,父类的initialize方法do nothing。

不加,貌似也没问题,位置和大小能记住。
-----------------------------------------------
在RCP中,用户通过View和Editor与程序进行交互,透视图就是用来组织这二者的东西。
------------------------------------------------
添加View:
打开plugin.xml,进入Extensions页,在org.eclipse.ui.views下追加view即可。
把详细中的id,name,class等等填一下即可。

然后把对应的类写一下,继承org.eclipse.ui.part.ViewPart即可
public class ViewWawa extends org.eclipse.ui.part.ViewPart {
    @Override
    public void createPartControl(Composite parent) {
        Label xx = new Label(parent,SWT.NONE);
        xx.setText("哇哇");
    }

    @Override
    public void setFocus() {
        // TODO Auto-generated method stub
    }
}

创建View以后,要在透视图中追加才行,否则不会显示出来。
在Perspective的createInitialLayout方法中追加。
public class Perspective implements IPerspectiveFactory {

    public void createInitialLayout(IPageLayout layout) {
        //追加View
        String area = layout.getEditorArea();
        layout.addView("viewGaGa", IPageLayout.LEFT, 0.5f, area);
    }
}
使用addView方法,添加的是TAB页,可以被移动,关闭等等,
使用addStandaloneView方法,则是单独的一个页。
layout.addStandaloneView("viewGaGa", false,IPageLayout.LEFT, 1.0f, area);
false是不显式TAB的title。
----------------------------------------------------
Editor不能被追加到视图中,而是指定Editor在视图的那个区域显示。
layout.setEditorAreaVisible(false);
可以不显示编辑器区域。
---------------------------------------------------
工作台关闭时,会保存视图的设置。
为了调试,应该在Run Configurations的Main中选中clear workspace。
否则打开还是上次的样子。
---------------------------------------------------
Dependencies页是运行时所依赖的包,不是编译时需要的。
是写在META-INF/MANIFEST.MF文件中的,Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime
修改这个列表,会自动修改build path引用的jar包。

Runtime页是指定META-INF/MANIFEST.MF文件中的Bundle-ClassPath块的。
-----------------------------------------------------
Table table = tv.getTable(); //tv是一个TableViewer对象
TableItem item = table.getItem(0); //得到第1行
Color color =Display.getDefault().getSystemColor(SWT.COLOR_RED);//红色
item.setBackground(1, color); //设置此行的第2列为红色
table.redraw(); //重画界面
------------------------------------------------------
Eclipse RCP框架中,每个view都是独立的,在一个view中没法直接得到另一个view的实例,
要实现view之间的交互需要一些特殊手段,如通过selection监听器监听其他视图的selection事件,
详细使用可参考http://www.cnblogs.com/zephyr/archive/2008/05/30/1210477.html。

本例中实现的是点击左边SWT的导航树,同步选中右边TWaver的对应的树节点,要实现这样的功能,要求右边的视图能监听左边视图的变化事件,首先我们在NavigationView中注册导航树为事件提供者:
注意下面的这行代码:this.getSite().setSelectionProvider(treeViewer);其作用是向系统提供一个消息源,这样当这个树选中变化时,别的视图就可以监听到这些事件

1
public void createPartControl(Composite parent) {
2
        treeViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
3
        ...
4
        this.getSite().setSelectionProvider(treeViewer);
5
        ...
6
    }
然后在View视图中监听上面的消息源

1
public void createPartControl(Composite parent) {
2
    ...
3
    this.getSite().getPage().addSelectionListener(NavigationView.ID, new ISelectionListener() {
4
        public void selectionChanged(IWorkbenchPart arg0, ISelection arg1) {
5
            ...
6
        }
7
    });
8
    ...
9
}
通过以上两步就实现了视图View监听视图NavigationView中变化事件的功能,同理,如果需要在NavigationView视图中监听View视图中的事件,则需要注册View为事件源,然后在NavigationView中监听该事件,有了这种消息传递机制,我们就可以实现各个视图间的通信了,而具体同步的代码我这里就不多说了。
------------------------------------------------------
When your form page is instantiated, you need to add it to something in order to get notified of page changes. In MultiPageEditorPart they use org.eclipse.jface.dialogs.IPageChangedListener.

formEditor.addPageChangedListener(page);
--------------------------------------------
MultiPageEditor中的每一个页面,可以是一个Editor,也可以是任何的一个SWT Composite。创建多页面的Editor,首先需要继承MultiPageEditorPart。在MultiPageEditorPart的createPages()方法中创建每一个Page。创建Page的方法有两种,一种是使用addPage(IEditorPart,IEditorInput),接受一个Editor对象(创建这个Editor对象直接进行new XXXEditor()即可),另一种是使用addPage(Control control)。创建这个control时,使用getContainer()所得到的容器作为这个Composite的parent即可。而这个作为container的parent,可以想象的到,实际上就是一个CTabFolder。

这个CTabFolder在创建Editor时被自动创建,并将其addSelectionListener的响应事件,映射到MultiPageEditor的pageChange()方法上。因此,例如要同步不同页面之间的内容,如果要监听页面切换的事件响应,只需实现pageChange()方法即可。
----------------------------------------
在GEF的开发中,多页标签编辑器是一种常见的实现,其实现主要是继承MultiPageEditorPart或者FormEditor来实现,在实现的子类中加入自定义的Editor或者page。
一、继承MultiPageEditorPart
具体步骤如下:
a、自定义继承MultiPageEditorPart的CustomMultiPageEditor
b、在其中调用createPages()方法,来创建多个页面[int org.eclipse.ui.part.MultiPageEditorPart.addPage(IEditorPart editor, IEditorInput input) throws PartInitException],通过这个方法加入自己的编辑器
二、继承FormEditor
具体步骤如下:
a、自定义继承FormEditor的CustomMultiEditor
b、在其中调用addPage()方法,来创建多个页面[public int addPage(IEditorPart editor, IEditorInput input)],d调用这个方法增加自己的编辑器
三、关于保存
在实现多页编辑器之前,其内嵌的Editor已经重载了doSave()的方法。在多页编辑器中重载doSave()方法,调用getEditor(this.nowPageIndex).doSave(monitor)来实现保存。
 
以上步骤虽然实现了多页编辑器,但是在编辑器和文本之间的同步并未实现,这是下一步要考虑的,目前还没有思路
--------------------------------------
在FormEditor中,
getActiveEditor() 返回当前激活的editor,如果当前页不是editor,那么将返回null。
getActivePage() 返回当前激活的页的index,不管当前页是editor还是FormPage,都能返回。
getActivePageInstance() 返回当前激活的FormPage,如果当前页不是FormPage(比如是editor),那么将返回null。
getEditor(pageIndex) 根据页面index,返回对应的editor,如果此页不是editor,将返回null。
getSelectedPage() 被选择的页,页面切换时用,与getActivePageInstance方法相同。
getCurrentPage(),返回当前页的index,页面切换时,返回old页的index.

注意:
addPage(IFormPage page)添加的是FormPage
addPage(IEditorPart editor, IEditorInput input) 添加的是editor,
其实,FormPage也是EditorPart的子类。但是addPage(IFormPage page)时,只是把它的control添加进来了。
----------------------------------------
addPage(IEditorPart editor, IEditorInput input)时,就调用了editor的init方法,这样有错的话,就直接抛出来了,界面还未创建。
然后调用editor的createPartControl()方法创建editor的界面,然后加一个Tab页,将editor放入。
-----------------------------------------
我的理解:
FormEditor中,还是add的editor是主力,它完成编辑的任务。
其它的FormPage页只是一种辅助,比如各种形式的展现什么的~~
这些FormPage页应该从主力editor取得数据,直接使用引用就好了,然后显示什么的~~
即使有更改,因为是引用,主力editor中数据自然就变化了,至于界面,需要切换回主力editor时刷新一下吧。怎么触发?
----------------------------------------
Grid布局就是按控件声明顺序挨个往格里放
-----------------------------------
View可以在plugin.xml中通过perspectiveExtensions添加即可,不是非要在Perspective.java中写。

   <extension
         id="aaa"
         point="org.eclipse.ui.perspectiveExtensions">
      <perspectiveExtension
            targetID="*">
         <view
               id="com.xxxxx.tools.commandLine.editor.view.TelnetResultView"
               minimized="false"
               ratio="0.5f"
               relationship="stack"
               relative="org.eclipse.ui.console.ConsoleView"
               visible="true">
         </view>
      </perspectiveExtension>
   </extension>
不过View只是添加上了,必要时要在代码中给它显示出来。
    IWorkbenchPage page = this.getSite().getPage();
    IViewPart view = null;
    try {
        view = page.showView(TelnetResultView.ID);
    } catch (PartInitException e1) {
        e1.printStackTrace();
    }
----------------------------------------------------
打包出来的plugin下有哪些jar包,是mainframe的product定义里
增加的那些jar包~~
也就是说,缺哪个,就增加好了~~
没必要用ant去copy~~
-------------------------

----------------------------------------------------------------
程序说明:在表格中,界面中显示的数据和setInput(Object input)传入的input对象是分离的。也就是说如果input对象中的记录数据发生改变,要调用表格的tv.refresh()或tv.update(Object element, String[] properties)才能在界面上也显示新的数据。refresh、update两个更新界面的方法中:前者是全面更新;后者是只更新某一条记录(element)在界面上的显示,后者的第二个参数甚至还可以指定更新哪几个字段的界面显示,显然后者更新效率要高些。
================================================================
doSave(IProgressMonitor)—Saves the contents of this editor. If 
thesave is successful, the part should fire a property changed event 
(PROP_DIRTY property), reflecting the new dirty state. If the save is 
canceled via user action, or for any other reason, the part should 
invoke setCanceled on the IProgressMonitor to inform the caller 
(see Section 9.4, Progress Monitor, on page415).
=================================================================
public void setFocus() {
   switch (getActivePage()) {
      case 0:
         treeViewer.getTree().setFocus();
         break;
      case 1:
         textEditor.setFocus();
         break;
   }
}=================================
Whenever a user enters an invalid value, you have to decide how the user
will be notified that the value is invalid. In this case, add an ICellEditor-
Listener in the initTreeEditors() method so that the error message will
appear in the window’s status line (see Figure 8–7). For a more prominent
error message, the editor’s header area could be redesigned to allow an error
image and message to be displayed just above the tree rather than in the work-
bench’s status line.
==============================
protected void pageChange(int newPageIndex) {
   switch (newPageIndex) {
      case 0 :
         if (isDirty())
            updateTreeFromTextEditor();
         break;
      case 1 :
         if (isPageModified)
            updateTextEditorFromTree();
         break;
   }
   isPageModified = false;
   super.pageChange(newPageIndex);
}
=========================
treeViewer.getTree().addKeyListener(new KeyListener() {
      public void keyPressed(KeyEvent e) {
         if (e.keyCode == SWT.ALT)
            isAltPressed = true;
         if (e.character == SWT.DEL)
            removeAction.run();
      }
----------------------------
先设置展开层数,然后追加列,最后再setInput(),这个方法里面就开始构建TreeItem了,里面要取列的数量。
如果setInput()在前,第一层的取到的列就是1了(如果列是0,就按1算)。
--------------------------------
通过ACTION的ID来获得ACTION
文章分类:Java编程
现在又很多需求都需要动态去改变Action的enable/disenable,其实很简单,只需要在构造Action的时候加入setActionDefinitionId(actinDefID);就可以了,然后就可以通过ID来获得Action了getActionRegistry().getAction(actionID); 
还有种方法,那就是Map了,运用键值对的关系set进去,这种方法好像是eclipse源代码里经常用到的,我也是通过翻看了源代码才知道的,不过这个方法是GEF的,那么在RCP/SWT环境下怎么做呢?RCP环境下的Action都是jface的Action,jface里有个IContributionManager接口用来管理菜单的,里面有个find方法得到MenuManager,得到MenuManager之后再用MenuManager中的find方法得到Action
----------------------------------
A工程暴露包,B工程buildPath引用A工程即可,然后在依赖里加入A工程名字即可。
-----------------------------------
设置TreeViewer的前景色和背景色
让TreeViewerLabelProvider实现IColorProvider中的getBackground和getForeground方法即可
-----------------------------------
将treeViewer的根节点设置为默认展开
treeViewer.setExpandedState(treeViewer.getTree().getItems()[0].getData(), true);
-----------------------------------
     IActionBars bars = getViewSite().getActionBars();
        fillLocalPullDown(bars.getMenuManager());
        fillLocalToolBar(bars.getToolBarManager());
----------------------------
    protected void updateStatusline(SelectionChangedEvent event) { 
        IStatusLineManager statusline = this.getViewSite().getActionBars().getStatusLineManager(); 
        IStructuredSelection selection = (IStructuredSelection) event.getSelection(); 
        String msg = getSelectionMessage(selection); 
            System.out.println("\t选择了:"+msg);
            statusline.setMessage(msg); 
        }
-----------------------------
拖拽
final Transfer[] transfer=new Transfer[]{LocalSelectionTransfer.getTransfer()};
        
        treeViewer.addDragSupport(DND.DROP_MOVE, transfer, new DragSourceAdapter (){

            @Override
            public void dragSetData(DragSourceEvent event) {
                // TODO Auto-generated method stub                ((LocalSelectionTransfer)transfer[0]).setSelection((IStructuredSelection)treeViewer.getSelection());
                event.data=((IStructuredSelection)treeViewer.getSelection()).getFirstElement();
                event.doit = true;
            }

            @Override
            public void dragFinished(DragSourceEvent event) {
                // TODO Auto-generated method stub
            }

            @Override
            public void dragStart(DragSourceEvent event) {
                // TODO Auto-generated method stub
                
            }
        });
treeViewer.addDropSupport(DND.DROP_MOVE, transfer, new ViewerDropAdapter(treeViewer){

            @Override
            public boolean performDrop(Object data) {
                // TODO Auto-generated method stub
                getCurrentLocation();
                Element element=(Element)getCurrentTarget();
                IStructuredSelection selection=(IStructuredSelection)data;
                Element elemented=(Element)selection.getFirstElement();
                System.out.println("element:"+element.getAttribute("name"));
                System.out.println("drop:"+elemented.getAttribute("name"));
                element.appendChild(elemented);
                treeViewer.refresh();
                return true;
            }

            @Override
            public boolean validateDrop(Object target, int operation,
                    TransferData transferType) {
                // TODO Auto-generated method stub
                return true;
            }
            

        });

// TODO Auto-generated method stub ((LocalSelectionTransfer)transfer[0]).setSelection((IStructuredSelection)treeViewer.getSelection());
这个要这样的
// TODO Auto-generated method stub   
((LocalSelectionTransfer)transfer[0]).setSelection((IStructuredSelection)treeViewer.getSelection())
===============================================
经过自己努力尝试,问题解决了,这里跟大家共享一下:
由于每次创建节点图标都是新建的:Image image= getImageDescriptor(path).createImage();
而图标是属于用户对象,刷新节点是就的节点对象虽然被销毁,但是这种系统用户对象是不被销毁的,所以导致系统资源泄漏,从任务管理器可以看到user对象涨到5000多时界面刷新就有问题了,大家可以试试
================================================
Tree结构对应的Data要实现hashCode()和equals()方法,否则刷新时,Tree的状态不会保持住。
这两个方法很重要!!!
TreeViewer会把数据对象与TreeItem的映射保存到hashMap中,刷新、编辑时要比较两个数据对象是否相等。
hashCode()和equals()方法要把两个节点完全区分开才行,所以里面要考虑节点的位置因素。
两个节点对象的值完全一样,但是位置是不一样的,那么他们两个就不相等。

现在的算法还有重复的可能。
===============================================
public Object getColumnValue(String fieldName) {
}
对于要编辑的列,该方法不要返回null。
点击该列时,会先getValue,然后set进cellEditor,是null的话,会报错。
=================================================
buttonOK.addListener(SWT.Selection, new Listener() {
      public void handleEvent(Event event) {
        shell.dispose();
      }
    });
=================================================
hexInput = new Text(this, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
Text控件自己就支持滚动条!!!
==================================================
String.Format("0x%02x",ch);
====================================================
// Allow backspace and delete
if (event.character == '\u0008' || event.character == '\u007F') {
  event.doit = true;
}
======================================================
文本框A的modify事件中,更新另一个文本框B时,会激发B的modify方法。
如果B的modify方法里又更新了文本框A的内容,那么又会触发A的modify事件。
成了一个循环了。

一个解决办法就是:先remove掉listener,然后更新内容,然后再把listener追加回来。
=========================================================
getButton(IDialogConstants.OK_ID).setEnabled(false);
setErrorMessage(null);
======================================================
取得光标位置,真变态!
int start = t.getSelection().x;

setTextWithoutListener(t,hexInput);
t.setSelection(start);
=====================================================
选择Tree中的所有节点
tv.getTree().selectAll();
===============================
CellEdit的Text,点击一下默认是选中所有文本,可以修改以下:
        Text text = (Text) cellEditor[0].getControl();
        text.addFocusListener(new FocusAdapter(){
            
            @Override
            public void focusGained(FocusEvent e) {
                Text text = (Text)e.widget;
                text.setSelection(text.getText().length());
                
            }
            
        });
下拉框点一下就展开。
CCombo combo = (CCombo) cellEditor[1].getControl();
combo.addFocusListener(new FocusAdapter(){
    
    @Override
    public void focusGained(FocusEvent e) {
        CCombo combo = (CCombo)e.widget;
        combo.setListVisible(true);
        
    }
    
});
===========================================
更新界面的,要异步
getControl().getDisplay().asyncExec(new Runnable() {

    public void run() {
        ((CCombo) getControl()).setListVisible(true);
    }

});
============================================
keybindings will follow the pattern: binding->command->handler. In the 
case that you already have an IAction that works, using 
jface.ActionHandler can create a bridge (you can use a window or 
IWorkbenchPartSite, depending on your level). So in a view: 

IHandlerService hs 
= (IHandlerService) getSite().getService(IHandlerService.class); 
hs.activateHandler("command.id", new ActionHandler(menuAction)); 

If you are in your ActionBarAdvisor, setting the action definition id 
and using register(IAction) will do the work for you. 
=======================================
valueEditComposite.getHexBt().addSelectionListener(new SelectionAdapter() {
    public void widgetSelected(SelectionEvent evt) {
        Button button = (Button)evt.widget;
        if(button.getSelection()){
            changeFormat(true);
        }
    }
});
选择状态变化,就触发。
============================================
Command的ID的常量
org.eclipse.ui.IWorkbenchCommandConstants

Constants for all commands defined by the Eclipse workbench
--------------------------------------------------
Status status = new Status(IStatus.ERROR, "My Plug-in ID", 0,
            "Status Error Message", null);
        ErrorDialog.openError(Display.getCurrent().getActiveShell(),
            "JFace Error", text.getText(), status);
-------------------------------------------------------------------
在 wizard类里复写performFinish方法时加入
public boolean performFinish(){
        try{
            this.getContainer().run(true, false, new IRunnableWithProgress()            {public void run(IProgressMonitor monitor)
                        throws InvocationTargetException, InterruptedException
                {monitor.beginTask("正在生成汇总...",
                            IProgressMonitor.UNKNOWN);
                    // 下面的代码写业务逻辑,别忘了调用monitor.worked(..)让进度条前进
                    monitor.worked(IProgressMonitor.UNKNOWN);
                
                    monitor.done();
}
});
    return true;
} catch (InvocationTargetException e){
            // 异常处理
        } catch (InterruptedException e)
        {
            ;//
        }
        return false;
    }
---------------------------------------------------------------
我在GraphicalViewer中增加了 
protected KeyHandler initSharedKeyHandler() { 
if (sharedKeyHandler == null) { 
sharedKeyHandler = new KeyHandler(); 
sharedKeyHandler.put(KeyStroke.getReleased('', 97, SWT.CTRL), editor.getActionRegistry().getAction(ActionFactory.SELECT_ALL.getId())); 
sharedKeyHandler.put(KeyStroke.getReleased('', 121, SWT.CTRL), editor.getActionRegistry().getAction(ActionFactory.REDO.getId())); 
sharedKeyHandler.put(KeyStroke.getReleased('', 122, SWT.CTRL), editor.getActionRegistry().getAction(ActionFactory.UNDO.getId())); 
sharedKeyHandler.put(KeyStroke.getPressed(SWT.DEL, 127, 0), editor.getActionRegistry().getAction(ActionFactory.DELETE.getId())); 


return sharedKeyHandler; 

这样的一个方法之后我的editor可以使用undo/redo了,但是有个问题就是只有editor获得焦点的时候才起作用。
------------------------------------------------------------------
                                      action = new UndoAction(this);
        action.setActionDefinitionId(ActionFactory.UNDO.getCommandId());
        getActionRegistry().registerAction(action);
        getStackActions().add(action.getId());

        action = new RedoAction(this);
        action.setActionDefinitionId(ActionFactory.REDO.getCommandId());
        getActionRegistry().registerAction(action);
        getStackActions().add(action.getId());
-------------------------------------------------------------------
1.在GEF中使用Command来完成undo操作的:
org.eclipse.gef.commands.Command
org.eclipse.gef.commands.CompoundCommand这是一个redoAll/undoAll的操作,内含一个list.
org.eclipse.gef.commands.CommandStack命令栈

2.纯SWT的例子,用linkedList模拟栈来实现:
http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/SWTUndoRedo.htm

3.在org.eclipse.core.commands中,采用的是:IUndoableOperation和IOperationHistory
参见例子:
http://www.java-forums.org/eclipse/15550-beginner-eclipse-rcp-undo-redo-operation.html
调试:
1).扩展点org.eclipse.ui.actionSets/actionSet下要注意visible="true"
2).要创建一个view在createPartControl(Composite parent)中       
IWorkbench workbench = this.getViewSite().getWorkbenchWindow().getWorkbench();
3).注意这个的使用:menuMgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
框架讲解:
http://dev.eclipse.org/viewcvs/index.cgi/platform-ui-home/R3_1/undo-redo-proposal/undo-redo%20support.html?view=co
---------------------------------------------------------------------
// 后续操作不刷新界面
tv.getTree().setRedraw(false);

...........
tv.getTree().setRedraw(true);
--------------------------------------------------
A general rule in SWT is that no events are fired when
you change properties programmtically (The only exceptions are
SWT.Modify and SWT.Verify).
-------------------------------------------
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved