關於Eclipse插件開發(四)-------給視圖加下拉菜單和按鈕和加入編輯器.


本例將給視圖加入下拉菜單和按鈕,同時再為列表添加一個右鍵菜單.

創建ActionGroup類

加入菜單和按鈕的方法與SWT和JFace組件的一樣,先創建一個ActionGroup代碼如下:

 MyActionGroup.java

 

 1 public class MyActionGroup extends ActionGroup {
 2     // 加入按鈕
 3     public void fillActionBars(IActionBars actionBars) {
 4         if (actionBars == null)
 5             return;
 6         IToolBarManager toolBar = actionBars.getToolBarManager();
 7         toolBar.add(new Action1());
 8         toolBar.add(new Action2());
 9     }
10 
11     // 加入下拉菜單、右鍵彈出菜單
12     public void fillContextMenu(IMenuManager menu) {
13         if (menu == null)
14             return;
15         menu.add(new Action1());
16         menu.add(new Action2());
17     }
18 
19     private class Action1 extends Action {
20         public Action1() {
21             ImageDescriptor imageDesc = WorkbenchImages
22                     .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_NEW_PAGE);
23                     //.getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_HOME_NAV);
24             //這個地放原碼是想在在View1上顯示一個"小房子"的圖標.但是我參看IWorkbenchGraphicConstants的源碼
25             //沒有IMG_ETOOL_HOME_NAV這個常量字段.導入Eclipse也報錯,我就 換了一個.
26             setHoverImageDescriptor(imageDesc);
27             setText("Action1");
28         }
29 
30         public void run() {
31         }
32     }
33 
34     private class Action2 extends Action {
35         public Action2() {
36             ImageDescriptor imageDesc = WorkbenchImages
37                     .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_IMPORT_WIZ);
38             setHoverImageDescriptor(imageDesc);
39             setText("Action2");
40         }
41 
42         public void run() {
43             new LanguageDialog(null).open();
44         }
45     }
46 }

 

程序說明:

1.本程序中含有兩個Action類:Action1,Action2,和以往的Action不同之處在於它的圖像描述符是直接從Eclipse環境中取得.既然插件在Eclipse環境內運行,那么Eclipse本身的圖標就可以直接拿來使用,不過Eclipse會給出 一個警告:"建議不要訪問:由於對必須的庫...jar 具有一定的限制,一次不能訪問類型WorkbenchImages",這是因為該類internal包中,也就是說它僅局限於內部使用.

2.fillContextMenu方法比起以前單純的SWT編程少了幾句.在后邊的總結在紅中可以看到它移動到View1類中去了,主要原因是為了此方法兼顧添加視圖的下拉菜單.

 

修改View1類

在Viwe1中增加了3中方法,分別用來加入視圖的導航欄按鈕,下拉菜單,以及加入表List的右鍵菜單.代碼如下:

(下面的這個View1.java中也加入了編輯器對應的事件.雙擊視圖1的列表項,則打開對應的編輯器,因此在View1類的List對象添加一個鼠標雙擊視圖1的列表項,則打開對應的編輯器,一次在View1類的List對象添加一個鼠標雙擊事件監聽器.另外還要考慮到,如果已經打開了列表項對應的編輯器,則下次再雙擊時就不應再打開該項的編輯器,而是將其設成當前編輯器.)

得到編輯器對象:IEditorPart editor = IWorkbenchPage.findEditor(IEditorInput);

打開編輯器對象:IWorkbenchpage.openEditor(IEditorInput.editorID);

View1.java

public class View1 extends ViewPart {
    private List list; // 將列表寫成類的實例變量,以擴大它的可訪問范圍
    //注意這個List並不是java.util包下的.而是org.eclipse.swt.widgets.List;包下的.
    public void createPartControl(Composite parent) {
        IWorkbenchHelpSystem help = PlatformUI.getWorkbench().getHelpSystem();
        help.setHelp(parent, "cn.com.kxh.myplugin.buttonHelpId");
        Composite topComp = new Composite(parent, SWT.NONE);
        topComp.setLayout(new FillLayout());
        list = new List(topComp, SWT.BORDER);
        list.add("中國");
        list.add("美國");
        list.add("法國");
        // 列表選擇事件監聽
        list.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                // 由IWorkbenchPage獲得view2對象
                IWorkbenchPage wbp = getViewSite().getPage();
                //在插件中IWorkbenchPage對象比較重要,這里再給出一種獲得此對象的通用的方法.
                // Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
                IViewPart view2 = wbp.findView("cn.com.kxh.myplugin.View2");
                //這個地方的參數是"視圖2"在plugin.xml中的id標識.由此可見plugin.xml文件在插件中的地位是極其重要的.
                // 將當前選擇的列表項顯示在文本框中
                Text text = ((View2) view2).getText();
                text.setText(list.getSelection()[0]);
            }
        });
        // 列表選擇事件監聽
        list.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                // 由IWorkbenchPage獲得view2對象
                IWorkbenchPage wbp = getViewSite().getPage();// Activator.getDefault().getWorkbench().getActiveWorkbenchWindow(). getActivePage();
                IViewPart view2 = wbp.findView("cn.com.kxh.myplugin.View2");
                // 將當前選擇的列表項顯示在文本框中
                Text text = ((View2) view2).getText();
                text.setText(list.getSelection()[0]);
            }
        });
        list.addMouseListener(new MouseAdapter() {
            private ChinaEditorInput chinaEditorInput = new ChinaEditorInput();
            private UsaEditorInput usaEditorInput = new UsaEditorInput();
            private FranceEditorInput franceEditorInput = new FranceEditorInput();

            public void mouseDoubleClick(MouseEvent e) {
                // 根據不同列表項得到其相應的editorInput對象和editorID,其中
                // editorID指該編輯器在plugin.xml文件中設置id標識值
                List list = (List) e.getSource();// 由MouseEvent得到列表對象
                String listStr = list.getSelection()[0];// 得到當前列表項的字符
                IEditorInput editorInput = null;
                String editorID = null;
                if (listStr.equals("中國")) {
                    editorInput = chinaEditorInput;
                    editorID = "cn.com.kxh.myplugin.ChinaEditor";
                } else if (listStr.equals("美國")) {
                    editorInput = usaEditorInput;
                    editorID = "cn.com.kxh.myplugin.UsaEditor";
                } else if (listStr.equals("法國")) {
                    editorInput = franceEditorInput;
                    editorID = "cn.com.kxh.myplugin.FranceEditor";
                }
                // 如果editorInput或editorID為空則中斷返回
                if (editorInput == null || editorID == null)
                    return;
                // 取得IWorkbenchPage,並搜索使用editorInput對象對應的編輯器
                IWorkbenchPage workbenchPage = getViewSite().getPage();
                IEditorPart editor = workbenchPage.findEditor(editorInput);
                // 如果此編輯器已經存在,則將它設為當前的編輯器(最頂端),否則
                // 重新打開一個編輯器
                if (editor != null) {
                    workbenchPage.bringToTop(editor);
                } else {
                    try {
                        workbenchPage.openEditor(editorInput, editorID);
                    } catch (PartInitException e2) {
                        e2.printStackTrace();
                    }
                }
            }
        });

        // 加入導航欄按鈕、下拉菜單、右鍵菜單
        MyActionGroup actionGroup = new MyActionGroup();
        fillViewAction(actionGroup);// 加入視圖的導航欄按鈕
        fillViewMenu(actionGroup);// 加入視圖的下拉菜單
        fillListMenu(actionGroup);// 加入視圖的下拉菜單
    }
    
    // 加入視圖的導航欄按鈕
    private void fillViewAction(MyActionGroup actionGroup) {
        IActionBars bars = getViewSite().getActionBars();
        actionGroup.fillActionBars(bars);
    }

    // 加入視圖的下拉菜單
    private void fillViewMenu(MyActionGroup actionGroup) {
        IMenuManager manager = getViewSite().getActionBars().getMenuManager();
        actionGroup.fillContextMenu(manager);
    }

    // 加入列表List的右鍵菜單
    private void fillListMenu(MyActionGroup actionGroup) {
        MenuManager manger = new MenuManager();
        Menu menu = manger.createContextMenu(list);
        list.setMenu(menu);
        actionGroup.fillContextMenu(manger);
    }
    
    @Override
    public void setFocus() {}
}

程序說明:視圖加按鈕,菜單的方式和以前SWT的方式是一樣的,只不過以前自己生成MenuManager等對象,而現在只需要使用插件平台提供的MenuManager對象.

在事件處理方法:本程序中為了便於理解,使用了if...else這種簡單的方式來判斷被雙擊的類表項,這適合列表項較少的情況,如果列表項太多,則代碼會相當長.解決這個問題,可將IEditorInput中沒有用到的getName方法借用一下,把editorID放到此方法里面,這樣就可以用下面的方式來得到IEditorInput和editorID了.

String key = ""+list.getSelectionIndex();

IEditorInput editorInput = (IEditorInput)list.getData(key);

String editorID = editorInput.getnName();

在實際開發綜合很多界面都是創建在編輯器上,雖然在這里是只講了最常用的編輯器使用方法,但已經足夠應付大部分開發的需要,如果你想了解更多關於編輯器的信息,可以查閱編輯器的幫助文檔,它在幫助中的位置是"平台插件開發者指南--->程序員指南----->編輯器".

 

將在透視圖中添加上對應的編輯器類:(這種效果就像在Eclipse張雙擊Java源文件,打開文件的編輯器一樣)

和以前一樣,先來修改plugin.xml文件將編輯器的擴展點加入,然后再創建相應的編輯器類.最后編寫列表的事件代碼.

plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
 <extension point="org.eclipse.ui.perspectives">
       <perspective
        name="myplugin 透視圖"
        icon="icons/selectall.gif"
        class="cn.com.kxh.myplugin.SamplePerspective"
        id="cn.com.kxh.myplugin.SamplePerspective">
    </perspective>
 </extension>
 <extension point="org.eclipse.ui.views">
     <view
             name="視圖1"
             icon="icons/prev.gif"
             category="com.glkxh.myplugin.view"
             class="cn.com.kxh.myplugin.View1"
             id="cn.com.kxh.myplugin.View1">
     </view>
     <view
             name="視圖2"
             icon="icons/project.gif"
             category="com.glkxh.myplugin.view"
             class="cn.com.kxh.myplugin.View2"
             id="cn.com.kxh.myplugin.View2">
     </view>
 </extension>
 <extension point="org.eclipse.ui.editors">
  <editor 
        name="中國Editor"
        icon="icons/project.gif"
        class="cn.com.kxh.myplugin.ChinaEditor"
        id="cn.com.kxh.myplugin.ChinaEditor">
  </editor>
  <editor 
        name="美國Editor"
        icon="icons/prev.gif"
        class="cn.com.kxh.myplugin.UsaEditor"
        id="cn.com.kxh.myplugin.UsaEditor">
  </editor>
  <editor 
        name="法國Editor"
        icon="icons/remove.gif"
        class="cn.com.kxh.myplugin.FranceEditor"
        id="cn.com.kxh.myplugin.FranceEditor">
   </editor>
  </extension>
</plugin>

上述代碼說明:編輯器的擴展點是org.eclipse.ui.editors,它各項的含義和視圖擴展點基本一樣,可參照視圖擴展點的說明,這里強調一點:icon是必填項.

編輯器必須實現IEditorPart接口,但通常是繼承抽象類EditorPart類(EditorPart是IEditorPart的子類).繼承EditorPart的子類必須實現父類的7個方法,在此先實現方法init,createPartControl,其他方法空實現.

代碼說明:編輯器的擴展點是org.eclispse.ui.editor

ChinaEditor.java

 1 public class ChinaEditor extends EditorPart {
 2     private boolean dirty = true; // 編輯器是否為臟的標識
 3 
 4     // Editor的初始化方法。本方法前兩句是固定不變的
 5     public void init(IEditorSite site, IEditorInput input) throws PartInitException {
 6         System.out.println("init");
 7         setSite(site);
 8         setInput(input);
 9         // 下一句設置Editor標題欄的顯示名稱,否則名稱用plugin.xml中的name屬性
10         // setPartName(input.getName());
11         // 下一句設置Editor標題欄的圖標,否則會自動使用一個默認的圖標
12         // setTitleImage(input.getImageDescriptor().createImage());
13     }
14 
15     // 在此方法中創建Editor中的界面組件
16     public void createPartControl(Composite parent) {
17         System.out.println("createPartControl");
18         Composite topComp = new Composite(parent, SWT.NONE);
19         topComp.setLayout(new FillLayout());
20         Text text = new Text(topComp, SWT.BORDER);
21         text.setText("中國之編輯器");
22 
23         text.addKeyListener(new KeyAdapter() {
24             public void keyPressed(KeyEvent e) {
25                 // 如果編輯器不臟(即沒有修改),則標志它臟並刷新界面狀態
26                 if (!isDirty()) {
27                     setDirty(true);
28                     firePropertyChange(IEditorPart.PROP_DIRTY);
29                 }
30             }
31         });
32     }
33 
34     // 保存的處理代碼在這種方法中,當按Ctrl+S鍵時會執行此方法。
35     // 最后別忘記標志為非臟及刷新界面狀態
36     public void doSave(IProgressMonitor monitor) {
37         if (isDirty()) {
38             // ……保存編輯器事件處理代碼(省略)
39             setDirty(false);
40             firePropertyChange(IEditorPart.PROP_DIRTY);
41         }
42     }
43 
44     // 是否允許“另存為”,false不允許
45     public boolean isSaveAsAllowed() {
46         return false;
47     }
48 
49     // “另存為”的代碼寫在這里,本例不實現它
50     public void doSaveAs() {}
51 
52     // dirty標識的set方法,由此方法設置編輯器為臟
53     public void setDirty(boolean dirty) {
54         this.dirty = dirty;
55     }
56 
57     // 編輯器的內容是否臟了。true臟,false不臟
58     public boolean isDirty() {
59         return dirty;
60     }
61 
62     // 當編輯器獲得焦點時會執行此方法,本例空實現
63     public void setFocus() {}
64 }

獲取視圖對象是用IWorkbenchPage的findView方法,方法參數是視圖在plugin.xml中的id標識,獲取編輯器對象是用findEditor方法,但該方法的參數卻不是id標識,而是一個IEditorInput對象.另外,加載一個編輯器是用IWorkbenchPage的openEditor(editorInput,editorID)方法.

由上可知,一個編輯器要對應一個IEditorInput和EditorPart,而且在IWorkbenchPage中是根據IEditorInput來取得EditorPart.

附上關系圖:

ChinaEditorInput.java

 1 public class ChinaEditorInput implements IEditorInput {
 2 
 3     // 返回true,則打開該編輯器后它會出現在Eclipse主菜單“文件”
 4     // 最下部的最近打開的文檔欄中。返回flase則不出現在其中。
 5     @Override
 6     public boolean exists() {
 7         return true;
 8     }
 9 
10     // 編輯器標題欄的圖標,不過它還需要在ChinaEditor中用
11     // setTitleImage方法設置,才能出現在標題欄中。
12     @Override
13     public ImageDescriptor getImageDescriptor() {
14         // return WorkbenchImages.getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_HOME_NAV);
15         return null;
16     }
17 
18     // 編輯器標題欄的顯示名稱,和上面的getImageDescriptor一樣也要
19     // 在ChinaEditor中用setPartName方法設置,才能出現在標題欄中。
20     @Override
21     public String getName() {
22         return "中國的編輯器";
23     }
24 
25     // 編輯器標題欄的小黃條提示文字,不需象getName那樣在ChinaEditor中再設置
26     @Override
27     public String getToolTipText() {
28         return "這是視圖1列表中的中國項對應的編輯器";
29     }
30 
31     // 返回一個可以用做保存本編輯輸入數據狀態的對象
32     @Override
33     public IPersistableElement getPersistable() {
34         return null;
35     }
36 
37     // 得到一個編輯器的適配器
38     // IAdaptable a = new ChinaEditorInput();
39     // IFoo x = (IFoo)a.getAdapter(IFoo.class);
40     // if (x != null) [用x來做IFoo的事情....]
41     @Override
42     public Object getAdapter(Class adapter) {
43         return null;
44     }
45 }

FranceEditor.java

 1 public class FranceEditor extends EditorPart {
 2 
 3     public void doSave(IProgressMonitor monitor) {}
 4 
 5     public void doSaveAs() {}
 6 
 7     public void init(IEditorSite site, IEditorInput input) throws PartInitException {
 8         setSite(site);
 9         setInput(input);
10     }
11 
12     public boolean isDirty() {
13         return false;
14     }
15 
16     public boolean isSaveAsAllowed() {
17         return false;
18     }
19 
20     public void createPartControl(Composite parent) {
21         Composite topComp = new Composite(parent, SWT.NONE);
22         topComp.setLayout(new FillLayout());
23         Text text = new Text(topComp, SWT.BORDER);
24         text.setText("法國之編輯器");
25     }
26 
27     public void setFocus() {}
28 
29 }

FranceEditorInput.java

 1 public class FranceEditorInput implements IEditorInput {
 2 
 3     public boolean exists() {
 4         return false;
 5     }
 6 
 7     public ImageDescriptor getImageDescriptor() {
 8         return null;
 9     }
10 
11     public String getName() {
12         return "法國的編輯器";
13     }
14 
15     public IPersistableElement getPersistable() {
16         return null;
17     }
18 
19     public String getToolTipText() {
20         return "這是視圖1列表中的法國項對應的編輯器";
21     }
22 
23     public Object getAdapter(Class adapter) {
24         return null;
25     }
26 
27 }

UsaEditor.java

public class UsaEditor extends EditorPart {

    public void doSave(IProgressMonitor monitor) {}

    public void doSaveAs() {}

    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
        setSite(site);
        setInput(input);
    }

    public boolean isDirty() {
        return false;
    }

    public boolean isSaveAsAllowed() {
        return false;
    }

    public void createPartControl(Composite parent) {
        Composite topComp = new Composite(parent, SWT.NONE);
        topComp.setLayout(new FillLayout());
        Text text = new Text(topComp, SWT.BORDER);
        text.setText("美國之編輯器");
    }

    public void setFocus() {}

}

UsaEditorInput.java

 1 public class UsaEditorInput implements IEditorInput {
 2 
 3     public boolean exists() {
 4         return false;
 5     }
 6 
 7     public ImageDescriptor getImageDescriptor() {
 8         return null;
 9     }
10 
11     public String getName() {
12         return "美國的編輯器";
13     }
14 
15     public IPersistableElement getPersistable() {
16         return null;
17     }
18 
19     public String getToolTipText() {
20         return "這是視圖1列表中的美國項對應的編輯器";
21     }
22 
23     public Object getAdapter(Class adapter) {
24         return null;
25     }
26 
27 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM