2011-04-20 85 views
4

我正在爲Eclipse編寫一個插件,它爲在我們的軟件堆棧中使用的特定預處理器指令提供語法高亮顯示。在編譯實際的代碼之前,這些代碼會被一個外部程序取代(假設像<% FOO %>這樣的標籤被替換爲別的東西,比如版本字符串)。Eclipse插件處理與不同編輯器相同的文件擴展名

因此,該插件爲每個標籤提供註釋以快速識別這些標籤。這些註釋不是實現自己的編輯器,而是爲現有的編輯器提供註釋,如JavaEditor或PHP-Editor。

現在的問題是,由外部程序處理的文件都具有相同的文件擴展名,如.inc。它們可以包含Java代碼或PHP代碼(將來也可能包含其他語言)。

我已經成功添加了一個內容類型到我的插件,我可以根據一些標準區分不同的文件。所以,當我有一個java .inc文件並指定內容類型inc file (java)

但是,用戶應該能夠覆蓋此自動檢測(另外,有時自動檢測可能會失敗)。因此,我希望能夠用不同的編輯器(Java編輯器,PHP編輯器,...)打開一個文件(foo.inc),並且能夠保存該關聯。

我目前想的方法:

  • 覆蓋文件開行動檢查在我的項目設置並打開相應的編輯器。我沒有找到,討論瞭如何覆蓋所有文件打開動作(文件→打開文件在主菜單中,打開在Project Navigator,...)
  • 實現一個自己的編輯器,然後打開相應的編輯器的解決方案。這似乎是一種駭人的做法,也會造成一些延誤。
  • 在文件的「打開方式」上下文菜單中,用戶可以更改編輯器。以編程方式更改它可以,但我找不到存儲此選項的API或文件。
  • 爲一個項目實現不同的Natures,然後在每個特性的上下文中以不同的方式關聯文件類型。只會提供項目特定的關聯,而不是每個文件。

有沒有更好的解決方案?你知道更多關於我列出的任何方法嗎?

回答

3

我發現如何覆蓋文件打開操作:通過註冊actionProvider,它覆蓋org.eclipse.ui.navigator.resources.OpenActions。我提供了所有的代碼,因爲將所有這些不同的東西放在一起並使其工作起來相對困難。

讓我們從插件開始。XML條目:

<!-- overwrite OpenActions --> 
<extension 
     point="org.eclipse.ui.navigator.navigatorContent"> 
    <actionProvider 
     class="myplugin.navigator.OpenActionProvider" 
     id="myplugin.navigator.actions.open" 
     overrides="org.eclipse.ui.navigator.resources.OpenActions" 
     priority="highest"> 
     <enablement> 
     <and> 
      <instanceof 
        value="org.eclipse.core.resources.IFile"> 
      </instanceof> 
      <test 
        property="org.eclipse.core.resources.extension" 
        value="frm"> 
      </test> 
     </and> 
     </enablement> 
    </actionProvider> 
</extension> 
<extension 
     point="org.eclipse.ui.navigator.viewer"> 
    <viewerActionBinding 
     viewerId="org.eclipse.ui.navigator.ProjectExplorer"> 
     <includes> 
     <actionExtension 
       pattern="myplugin.navigator.actions.open"> 
     </actionExtension> 
     </includes> 
    </viewerActionBinding> 
</extension> 

的OpenActionProvider看起來是這樣的:

package myplugin.navigator; 

import org.eclipse.jface.action.IMenuManager; 
import org.eclipse.ui.IActionBars; 
import org.eclipse.ui.IViewPart; 
import org.eclipse.ui.actions.ActionContext; 
import org.eclipse.ui.navigator.CommonActionProvider; 
import org.eclipse.ui.navigator.ICommonActionConstants; 
import org.eclipse.ui.navigator.ICommonActionExtensionSite; 
import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite; 

public class OpenActionProvider extends CommonActionProvider { 
    private OpenEditorActionGroup fOpenGroup; 

    @Override 
    public void init(ICommonActionExtensionSite site) { 
      ICommonViewerWorkbenchSite workbenchSite = null; 
      if (site.getViewSite() instanceof ICommonViewerWorkbenchSite) { 
        workbenchSite = (ICommonViewerWorkbenchSite) site.getViewSite(); 
      } 
      if (workbenchSite != null) { 
        if (workbenchSite.getPart() != null && workbenchSite.getPart() instanceof IViewPart) { 
          IViewPart viewPart = (IViewPart) workbenchSite.getPart(); 

          fOpenGroup = new OpenEditorActionGroup(viewPart); 
        } 
      } 
    } 

    @Override 
    public void dispose() { 
      if (fOpenGroup != null) { 
        fOpenGroup.dispose(); 
        fOpenGroup = null; 
      } 
      super.dispose(); 
    } 

    @Override 
    public void fillActionBars(IActionBars actionBars) { 
      if (fOpenGroup == null) 
        return; 

      fOpenGroup.updateActionBars(); 
      actionBars.setGlobalActionHandler(ICommonActionConstants.OPEN, fOpenGroup.getOpenAction()); 
    } 

    @Override 
    public void fillContextMenu(IMenuManager menu) { 
      if (fOpenGroup == null) 
        return; 
      fOpenGroup.fillContextMenu(menu); 
    } 

    @Override 
    public void setContext(ActionContext context) { 
      super.setContext(context); 
      if (fOpenGroup == null) 
        return; 
      fOpenGroup.setContext(context); 
    } 
} 

的OpenEditorActionGroup看起來是這樣的:

package myplugin.navigator; 
import java.util.ArrayList; 
import java.util.List; 

import org.eclipse.core.resources.IFile; 
import org.eclipse.core.resources.IResource; 
import org.eclipse.core.runtime.IAdaptable; 
import org.eclipse.jface.action.IAction; 
import org.eclipse.jface.action.IMenuManager; 
import org.eclipse.jface.action.MenuManager; 
import org.eclipse.jface.viewers.ISelection; 
import org.eclipse.jface.viewers.IStructuredSelection; 
import org.eclipse.jface.viewers.StructuredSelection; 
import org.eclipse.ui.IActionBars; 
import org.eclipse.ui.IViewPart; 
import org.eclipse.ui.actions.OpenFileAction; 
import org.eclipse.ui.actions.OpenWithMenu; 
import org.eclipse.ui.navigator.ICommonMenuConstants; 


public class OpenEditorActionGroup extends AbstractActionGroup { 
    private OpenFileAction fOpenFileAction; 

    public OpenEditorActionGroup(IViewPart viewPart) { 
      super(viewPart); 
    } 

    @Override 
    protected void makeActions() { 
      fOpenFileAction= new OpenGenElementAction(getViewPart().getSite().getPage()); 
    } 

    public static IStructuredSelection convertSelectionToResources(ISelection s) { 
      List<Object> converted = new ArrayList<Object>(); 
      if (s instanceof StructuredSelection) { 
        Object[] elements = ((StructuredSelection) s).toArray(); 
        for (int i = 0; i < elements.length; i++) { 
          Object e = elements[i]; 
          if (e instanceof IResource) { 
            converted.add(e); 
          } else if (e instanceof IAdaptable) { 
            IResource r = (IResource) ((IAdaptable) e).getAdapter(IResource.class); 
            if (r != null) { 
              converted.add(r); 
            } 
          } 
        } 
      } 
      return new StructuredSelection(converted.toArray()); 
    } 


    @Override 
    public void fillContextMenu(IMenuManager menu) { 
      System.out.println("fillcontextmenu"); 
      if (getContext() == null) 
        return; 
     IStructuredSelection celements = (IStructuredSelection)getContext().getSelection(); 
      IStructuredSelection selection = convertSelectionToResources(celements); 

      fOpenFileAction.selectionChanged(celements); 
      if (!fOpenFileAction.isEnabled()) 
        return; 
      menu.appendToGroup(ICommonMenuConstants.GROUP_OPEN, fOpenFileAction); 
      fillOpenWithMenu(menu, selection); 
    } 

的AbstractActionGroup是隻是一個包裝,你應該想實現更多的這些:

package myplugin.navigator; 
import org.eclipse.core.runtime.Assert; 
import org.eclipse.jface.action.IMenuManager; 
import org.eclipse.jface.resource.ImageDescriptor; 
import org.eclipse.ui.IActionBars; 
import org.eclipse.ui.IViewPart; 
import org.eclipse.ui.actions.ActionGroup; 

public abstract class AbstractActionGroup extends ActionGroup { 
    private final IViewPart fViewPart; 

    public AbstractActionGroup(IViewPart viewPart) { 
      Assert.isNotNull(viewPart); 
      fViewPart = viewPart; 
      makeActions(); 
    } 

    protected IViewPart getViewPart() { 
      return fViewPart; 
    } 

    protected ImageDescriptor getImageDescriptor(String relativePath) { 
      return ImageDescriptor.createFromURL(null); 
    } 

    protected abstract void makeActions(); 
    @Override 
    public abstract void fillContextMenu(IMenuManager menu); 
    @Override 
    public abstract void fillActionBars(IActionBars actionBars); 
    @Override 
    public abstract void updateActionBars(); 
} 

最後的OpenGenElementAction本身:

package myplugin.navigator; 

import org.eclipse.core.resources.IFile; 
import org.eclipse.core.resources.IResource; 
import org.eclipse.jface.viewers.IStructuredSelection; 
import org.eclipse.ui.IEditorDescriptor; 
import org.eclipse.ui.IEditorPart; 
import org.eclipse.ui.IWorkbenchPage; 
import org.eclipse.ui.PartInitException; 
import org.eclipse.ui.PlatformUI; 
import org.eclipse.ui.actions.OpenFileAction; 
import org.eclipse.ui.editors.text.EditorsUI; 
import org.eclipse.ui.part.FileEditorInput; 

public class OpenGenElementAction extends OpenFileAction { 
    private IFile selectedFile = null; 
    private final IWorkbenchPage workbenchPage; 

    public OpenGenElementAction(IWorkbenchPage page) { 
      super(page); 
      workbenchPage = page; 
    } 

    @Override 
    public boolean isEnabled() { 
      return true; 
    } 

    @Override 
    public void run() { 
      System.out.println("RUN"); 
    } 

    @Override 
    protected boolean updateSelection(IStructuredSelection selection) { 
      if (selection.size() != 1) 
        return super.updateSelection(selection); 
      Object element = selection.getFirstElement(); 
      if (element instanceof IFile) { 
        selectedFile = (IFile)element; 
      } 

      return selectedFile != null || super.updateSelection(selection); 
    } 
} 
+0

之後,我發現這個代碼在**包裝資源管理器和項目導航器中都不起作用:(。 – Michael 2011-05-15 20:57:42

+0

感謝您發佈這個! – ernesto 2013-02-06 11:34:42

0

編程您可以直接攻擊IEditorRegistry,通過註冊特定的文件名,而不僅僅是擴展。

看: 「幫助上IEditorRegistry」

http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fui%2FIEditorRegistry.html

的方法:

void setDefaultEditor(String fileNameOrExtension, String editorId) 
     Sets the default editor id for the files that match 
     that specified file name or extension. 

接受全名和/或通配符。大多數openEditor調用(菜單,工具欄等)最終都會調用此註冊表以獲取適當的編輯器。 打開專門註冊該文件名的編輯器時設置鉤子。

如果您有兩個具有相同名稱和不同語言的文件,但這不是萬無一失,但與您的方法相比,它的實施快速且容易。

相關問題