IDEA 插件開發


 

 

 

IDEA 插件開發

----------------------------------------------------------------------------------------

 

一、PropertiesComponent.getInstance(project):臨時儲存數據,適用於application級別和project級別

PropertiesComponent.getInstance(project).setValue("kwy", "value");
PropertiesComponent.getInstance(project).getValue("key");

  

二、FileDocumentManager.getInstance().saveAllDocuments():保存文檔記錄

FileDocumentManager.getInstance().saveAllDocuments();

  

三、創建底邊toolwindow

1、繼承Executor類 public class MyExecutor extends Executor{} 2、配置extensions <extensions defaultExtensionNs="com.intellij">
    <executor implementation="mybatis.log.action.MyExecutor" id="MyExecutor"/>
  </extensions> Disposer.register(project, executor) 3、創建RunnerLayoutUi final RunnerLayoutUi.Factory factory = RunnerLayoutUi.Factory.getInstance(e.getProject()); final RunnerLayoutUi layoutUi = factory.create("SQL", "SQL", "SQL", e.getProject()); 4、創建RunContentDescriptor: return new RunContentDescriptor(new RunProfile() { @Nullable @Override public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment executionEnvironment) throws ExecutionException { return null; } @Override public String getName() { //第一層名稱顯示
                return "Sql"; } @Nullable @Override public Icon getIcon() { return null; } }, new DefaultExecutionResult(), layoutUi); Disposer.register(descriptor, this); Disposer.register(content, console); 5、展示工具ExecutionManager.getInstance(e.getProject()).getContentManager().showRunContent(executor, descriptor);

 

  

四、在toolwindow添加控制台(打印台)

1、    TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(e.getProject());
        ConsoleView console = consoleBuilder.getConsole();
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(console.getComponent(), BorderLayout.CENTER);

2、    final Content content = layoutUi.createContent("ConsoleContent", panel, "executable sql statements", AllIcons.Debugger.Console, panel);
        content.setCloseable(true);
        layoutUi.addContent(content);
3、控制台打印文本:console.print("hello", ConsoleViewContentType.USER_INPUT);

  

五、RunnerLayoutUi添加按鈕事件

1、創建按鈕組
final DefaultActionGroup actionGroup = new DefaultActionGroup();
        actionGroup.add(new anaction()));

2、ui添加按鈕
layoutUi.getOptions().setLeftToolbar(actionGroup, "RunnerToolbar");

  

六、控制台過濾器:ConsoleFilterProvider,Filter

1、實現Filter
public class MyFilter implements Filter {

    @Nullable
    @Override
    public Result applyFilter(@NotNull String s, int i) {
        System.out.println("sss=>" + s);
        System.out.println("i=" + i);
        return null;
    }
}

2、實現ConsoleFilterProvider,配置過濾器
public class MyConsoleFilterProvider implements ConsoleFilterProvider {

    @NotNull
    @Override
    public Filter[] getDefaultFilters(@NotNull Project project) {
        MyFilter filter = new MyFilter();
        return new Filter[]{filter};
    }
}

3、plugin.xml配置ConsoleFilterProvider
  <extensions defaultExtensionNs="com.intellij">
    <consoleFilterProvider implementation="com.log.provider.MyConsoleFilterProvider"/>
  </extensions>

  

七、創建選項:ListPopup

1、 plugin.xml配置事件組
<actions>
    <group id="Test-Group-id" text="Test-Group" >
    </group>
  </actions>
2、創建一個事件AnAction觸發選項ListPopup
public class ProPlug extends AnAction {
    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
// 獲取plugin.xml配置的事件組
        DefaultActionGroup group = (DefaultActionGroup) ActionManager.getInstance().getAction("Test-Group-id");
// 清空所有事件
        group.removeAll();
// 添加一個事件AnAction
        group.add(new AnAction("New-Anaction") {
            @Override
            public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
                System.out.println("this is new Anaction.....");
            }
        });
// 獲取工程的選項對象ListPoup
        ListPopup myPopup = JBPopupFactory.getInstance().createActionGroupPopup("MyPopup", group, e.getDataContext(),
                JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false);
// ListPopub的顯示位置,showCenteredInCurrentWindow當前窗口中間彈出,showInCenterOf在一個組件中間彈出
        myPopup.showInBestPositionFor(e.getDataContext());
    }
}

  

八、顯示提示框 

        Editor editor = e.getData(CommonDataKeys.EDITOR);
        ApplicationManager.getApplication().invokeLater(() -> {
            JBPopupFactory factory = JBPopupFactory.getInstance();
            factory.createHtmlTextBalloonBuilder("hello", null,
                    new JBColor(new Color(186, 238, 186), new Color(73, 117, 73)), null)
                    .setFadeoutTime(5000L)
                    .createBalloon()
                    .show(factory.guessBestPopupLocation(editor), Balloon.Position.above);
        });

  

九、復制文本到剪貼板

        CopyPasteManager.getInstance().setContents(new StringSelection("this is copy content"));

 

十、創建toolWindow工具

1、右鍵新建GUI Form:MyForm繼承SimpleToolWindowPanel 2、初始化構造器,添加根面板到MyForm 3、自定義布局form界面 4、客戶端獲取JPanel 5、創建ToolWindow工具並注冊JPanel public class MyForm extends SimpleToolWindowPanel { private JPanel parentPanel; private JTabbedPane tabbedPane1; private SimpleTree tree1; private JTextField textField1; private JTextField textField2; private JButton button1; private JTextArea textArea1; public MyForm(Project project) { super(true, true); // 初始化構造器,添加根面板到MyForm
 add(parentPanel); } } public void actionPerformed(AnActionEvent e) { // 客戶端獲取JPanel // JPanel jPanel = new OtherForm(e.getProject());
        JPanel jPanel = e.getProject().getComponent(MyForm.class); ContentFactory factory = ServiceManager.getService(ContentFactory.class); Content content = factory.createContent(jPanel, "New Panel", false); ToolWindowManager manager = ToolWindowManager.getInstance(e.getProject()); ToolWindow toolWindow = manager.registerToolWindow("NewTest", false, ToolWindowAnchor.RIGHT); ContentManager contentManager = toolWindow.getContentManager(); contentManager.addContent(content); contentManager.setSelectedContent(content, false); }

 

十一、彈出消息框

            Messages.showMessageDialog("hello", "New-Message", Messages.getInformationIcon());

  

十二、按鈕添加事件

JButton.addActionListener((e)->{ Messages.showMessageDialog("hello", "New-Message", Messages.getInformationIcon()); });

  

十二、動態添加menu

       ActionManager actionManager = ActionManager.getInstance();
            DefaultActionGroup codeMenu = (DefaultActionGroup) actionManager.getAction("EditMenu");
            codeMenu.add(new AnAction("New-Action") {
                @Override
                public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
                    Messages.showMessageDialog("hello", "New-Message", Messages.getInformationIcon());
                }
            });

  

十三、導航跳轉

NavigationItem.navigate(true)

  

十四、JTree樹配置

1、創建MyNavigationItem實現NavigationItem,保存PsiElement和NavigationItem
public class MyNavigationItem implements NavigationItem {
    private PsiElement psielment;
    private NavigationItem navigationItem;
    private String name;
    public MyNavigationItem(PsiElement psiElement) {
        this.psielment = psiElement;
        if (psiElement instanceof PsiMethod) {
            PsiMethod method = (PsiMethod) psiElement;
            this.name = method.getName();
        }
        if (psiElement instanceof NavigationItem) {
            this.navigationItem = (NavigationItem) psiElement;
        }

    }

    @Nullable
    @Override
    public String getName() {
        return name;
    }

    @Nullable
    @Override
    public ItemPresentation getPresentation() {
        return new MyItemPresentation(name);
    }

    @Override
    public void navigate(boolean b) {
        if (null != navigationItem) {
            navigationItem.navigate(b);
        }
    }

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

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



2、創建樹節點MyTreeNode繼承CachingSimpleNode
	public class MyTreeNode extends CachingSimpleNode {

	private SimpleNode parent;
	private MyNavigationItem myNavigationItem;
	private List<MyTreeNode> children = new ArrayList<>();
	private String name;

	protected MyTreeNode(String name, SimpleNode parent, PsiElement psiElement) {
		super(parent);
		this.getTemplatePresentation().setIcon(Module);
		this.setIcon(Module);
		this.parent = parent;
		if (null != psiElement) {
			this.myNavigationItem = new MyNavigationItem(psiElement);
		}
		this.name = name;
	}

	@Override
	protected SimpleNode[] buildChildren() {
		return children.parallelStream().toArray(SimpleNode[]::new);
	}

	public List<MyTreeNode> children() {
		return children;
	}

	@Override
	public String getName() {
		return name;
	}

// 雙擊樹節點

	@Override
	public void handleDoubleClickOrEnter(SimpleTree tree, InputEvent inputEvent) {
		SimpleNode selectedNode = tree.getSelectedNode();
			if (selectedNode instanceof MyTreeNode) {
			MyTreeNode myTreeNode = (MyTreeNode) selectedNode;
				if (null != myTreeNode.myNavigationItem) {
					myNavigationItem.navigate(true);
				}
			}
		}
	}

3、創建MySimpleTreeStrure繼承SimpleTreeStructure,重寫getRootElement
public class MySimpleTreeStructure extends SimpleTreeStructure {

    private MyTreeNode root;

    public MySimpleTreeStructure(Project project) {
        root = new MyTreeNode(project.getName(), null, null);
        Module[] modules = ModuleManager.getInstance(project).getModules();
        if (modules != null && modules.length > 0) {
            List<MyTreeNode> children = root.children();
            for (Module module : modules) {
                MyTreeNode moduleNode = new MyTreeNode(module.getName(), root, null);
                List<MyTreeNode> moduleChild = moduleNode.children();
                children.add(moduleNode);

                Collection<PsiAnnotation> controller = JavaAnnotationIndex.getInstance().get("Controller", project, GlobalSearchScope.moduleScope(module));

                if (null != controller && controller.size() > 0) {

                    for (PsiAnnotation psiAnnotation : controller) {
                        PsiClass psiClass = (PsiClass) psiAnnotation.getParent().getParent();
                        PsiMethod[] methods = psiClass.getMethods();
                        if (null != methods && methods.length > 0) {
                            for (PsiMethod method : methods) {
                                moduleChild.add(new MyTreeNode(method.getName(), moduleNode, method));
                            }
                        }
                    }

                }
            }
        }
    }

    @NotNull
    @Override
    public Object getRootElement() {
        return root;
    }

    public SimpleNode getRoot() {
        return root;
    }
}



4、初始化SimpleTreeBuilder
 MySimpleTreeStructure structure = new MySimpleTreeStructure(project);
        SimpleTreeBuilder myTreeBuilder = new SimpleTreeBuilder(tree1, (DefaultTreeModel)tree1.getModel(), structure, null);
        Disposer.register(project, myTreeBuilder);
        myTreeBuilder.initRoot();
        myTreeBuilder.expand(structure.getRoot(), null);

  

十五、搜索框

1、新建入口AnAction繼承GotoActionBase public class NewGotoActionBase extends GotoActionBase { @Override protected void gotoActionPerformed(@NotNull AnActionEvent e) { MyChooseByname chooseByname = new MyChooseByname(); ChooseByNameContributor[] butor = new ChooseByNameContributor[]{chooseByname}; FilterModel model = new FilterModel(e.getProject(), butor); GotoActionCallback callback = new GotoActionCallback() { @Override public void elementChosen(ChooseByNamePopup chooseByNamePopup, Object o) { Messages.showInfoMessage("Hello", "Title"); } }; showNavigationPopup(e, model, callback); } } 2、創建數據提供者MyChooseByName實現ChooseByNameContributor public class MyChooseByname implements ChooseByNameContributor { List<MyNavigationItem> list = new ArrayList<>(); public MyChooseByname() { for (int i = 0; i < 20; i++) { list.add(new MyNavigationItem(i + "", null)); } } /** * @description: 提供全部選項 * * @author: chenzhiwei * @create: 2020/5/16 22:31 * @return java.lang.String[] */ @NotNull @Override public String[] getNames(Project project, boolean b) { return list.parallelStream().map(MyNavigationItem::getValue).toArray(String[]::new); } /** * @description: 匹配到符合的項 * * @author: chenzhiwei * @create: 2020/5/16 22:31 * @return com.intellij.navigation.NavigationItem[] */ @NotNull @Override public NavigationItem[] getItemsByName(String s, String s1, Project project, boolean b) { NavigationItem[] navigationItems = list.parallelStream().filter( p -> p.getValue().equals(s) ) .toArray(NavigationItem[]::new); System.out.println("array="+ Arrays.toString(navigationItems)); return navigationItems; } } 3、創建搜索框模型MyFliteringGotoByModel繼承FilteringGotoByModel public class FilterModel extends FilteringGotoByModel { protected FilterModel(@NotNull Project project, @NotNull ChooseByNameContributor[] contributors) { super(project, contributors); } /** * @description: 命中選項 * * @author: chenzhiwei * @create: 2020/5/16 22:32 * @return java.lang.Object */ @Nullable @Override protected Object filterValueFor(NavigationItem navigationItem) { if (navigationItem instanceof MyNavigationItem) { MyNavigationItem myNavigationItem = (MyNavigationItem) navigationItem; return myNavigationItem.getValue(); } return null; } /** * @description: 搜索框標題 * * @author: chenzhiwei * @create: 2020/5/16 22:32 * @return java.lang.String */ @Nls(capitalization = Nls.Capitalization.Sentence) @Override public String getPromptText() { return "Enter"; } @NotNull @Override public String getNotInMessage() { return "Not in Message"; } @NotNull @Override public String getNotFoundMessage() { return "Not Found message"; } /** * @description: 過濾器是否打開 * * @author: chenzhiwei * @create: 2020/5/16 22:33 * @return java.lang.String */ @Nullable @Override public String getCheckBoxName() { return "New Check"; } @Override public boolean loadInitialCheckBoxState() { return false; } @Override public void saveInitialCheckBoxState(boolean b) { } @NotNull @Override public String[] getSeparators() { return new String[]{"/","?"}; } /** * @description: 必須重寫,返回數據項 * * @author: chenzhiwei * @create: 2020/5/16 22:33 * @return java.lang.String */ @Nullable @Override public String getFullName(@NotNull Object element) { return ((MyNavigationItem)element).getValue(); } @Override public boolean willOpenEditor() { return true; } } 4、在GotoActionBase中創建回調函數GotoActionCallback // 初始化回調函數
        GotoActionCallback callback = new GotoActionCallback() { @Override public void elementChosen(ChooseByNamePopup chooseByNamePopup, Object o) { Messages.showInfoMessage("Hello", "Title"); } }; 6、彈出搜索框showNavigationPopup(e,model,callback) 7、添加過濾器,新建過濾器指定類型FilterDemo public class FilterDemo { private String name; private String value; public FilterDemo(String name, String value) { this.name = name; this.value = value; } public String getValue() { return value; } } 8、在MyNavigationItem中維護FilterDemo public class MyNavigationItem implements NavigationItem { private PsiElement psielment; private NavigationItem navigationItem; private String name; private FilterDemo demo; public MyNavigationItem(String name, PsiElement psiElement) { this.psielment = psiElement; if (psiElement instanceof PsiMethod) { PsiMethod method = (PsiMethod) psiElement; this.name = method.getName(); } if (psiElement instanceof NavigationItem) { this.navigationItem = (NavigationItem) psiElement; } this.name = name; demo = new FilterDemo(name, name); } @Nullable @Override public String getName() { return name; } @Nullable @Override public ItemPresentation getPresentation() { return new MyItemPresentation(name); } @Override public void navigate(boolean b) { if (null != navigationItem) { navigationItem.navigate(b); } } @Override public boolean canNavigate() { return true; } @Override public boolean canNavigateToSource() { return true; } public String getValue() { return this.name; } public FilterDemo getDemo() { return demo; } 9、在MyFilteringGotoByModel添加泛型FilterDemo,如FilteringGotoByModel<FilterDemo>
public class FilterModel extends FilteringGotoByModel<FilterDemo> { protected FilterModel(@NotNull Project project, @NotNull ChooseByNameContributor[] contributors) { super(project, contributors); } /** * @description: 命中選項 * * @author: chenzhiwei * @create: 2020/5/16 22:32 * @return java.lang.Object */ @Nullable @Override protected FilterDemo filterValueFor(NavigationItem navigationItem) { if (navigationItem instanceof MyNavigationItem) { MyNavigationItem myNavigationItem = (MyNavigationItem) navigationItem; return myNavigationItem.getDemo(); } return null; } /** * @description: 搜索框標題 * * @author: chenzhiwei * @create: 2020/5/16 22:32 * @return java.lang.String */ @Nls(capitalization = Nls.Capitalization.Sentence) @Override public String getPromptText() { return "Enter"; } @NotNull @Override public String getNotInMessage() { return "Not in Message"; } @NotNull @Override public String getNotFoundMessage() { return "Not Found message"; } /** * @description: 過濾器是否打開 * * @author: chenzhiwei * @create: 2020/5/16 22:33 * @return java.lang.String */ @Nullable @Override public String getCheckBoxName() { return "New Check"; } @Override public boolean loadInitialCheckBoxState() { return false; } @Override public void saveInitialCheckBoxState(boolean b) { } @NotNull @Override public String[] getSeparators() { return new String[]{"/","?"}; } /** * @description: 必須重寫,返回數據項 * * @author: chenzhiwei * @create: 2020/5/16 22:33 * @return java.lang.String */ @Nullable @Override public String getFullName(@NotNull Object element) { return ((MyNavigationItem)element).getValue(); } @Override public boolean willOpenEditor() { return true; } } 10、新建MyChooseByNameFilter過濾器繼承ChooseByNameFilter<FilterDemo>
public class MyChooseByNameFilter extends ChooseByNameFilter<FilterDemo> { public MyChooseByNameFilter(@NotNull ChooseByNamePopup popup, @NotNull FilteringGotoByModel<FilterDemo> model, @NotNull Project project) { super(popup, model, new MyChooseByNameFilterConfiguration(), project); } @Override protected String textForFilterValue(@NotNull FilterDemo filterDemo) { return filterDemo.getValue(); } @Nullable @Override protected Icon iconForFilterValue(@NotNull FilterDemo filterDemo) { return null; } @NotNull @Override protected Collection<FilterDemo> getAllFilterValues() { List<MyNavigationItem> list = MyChooseByname.list; List<FilterDemo> collect = list.parallelStream().map(MyNavigationItem::getDemo) .collect(Collectors.toList()); return collect; } } 10、新建MyChooseByNameFilterCondiguration繼承ChooseByNameFilterConfiguration<FilterDemo>,並交給plugin.xml維護 public class MyChooseByNameFilterConfiguration extends ChooseByNameFilterConfiguration<FilterDemo> { @Override protected String nameForElement(FilterDemo filterDemo) { return filterDemo.getValue(); } } <extensions defaultExtensionNs="com.intellij">
    <projectService serviceImplementation="MyChooseByNameFilterConfiguration"/>
  </extensions>

11、在callback中實現createFilter方法,返回實例化的MyChooseByNameFilter對象 public class NewGotoActionBase extends GotoActionBase { @Override protected void gotoActionPerformed(@NotNull AnActionEvent e) { MyChooseByname chooseByname = new MyChooseByname(); ChooseByNameContributor[] butor = new ChooseByNameContributor[]{chooseByname}; FilterModel model = new FilterModel(e.getProject(), butor); // 初始化回調函數
        GotoActionCallback callback = new GotoActionCallback() { @Nullable @Override protected ChooseByNameFilter createFilter(@NotNull ChooseByNamePopup popup) { return new MyChooseByNameFilter(popup, model, e.getProject()); } @Override public void elementChosen(ChooseByNamePopup chooseByNamePopup, Object o) { Messages.showInfoMessage("Hello", "Title"); } }; showNavigationPopup(e, model, callback); } } 12、注意:FilterDemo必須是同一個對象 13、搜索框搜索的時候顯示輔助內容,新建MyItemPresentation public class MyItemPresentation implements ItemPresentation { private String name; public MyItemPresentation(String name) { this.name = name; } /** * @description: 搜索結果最終顯示 * * @author: chenzhiwei * @create: 2020/5/17 10:16 * @return java.lang.String */ @Nullable @Override public String getPresentableText() { return name; } /** * @description: 搜索結果的輔助說明 * * @author: chenzhiwei * @create: 2020/5/17 10:16 * @return java.lang.String */ @Nullable @Override public String getLocationString() { return "getLocationString"; } /** * @description: 搜索結果的圖標 * * @author: chenzhiwei * @create: 2020/5/17 10:16 * @return javax.swing.Icon */ @Nullable @Override public Icon getIcon(boolean b) { return null; } }

 

十六、樹節點鼠標右鍵菜單Popup

public class NewForm extends SimpleToolWindowPanel { private JPanel parentPanel; private JTree tree1; public NewForm(Project project) { super(true, true); add(parentPanel); MyTreeStructure structure = new MyTreeStructure(project); SimpleTreeBuilder builder = new SimpleTreeBuilder(tree1, (DefaultTreeModel) tree1.getModel(), structure, null); Disposer.register(project, builder); builder.initRoot(); builder.expand(structure.getRootElement(), null); tree1.addMouseListener(new PopupHandler() { @Override public void invokePopup(Component component, int x, int y) { ActionManager manager = ActionManager.getInstance(); ActionGroup actionGroup = (ActionGroup) manager.getAction("popupMenu"); JPopupMenu newMyPopup = manager.createActionPopupMenu("NewMyPopup", actionGroup).getComponent(); newMyPopup.show(component, x, y); } }); } } plugin.xml配置 <actions>
    <group id="popupMenu" text="PopupMenus" popup="true">
      <action class="NewPlugin" id="New One" text="New One" icon="AllIcons.Actions.Search"/>
      <action class="NewPlugin" id="New Two" text="New Two" icon="AllIcons.Actions.Refresh"/>
    </group>
  </actions>

 

十七、創建toolWindow工具方式二

1、創建SimpleToolWindowPanel(JPanel)並布局:如MyForm
public class MyForm extends SimpleToolWindowPanel {
    private JPanel parentPanel;
    private JTabbedPane tabbedPane1;
    private SimpleTree tree1;
    private JTextField textField1;
    private JTextField textField2;
    private JButton button1;
    private JTextArea textArea1;

    public MyForm(Project project) {
        super(true, true);
        MySimpleTreeStructure structure = new MySimpleTreeStructure(project);
        SimpleTreeBuilder myTreeBuilder = new SimpleTreeBuilder(tree1, (DefaultTreeModel)tree1.getModel(), structure, null);
        Disposer.register(project, myTreeBuilder);
        myTreeBuilder.initRoot();
        myTreeBuilder.expand(structure.getRoot(), null);



        add(parentPanel);
        button1.addActionListener((e)->{
            ActionManager actionManager = ActionManager.getInstance();
            DefaultActionGroup codeMenu = (DefaultActionGroup) actionManager.getAction("EditMenu");
            codeMenu.add(new AnAction("New-Action") {
                @Override
                public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
                    Messages.showMessageDialog("hello", "New-Message", Messages.getInformationIcon());
                }
            });
        });
    }
}

2、創建tool window的工廠:ToolWindowFactory
public class ToolFactory implements ToolWindowFactory {

    @Override
    public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
        Content content = toolWindow.getContentManager().getFactory().createContent(project.getComponent(MyForm.class), "New-Panel", false);
        toolWindow.getContentManager().addContent(content);
        toolWindow.setTitle("New Tool");
        toolWindow.setType(ToolWindowType.DOCKED, null);
    }
}

3、在配置pugin.xml中配置tool window
 <extensions defaultExtensionNs="com.intellij">
    <toolWindow anchor="bottom" id="NewTool" factoryClass="ToolFactory"/>
  </extensions>

4、獲取tool window
ToolWindow toolWindow = ToolWindowManager.getInstance(e.getProject()).getToolWindow("NewTool");
        toolWindow.activate(()->{
            System.out.println("show");
        });

  

 十八、JTree配置方式二:待定

 

十九:ToolWindowBar:Panel添加toolBar

public class NewForm extends SimpleToolWindowPanel { private JPanel parentPanel; private JTree tree1; public NewForm(Project project) { super(true, true); add(parentPanel); ActionGroup popupMenu = (ActionGroup) ActionManager.getInstance().getAction("popupMenu"); ActionToolbar newToolBar = ActionManager.getInstance().createActionToolbar("New Tool Bar", popupMenu, false); setToolbar(newToolBar.getComponent()); } } plugin.xml配置 <actions>
    <group id="popupMenu" text="PopupMenus" popup="true">
      <action class="NewPlugin" id="New One" text="New One" icon="AllIcons.Actions.Search"/>
      <action class="NewPlugin" id="New Two" text="New Two" icon="AllIcons.Actions.Refresh"/>
    </group>
  </actions>

 

二十:獲得當前編輯器

new AnAction("AddAction","Nothing", AllIcons.Actions.Back) { @Override public void actionPerformed(@NotNull AnActionEvent anActionEvent) { Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR); WriteCommandAction.runWriteCommandAction(anActionEvent.getProject(),()->{ // 插入的位置:當前光標的位置
            int position = editor.getCaretModel().getOffset(); editor.getDocument().insertString(position,
"Hello"); }); } });


二十一:定位到行列

new AnAction("AddAction","Nothing", AllIcons.Actions.Back) { @Override public void actionPerformed(@NotNull AnActionEvent anActionEvent) { Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR); // 行數,從0開始
                int line = 11; // 列數,從1開始
                int column = 12; LogicalPosition position = new LogicalPosition(line, column); editor.getCaretModel().moveToLogicalPosition(position); editor.getScrollingModel().scrollToCaret(ScrollType.CENTER); } }
 
        

 二十二、添加控制台方式二

1、創建console組件:    
    ConsoleView console = TextConsoleBuilderFactory.getInstance().createBuilder(project).getConsole();
2、初始化console到SimpleToolWindowPanel面板:
 jpanel.setLayout(new BorderLayout());
        jpanel.add(console.getComponent(), "Center");
3、在控制台打印數據:
        console.print("hello world", ConsoleViewContentType.NORMAL_OUTPUT);

注意:console先在panel中初始化,再初l始化toolWindowBar組件
將console放在JPanel中,則需要設置邊框laout和位置Center

  

二十三、新建窗口彈窗

1、右鍵新建Frame繼承JFrame 2、構造函數添加頂層組件 add(parentPanel) 3、實例化JFrame public class NewFrame extends JFrame { private JTextField textField1; private JTextField textField2; private JPanel rootPanel; public NewFrame() { add(rootPanel); } } public class MyPlugin extends AnAction { @Override public void actionPerformed(AnActionEvent e) { NewFrame frame = new NewFrame(); frame.pack(); frame.setLocationRelativeTo(null); frame.setSize(500, 300); frame.setVisible(true); } }

 

二十四、新建對話框彈框JDialog

右鍵新建Dialog並進行布局
@Override
    public void actionPerformed(AnActionEvent e) {
        MyDialog dialog = new MyDialog();
        dialog.pack();
        dialog.setSize(500, 300);
        dialog.setVisible(true);
        System.exit(0);
    }

   

二十五、圖標跳轉

1、新建MyLineMarkerProvider實現LineMarkerProvider重寫collectSlowLineMarkers方法 public class MyLineMarkerProvider implements LineMarkerProvider { @Nullable @Override public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) { return null; } @Override public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) { for (PsiElement element : elements) { if (element instanceof PsiMethod) { NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder // 圖標顯示
 .create(AllIcons.Actions.Scratch) .setAlignment(GutterIconRenderer.Alignment.CENTER) // 跳轉目標
 .setTarget(element) .setTooltipTitle(""); // 跳轉源頭
 result.add(builder.createLineMarkerInfo(element)); } } } } 
plugin.xml配置
<extensions defaultExtensionNs="com.intellij"> <codeInsight.lineMarkerProvider language="JAVA" implementationClass="MyLineMarkerProvider"/> </extensions>

 

 二十六、右鍵new創建文件

1、新建事件繼承CreateElementActionBase,重寫invokeDialog,create public class MyCreateElementActionBase extends CreateElementActionBase { public MyCreateElementActionBase() { // 菜單顯示名稱,描述,圖標
        super("MyCreateElementActionBaseShow", "Create new XML File", AllIcons.Actions.Refresh); } @NotNull @Override protected PsiElement[] invokeDialog(Project project, PsiDirectory directory) { MyInputValidator validator = new MyInputValidator( project, directory); Messages.showInputDialog(project, "輸入", "New", AllIcons.Actions.Scratch, "", validator); return validator.getCreatedElements(); } @NotNull @Override protected PsiElement[] create(@NotNull String s, PsiDirectory psiDirectory) throws Exception { String text = "<idea-plugin>\n" +
                "</idea-plugin>"; // 創建文件
        PsiFile f = PsiFileFactory.getInstance(psiDirectory.getProject()).createFileFromText(s + ".xml", new MyFileTypeIdentifiableByVirtualFile(), text); // 添加到當前文件夾
 psiDirectory.add(f); PsiElement lastChild = f.getLastChild(); return new PsiElement[]{lastChild, f}; } @Nls(capitalization = Nls.Capitalization.Title) @Override protected String getErrorTitle() { return "出現異常"; } @Nls @Override protected String getActionName(PsiDirectory psiDirectory, String s) { return null; } } 2、添加到new菜單NewGroup <actions>
    <action id=" MyCreateElementActionBase " class="MyCreateElementActionBase" text="MyCreateElementActionBase" description="MyCreateElementActionBase">
      <add-to-group group-id="NewGroup" anchor="last"/>
    </action>
  </actions>


3|設置文件類型:FileTypeIdentifiableByVirtualFile public class MyFileTypeIdentifiableByVirtualFile implements FileTypeIdentifiableByVirtualFile { @Override public boolean isMyFileType(@NotNull VirtualFile virtualFile) { return false; } @NotNull @Override public String getName() { return "xml"; } @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull @Override public String getDescription() { return "xml"; } @NotNull @Override public String getDefaultExtension() { return "xml"; } @Nullable @Override public Icon getIcon() { return AllIcons.Actions.Scratch; } @Override public boolean isBinary() { return false; } @Override public boolean isReadOnly() { return false; } @Nullable @Override public String getCharset(@NotNull VirtualFile virtualFile, @NotNull byte[] bytes) { return null; } }

 

二十七:彈出輸入框

 String input = Messages.showInputDialog(e.getProject(), "Input", "New", AllIcons.Actions.Scratch, "", null); Messages.showInfoMessage(input, "New Title");

 

 二十八,控制台日志着色

1、創建MyFilter實現Filter public class MyFilter implements Filter { private static Integer offset = 0; @Nullable @Override public Result applyFilter(@NotNull String s, int i) { offset += s.length(); Result result = null; if (s.length() > 5) { TextAttributes textAttributes = new TextAttributes(); textAttributes.setBackgroundColor(JBColor.WHITE); textAttributes.setForegroundColor(JBColor.RED); TextAttributes textAttributes2 = new TextAttributes(); textAttributes2.setBackgroundColor(JBColor.YELLOW); textAttributes2.setForegroundColor(JBColor.GREEN); // 點擊日志跳轉
            HyperlinkInfo info = new HyperlinkInfo() { @Override public void navigate(Project project) { navigate(project); } }; List<ResultItem> list = new ArrayList<>(); // 前段白底紅字
            ResultItem item = new ResultItem(offset - s.length(), offset - 5, info, textAttributes); // 最后5個字符黃底綠字
            ResultItem item2 = new ResultItem(offset - 5, offset, info, textAttributes2); list.add(item); list.add(item2); result = new Result(list); } return result; } } 2、新建MyConsoleFilterProvider實現ConsoleFilterProvider public class MyConsoleFilterProvider implements ConsoleFilterProvider { @NotNull @Override public Filter[] getDefaultFilters(@NotNull Project project) { return new Filter[]{new MyFilter()}; } } 3、plugin.xml <extensions defaultExtensionNs="com.intellij">
    <consoleFilterProvider implementation="MyConsoleFilterProvider" />
  </extensions>

 

二十六:日志折疊

1、新建MyConsoleFolding實現接口ConsoleFolding public class MyConsoleFolding extends ConsoleFolding { @Override public boolean shouldFoldLine(@NotNull Project project, @NotNull String line) { // 如果包含hello字符則折疊
        return line.contains("hello"); } @Nullable @Override public String getPlaceholderText(@NotNull Project project, @NotNull List<String> lines) { return "< line" + lines.size() + ">"; } } 2、plugin.xml配置 <extensions defaultExtensionNs="com.intellij">
    <console.folding implementation="MyConsoleFolding"/>
  </extensions>

 

二十七:全局設置頁添加面板

1、新建MyConfigurable實現接口Configurable public class MyConfigurable implements Configurable { @Nls(capitalization = Nls.Capitalization.Title) @Override public String getDisplayName() { return "設置面板"; } @Nullable @Override public JComponent createComponent() { return new ConfigFrame(); } @Override public boolean isModified() { return false; } @Override public void apply() throws ConfigurationException { } } 2、plugin.xml配置 <extensions defaultExtensionNs="com.intellij">
    <applicationConfigurable id="myConfigurable" displayName="新面板" implementation="MyConfigurable"/>
  </extensions>

3、添加panel public class ConfigFrame extends SimpleToolWindowPanel { private JTree tree1; private JPanel rootPanel; public ConfigFrame() { super(true, true); add(rootPanel); } }

 

 二十八:日志輸入過濾器實現接口ConsoleInputFilterProvider

plugin.xml配置consolInputFilterProvider

 

二十九:JEditorPanel組件添加超鏈接 

1、將JEditorPane設置為不可編輯 editorPane1.setEditable(false); 2、將JEditorPane設置為網頁格式 editorPane1.setContentType("text/html"); 3、JEditorPane中添加a標簽 editorPane1.setText("<a href=\"http://www.baidu.com\">百度</a>"); 4、添加超鏈接監聽器HyperlinkListener editorPane1.addHyperlinkListener(e -> { if (Desktop.isDesktopSupported() && e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) { try { Desktop.getDesktop().browse(e.getURL().toURI()); } catch (IOException ioException) { ioException.printStackTrace(); } catch (URISyntaxException uriSyntaxException) { uriSyntaxException.printStackTrace(); } } });


三十:插件更新提示

public class MyPlugin extends AnAction { @Override public void actionPerformed(AnActionEvent e) { NotificationGroup group = new NotificationGroup("MyNotifyId", NotificationDisplayType.BALLOON, true); Notification notification = group.createNotification("MyTitle", "省略...", "內容", NotificationType.INFORMATION); NotificationAction actions = new NotificationAction("點擊按鈕") { @Override public void actionPerformed(@NotNull AnActionEvent anActionEvent, @NotNull Notification notification) { Messages.showInfoMessage("提示內容", "提示標題"); } }; notification.addAction(actions); notification.notify(e.getProject()); }
 
        

三十一:配置數據持久化:@State,
PersistentStateComponent
1、新建配置類,用來持久化數據StorageConfig public class StorageConfig { private String name; private String value; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } 2、新建數據持久化state類MyState @State(name = "MyStorage",storages = {@Storage("my-config.xml")}) public class MyState implements PersistentStateComponent<MyState> { private StorageConfig config; public static MyState getInstance(){ return ServiceManager.getService(MyState.class); } @Nullable @Override public MyState getState() { return this; } @Override public void loadState(@NotNull MyState myState) { if (null == myState) { return; } XmlSerializerUtil.copyBean(myState, this); } public StorageConfig getConfig() { if (null == config) { config = new StorageConfig(); } return config; } public void setConfig(StorageConfig config) { this.config = config; } } 3、新建面板JFrame:ConfigFrame public class ConfigFrame extends SimpleToolWindowPanel { private JTree tree1; private JPanel rootPanel; private JTextField textField1; private JButton button1; public ConfigFrame() { super(true, true); add(rootPanel); button1.addActionListener(e -> apply()); } public void apply() { StorageConfig config = MyState.getInstance().getConfig(); if (null == config) { config = new StorageConfig(); } config.setName(textField1.getText()); config.setValue(textField1.getText() + "-new"); } } 4、新建設置面板類MyConfig public class MyConfig implements SearchableConfigurable { private ConfigFrame frame; @NotNull @Override public String getId() { return "MyConfig"; } @Nls(capitalization = Nls.Capitalization.Title) @Override public String getDisplayName() { return "設置面板"; } @Nullable @Override public JComponent createComponent() { return frame = new ConfigFrame(); } @Override public boolean isModified() { return false; } @Override public void apply() throws ConfigurationException { frame.apply(); } } 5、plugin.xml配置 <extensions defaultExtensionNs="com.intellij">
    <applicationConfigurable id="MyConfig" displayName="新面板" implementation="MyConfig"/>
    <applicationService serviceImplementation="MyState"/>
  </extensions>

6、獲取持久化配置的數據 StorageConfig config = MyState.getInstance().getConfig(); Messages.showInfoMessage(config.getName(), config.getValue()+"---");
 
        

 

三十一:在IDEA主窗口菜單欄添加菜單選項=>MainMenu

添加菜單組到IDEA主窗口菜單欄中:MainMenu <actions>
    <group id="NewGroupId" text="MyMenu" popup="true">
      <add-to-group group-id="MainMenu" anchor="last"/>
      <action class="MyPlugin" text="MyPlugin" id="MyPluginss"/>
    </group>
  </actions>

 

三十二:新建項目繼承NewProjectAction

public class MyCreateProjectAction extends NewProjectAction { } 2、配置plugin.xml <group id="NewGroupId" text="MyMenu" popup="true">
      <action id="MyCreateProjectActionId" class="MyCreateProjectAction" text="MyCreateProjectAction"/>
      <add-to-group group-id="MainMenu" anchor="last"/>
    </group>
 
        

 

三十三:XML標簽與java函數互相跳轉

1、XML跳轉java,plugin.xml的language="XML" 新建MyRelatedItemLineMarkerProvider 繼承RelatedItemLineMarkerProvider實現collectNavigationMarkers public class MyRelatedItemLineMarkerProvider extends RelatedItemLineMarkerProvider { private List<String> list = new ArrayList<>(Arrays.asList("select", "update", "insert", "delete")); @Override protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo> result) { PsiFile containingFile = element.getContainingFile(); if (containingFile instanceof XmlFile && element instanceof XmlTag) { XmlFile xmlFile = (com.intellij.psi.xml.XmlFile) containingFile; XmlTag rootTag = xmlFile.getRootTag(); Project project = element.getProject(); if ("mapper".equals(rootTag.getName())) { XmlAttribute namespace = rootTag.getAttribute("namespace"); String substring = namespace.getValue().substring(namespace.getValue().lastIndexOf(".") + 1); XmlTag xmlTag = (XmlTag) element; if (StringUtils.isNotBlank(xmlTag.getName()) &&list.contains(xmlTag.getName())) { XmlAttribute id = xmlTag.getAttribute("id"); if (StringUtils.isNotBlank(id.getValue())) { // 查找文件
                        PsiFile psiFile = FilenameIndex.getFilesByName(project, substring + ".java", GlobalSearchScope.projectScope(project))[0]; PsiElement[] children = psiFile.getChildren(); List<PsiElement> collect = Stream.of(children).parallel() .filter(p -> p instanceof PsiClass) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(collect)) { PsiClass psiElement = (PsiClass) collect.get(0); PsiMethod[] methods = psiElement.getMethods(); if (null != methods && methods.length > 0) { for (PsiMethod method : methods) { if (method.getName().equals(id.getValue())) { NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder .create(AllIcons.Actions.Back) .setTarget(method) .setTooltipTitle("go to method"); result.add(builder.createLineMarkerInfo(element)); } } } } } } } } } } plugin.xml配置 <extensions defaultExtensionNs="com.intellij">
    <codeInsight.lineMarkerProvider implementationClass="MyRelatedItemLineMarkerProvider" language="XML"/>
  </extensions>

2、java跳轉xml,plugin.xml的language="JAVA" 新建MyRelatedItemLineMarkerProvider2繼承RelatedItemLineMarkerProvider public class MyRelatedItemLineMarkerProvider2 extends RelatedItemLineMarkerProvider { @Override protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo> result) { if (element instanceof PsiMethod) { PsiMethod method = (PsiMethod) element; String packageName = ((PsiJavaFileImpl) method.getContainingFile()).getPackageName(); PsiClass PsiClass = (PsiClass) method.getParent(); String nameSpace = packageName + "." + PsiClass.getName(); // PsiShortNamesCache.getInstance(element.getProject()).getAllFileNames() 獲取所有文件名
            List<String> collect = Stream.of(PsiShortNamesCache.getInstance(element.getProject()).getAllFileNames()) .filter(p -> p.contains(".xml")) .collect(Collectors.toList()); // FilenameIndex.getFilesByName(element.getProject(), p, GlobalSearchScope.projectScope(element.getProject()))獲取指定文件名的文件
            List<XmlFile> xmlFileList = collect.parallelStream().flatMap(p -> Stream.of(FilenameIndex.getFilesByName(element.getProject(), p, GlobalSearchScope.projectScope(element.getProject())))) .filter(p -> p instanceof XmlFile) .map(p -> { XmlFile file = (XmlFile) p; return file; }) .filter(p -> p.getRootTag().getAttribute("namespace") != null && p.getRootTag().getAttribute("namespace").getValue().equals(nameSpace)) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(xmlFileList)) { for (XmlFile xmlFile : xmlFileList) { XmlTag rootTag = xmlFile.getRootTag(); XmlTag[] children = rootTag.getSubTags(); if (null != children && children.length > 0) { List<XmlTag> id = Stream.of(children).parallel() .filter(p -> p.getAttribute("id").getValue()!=null &&p.getAttribute("id").getValue().equals(method.getName())) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(id)) { XmlTag xmlTag = id.get(0); NavigationGutterIconBuilder<PsiElement> builder=NavigationGutterIconBuilder .create(AllIcons.Actions.Close) .setTarget(xmlTag) .setTooltipTitle("go to mapper"); result.add(builder.createLineMarkerInfo(element)); } } } } } } } plugin.xml配置 <extensions defaultExtensionNs="com.intellij">
    <codeInsight.lineMarkerProvider implementationClass="MyRelatedItemLineMarkerProvider2" language="JAVA"/>
  </extensions>


三十四:新建項目自定義模板,核心類是ModuleBuilder
1、新建第一步的面板Frame:StepForm1 繼承SimpleToolWindowPanel public class StepForm1 extends SimpleToolWindowPanel { private JPanel panel; private JLabel label; public StepForm1() { super(true, true); add(panel); label.setText("第一步"); } } 2、新建第一步配置步驟,MyModuleWizardStep1繼承ModuleWizardStep public class MyModuleWizardStep1 extends ModuleWizardStep { @Override public JComponent getComponent() { return new StepForm1(); } @Override public void updateDataModel() { } } 3、新建第一二步面板:StepForm2繼承SimpleToolWindowPanel public class StepForm2 extends SimpleToolWindowPanel { private JPanel panel; private JLabel label; public StepForm2() { super(true, true); add(panel); label.setText("第二步"); } } 4、新建第二步配置步驟:MyModuleWizardStep2繼承ModuleWizardStep public class MyModuleWizardStep2 extends ModuleWizardStep { @Override public JComponent getComponent() { return new StepForm2(); } @Override public void updateDataModel() { } } 5、新建最后一步SDK配置步驟:MyModuleWizardStep3繼承SdkSettingsStep public class MyModuleWizardStep3 extends SdkSettingsStep { public MyModuleWizardStep3(SettingsStep settingsStep, @NotNull ModuleBuilder moduleBuilder, @NotNull Condition<? super SdkTypeId> sdkTypeIdFilter) { super(settingsStep, moduleBuilder, sdkTypeIdFilter); } } 6、初始化新模塊屬性:MyModuleBuilder繼承ModuleBuilder public class MyModuleBuilder extends ModuleBuilder { /** * @description: 模塊描述 * * @author: chenzhiwei * @create: 2020/5/31 11:46 * @return java.lang.String */ @Nls(capitalization = Nls.Capitalization.Sentence) @Override public String getDescription() { return "GetDescription"; } /** * @description: 模塊名稱 * * @author: chenzhiwei * @create: 2020/5/31 11:47 * @return java.lang.String */ @Override public String getName() { return "newModule"; } /** * @description: 模塊名稱顯示 * * @author: chenzhiwei * @create: 2020/5/31 11:47 * @return java.lang.String */ @Nls(capitalization = Nls.Capitalization.Title) @Override public String getPresentableName() { return "新模塊"; } @Override public String getParentGroup() { return "JAVA"; } @Override public String getGroupName() { return "GroupName"; } @Nullable @Override public String getBuilderId() { return getClass().getName(); } @Override public ModuleWizardStep modifyProjectTypeStep(@NotNull SettingsStep settingsStep) { return new EmptyStep(); } @Override public ModuleType<?> getModuleType() { ModuleType moduleType = new ModuleType("MyModuleIdss") { @NotNull @Override public ModuleBuilder createModuleBuilder() { return MyModuleBuilder.this; } @Nls(capitalization = Nls.Capitalization.Title) @NotNull @Override public String getName() { return "NewModuleType"; } @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull @Override public String getDescription() { return "ModuleType"; } @NotNull @Override public Icon getNodeIcon(boolean b) { return AllIcons.Actions.Refresh; } }; return moduleType; } /** * @description: 配置步驟一 * * @author: chenzhiwei * @create: 2020/5/31 11:47 * @return com.intellij.ide.util.projectWizard.ModuleWizardStep */ @Nullable @Override public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) { return new MyModuleWizardStep1(); } /** * @description: 配置步驟二 * * @author: chenzhiwei * @create: 2020/5/31 11:48 * @return com.intellij.ide.util.projectWizard.ModuleWizardStep[] */ @Override public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) { return new ModuleWizardStep[]{new MyModuleWizardStep2()}; } /** * @description: 配置最后步驟 * * @author: chenzhiwei * @create: 2020/5/31 11:48 * @return com.intellij.ide.util.projectWizard.ModuleWizardStep */ @Nullable @Override public ModuleWizardStep modifySettingsStep(@NotNull SettingsStep settingsStep) { Condition<SdkTypeId> condition = sdkTypeId -> sdkTypeId == JavaSdk.getInstance(); return  new MyModuleWizardStep3(settingsStep, this, condition); } /** * @description: finish完成回調函數 * * @author: chenzhiwei * @create: 2020/5/31 11:48 * @return void */ @Override public void setupRootModel(@NotNull ModifiableRootModel modifiableRootModel) { Messages.showInfoMessage("111", "22"); } } 7、plugin.xml配置 <extensions defaultExtensionNs="com.intellij">
    <moduleBuilder builderClass="MyModuleBuilder" id="moduleIds"/>
  </extensions>
 
        


WriteCommandAction.wri

String cintent
VirtualFile pomfile=root.findOrCreateChildData(this,pom.xml)
VfsUtil.saveText(pomfile,content)
Document doc=FileDocumentManager.getInstance().getDocument(pomfile)
PsiDocumentManager.getInstance(project).doPostponedOperationAndUnblockDocument(doc)
FileDocumentManager.getinstance().reloadFromDisk(doc)

三十五:代碼提示並修復
public class MyAbstractBaseJavaLocalInspectionTool2 extends AbstractBaseJavaLocalInspectionTool {

    @NotNull
    @Override
    public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {

        JavaElementVisitor visitor = new JavaElementVisitor() {
            @Override
            public void visitField(PsiField field) {
                super.visitField(field);
                holder.registerProblem(field, "hello world");
            }
        };
        return visitor;
    }

    @NotNull
    @Override
    public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
        SuppressQuickFix suppressQuickFix = new SuppressQuickFix() {
            @Nls(capitalization = Nls.Capitalization.Sentence)
            @NotNull
            @Override
            public String getFamilyName() {
                return "QuickFix2222";
            }

            @Override
            public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor problemDescriptor) {
                System.out.println("==========");
            }

            @Override
            public boolean isAvailable(@NotNull Project project, @NotNull PsiElement psiElement) {
                return psiElement instanceof PsiField;
            }

            @Override
            public boolean isSuppressAll() {
                return false;
            }
        };
        return new SuppressQuickFix[]{suppressQuickFix};

    }
    
}



<extensions defaultExtensionNs="com.intellij">
    <localInspection  language="JAVA"
                      displayName="Test field error11"
                      groupPath="Java"
                      groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.probable.bugs"
                      enabledByDefault="true"
                      level="ERROR" implementationClass="MyAbstractBaseJavaLocalInspectionTool2"/>
  </extensions>
 
        

 三十六:添加到右鍵菜單

<action id="EditorBasics.EditorIllustrationAction"
        class="org.intellij.sdk.editor.EditorIllustrationAction"
        text="Editor Replace Text"
        description="Replaces selected text with 'Replacement'."
        icon="SdkIcons.Sdk_default_icon">
  <add-to-group group-id="EditorPopupMenu" anchor="first"/>
</action>

 

三十七:是否顯示action

public class EditorIllustrationAction extends AnAction {
  @Override
  public void update(@NotNull final AnActionEvent e) {
    // Get required data keys
    final Project project = e.getProject();
    final Editor editor = e.getData(CommonDataKeys.EDITOR);
    
    // Set visibility only in case of existing project and editor and if a selection exists
    e.getPresentation().setEnabledAndVisible( project != null 
                                              && editor != null 
                                              && editor.getSelectionModel().hasSelection() );
  }
}

 

三十七:代碼元素前添加圖標操作RunLineMarkerContributor

public class MyRunLineMarkerContributor extends RunLineMarkerContributor {
    @Nullable
    @Override
    public Info getInfo(@NotNull PsiElement psiElement) {

        if (psiElement instanceof PsiMethod) {

            AnAction[] array = new AnAction[3];
            array[0] = new AnAction("11111") {
                @Override
                public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
                    Messages.showInfoMessage("1", "1");
                }
            };
            array[1] = new AnAction("22222") {
                @Override
                public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
                    Messages.showInfoMessage("2", "2");
                }
            };
            array[2] = new AnAction("333333") {
                @Override
                public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
                    Messages.showInfoMessage("3", "3");
                }
            };
            return new Info(AllIcons.RunConfigurations.TestState.Run, array, psiElement1 -> "hello");
        }
        return null;
    }
}

      <runLineMarkerContributor language="JAVA" 

plugin.xml配置
implementationClass="MyRunLineMarkerContributor"/>

 

 

三十八:自定義文件語言:Language

public class PfcLanguage extends Language {
public static final PfcLanguage INSTANCE = new PfcLanguage();
protected PfcLanguage() {
super("pfc");
}
}

public class PfcFile extends PsiFileBase {

public PfcFile(@NotNull FileViewProvider viewProvider) {
super(viewProvider, PfcLanguage.INSTANCE);
}

@NotNull
@Override
public FileType getFileType() {
return PfcLanguageFileType.INSTANCE;
}

@Override
public String toString() {
return "Pfc File";
}
}

public class PfcLanguageFileType extends LanguageFileType {
public static final PfcLanguageFileType INSTANCE = new PfcLanguageFileType();

protected PfcLanguageFileType() {
super(PfcLanguage.INSTANCE);
}

@NotNull
@Override
public String getName() {
return "Pfc file";
}

@NotNull
@Override
public String getDescription() {
return "pfc language file";
}

@NotNull
@Override
public String getDefaultExtension() {
return "pfc";
}

@Nullable
@Override
public Icon getIcon() {
// return PinganIcons.API_FILE;
return AllIcons.Actions.Back;
}
}




public class PfcFileTypeFactory extends FileTypeFactory {

@Override
public void createFileTypes(@NotNull FileTypeConsumer fileTypeConsumer) {
fileTypeConsumer.consume(PfcLanguageFileType.INSTANCE);
}
}



public class PfcParserDefinition implements ParserDefinition {

private static final IFileElementType PLANTUML_FILE_ELEMENT_TYPE = new IFileElementType(PfcLanguage.INSTANCE) {
@Override
public ASTNode parseContents(ASTNode chameleon) {
final CharSequence chars = chameleon.getChars();
return ASTFactory.leaf(PlainTextTokenTypes.PLAIN_TEXT, chars);
}
};

@NotNull
@Override
public Lexer createLexer(Project project) {
return new EmptyLexer();
}

@NotNull
@Override
public TokenSet getWhitespaceTokens() {
return TokenSet.EMPTY;
}

@NotNull
@Override
public TokenSet getCommentTokens() {
return TokenSet.EMPTY;
}

@NotNull
@Override
public TokenSet getStringLiteralElements() {
return TokenSet.EMPTY;
}

@NotNull
@Override
public PsiParser createParser(final Project project) {
throw new UnsupportedOperationException("Not supported1111");
}

@Override
public IFileElementType getFileNodeType() {
return PLANTUML_FILE_ELEMENT_TYPE;
}

@Override
public PsiFile createFile(FileViewProvider viewProvider) {
return new PfcFile(viewProvider);
}

@Override
public SpaceRequirements spaceExistenceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY;
}

@NotNull
@Override
public PsiElement createElement(ASTNode node) {
return PsiUtilCore.NULL_PSI_ELEMENT;
}
}

<fileTypeFactory implementation="com.pingan.core.language.pfc.PfcFileTypeFactory"/>
<lang.parserDefinition language="pfc" implementationClass="com.pingan.core.language.pfc.PfcParserDefinition"/>

 

三十九:自定義文件類型並添加圖標執行

四十:添加到主界面的按鈕:
<add-to-group group-id="NavBarToolBar"/>

四十一:plugin.xml引用外部xml配置
 <depends optional="true" config-file="plugin_xxx.xml">com.intellij.xxxx</depends>
 

四十二:ctrl+鼠標左鍵
XmlTagGotoDeclarationHandler implements GotoDeclarationHandler



    <gotoDeclarationHandler implementation="com.pingan.contributor.XmlTagGotoDeclarationHandler"/>
 
        

  

四十二:關鍵字補全:CompletionContributor

<completion.contributor language="PUML"
                                implementationClass="org.plantuml.idea.lang.PlantUmlCompletionContributor"/>

public class PfcCompletionContributor extends CompletionContributor implements DumbAware {
private static final Logger LOG = Logger.getInstance(PfcCompletionContributor.class);

public PfcCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new PfcCompletionProvider(PfcLanguageDescriptor.INSTANCE.keywords));
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new PfcCompletionProvider(PfcLanguageDescriptor.INSTANCE.types));
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new PfcCompletionProvider(PfcLanguageDescriptor.INSTANCE.keywordsWithoutHighlight));
}

public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
int offset = parameters.getOffset();
Document document = parameters.getEditor().getDocument();
int lineStartOffset = document.getLineStartOffset(document.getLineNumber(offset));
String text = document.getText(TextRange.create(lineStartOffset, offset));
Iterator iterator;
String value;
if (text.matches("\\s*!\\w*$")) {
iterator = PfcLanguageDescriptor.INSTANCE.preproc.iterator();
while (iterator.hasNext()) {
value = (String) iterator.next();
result.addElement(LookupElementBuilder.create(value.substring(1)).withPresentableText(value).withCaseSensitivity(true).bold());
}
} else if (text.matches("\\s*@\\w*$")) {
iterator = PfcLanguageDescriptor.INSTANCE.tags.iterator();

while (iterator.hasNext()) {
value = (String) iterator.next();
result.addElement(LookupElementBuilder.create(value.substring(1)).withPresentableText(value).withCaseSensitivity(true).bold());
}
} else {
if (text.endsWith("!")) {
return;
}

super.fillCompletionVariants(parameters, result);
// if (PlantUmlSettings.getInstance().isAutoComplete()) {
// WordCompletionContributor.addWordCompletionVariants(result, parameters, Collections.emptySet());
// }
WordCompletionContributor.addWordCompletionVariants(result, parameters, Collections.emptySet());
}
}

}


public class PfcCompletionProvider extends CompletionProvider<CompletionParameters> {

private final List<String> myItems;

PfcCompletionProvider(List<String> items) {
myItems = items;
}
@Override
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext processingContext, @NotNull CompletionResultSet result) {
if (parameters.getInvocationCount() == 0) {
return;
}
for (String item : myItems) {
result.addElement(LookupElementBuilder.create(item).withCaseSensitivity(true).withItemTextItalic(true));
}
}
}


public enum PfcLanguageDescriptor {
INSTANCE;

public static final String IDEA_PARTIAL_RENDER = "idea.partialRender";
public static final String IDEA_DISABLE_SYNTAX_CHECK = "idea.disableSyntaxCheck";

public static final String TAGS = "uml|dot|jcckit|ditaa|salt|math|latex|mindmap|gantt|wbs";

public final List<String> types = Collections.unmodifiableList(Arrays.asList(
"actor",
"participant",
"usecase",
"class",
"interface",
"abstract",
"enum",
"component",
"state",
"object",
"artifact",
"folder",
"rectangle",
"node",
"frame",
"cloud",
"database",
"storage",
"agent",
"stack",
"boundary",
"control",
"entity",
"card",
"file",
"package",
"queue",
"archimate",
"diamond"

));
public final List<String> tags = Collections.unmodifiableList(Arrays.asList(
"@startuml",
"@startdot",
"@startjcckit",
"@startditaa",
"@startsalt",
"@startmath",
"@startlatex",
"@startmindmap",
"@startgantt",
"@startwbs",
"@enduml",
"@enddot",
"@endjcckit",
"@endditaa",
"@endsalt",
"@endmath",
"@endlatex",
"@endmindmap",
"@endgantt",
"@endwbs"

));

public final List<String> keywordsWithoutHighlight = Collections.unmodifiableList(Arrays.asList(
"as",
"also",
"of",
"on",
"is"
));

public final List<String> keywords = Collections.unmodifiableList(Arrays.asList(
"autonumber",
"caption",
"title",
"newpage",
"box",
"alt",
"else",
"opt",
"loop",
"par",
"break",
"critical",
"note",
"rnote",
"hnote",
"legend",
"group",
"left",
"right",
"link",
"over",
"end",
"activate",
"deactivate",
"destroy",
"create",
"footbox",
"hide",
"show",
"skinparam",
"skin",
"top",
"bottom",
"top to bottom direction",
"package",
"namespace",
"page",
"up",
"down",
"if",
"else",
"elseif",
"endif",
"partition",
"footer",
"header",
"center",
"rotate",
"ref",
"return",
"repeat",
"start",
"stop",
"while",
"endwhile",
"fork",
"again",
"kill",
"order",
"allow_mixing",
"allowmixing",
"mainframe"
));

public final List<String> pluginSettingsPattern = Collections.unmodifiableList(Arrays.asList(
IDEA_PARTIAL_RENDER,
IDEA_DISABLE_SYNTAX_CHECK
));



public final List<String> preproc = Collections.unmodifiableList(Arrays.asList(
"!exit",
"!include",
"!pragma",
"!define",
"!undef",
"!if",
"!ifdef",
"!endif",
"!ifndef",
"!else",
"!definelong",
"!enddefinelong"
));



}
 
        

  

四十三:選擇文件夾

FileSaverDescriptor fsd = new FileSaverDescriptor("Save diagram", "Please choose where to save diagram");
        VirtualFile baseDir = ProjectUtil.guessProjectDir(anActionEvent.getProject());
        final VirtualFileWrapper wrapper = FileChooserFactory.getInstance().createSaveFileDialog(fsd, anActionEvent.getProject()).save(baseDir, "defaultFileName");
        

  

四十四:監聽文件修改

1、實現DocumentListener接口

public class PfcDocumentListener implements DocumentListener {

    @Override
    public void documentChanged(@NotNull DocumentEvent event) {
        FileDocumentManager instance = FileDocumentManager.getInstance();
        VirtualFile file = instance.getFile(event.getDocument());
        EditorFactory editorFactory = EditorFactory.getInstance();
        Editor[] editors = editorFactory.getEditors(event.getDocument());
        System.out.println("=========");
    }
}


2、注冊監聽器
EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
        eventMulticaster.addDocumentListener(plantUmlDocumentListener);
移除監聽器
  EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
        eventMulticaster.removeDocumentListener(plantUmlDocumentListener);

示例:
public class PlantUmlApplicationComponent implements ApplicationComponent {
    private DocumentListener plantUmlDocumentListener = new PfcDocumentListener();

    public PlantUmlApplicationComponent() {
		PlantUmlApplicationComponent.class.getClassLoader().setDefaultAssertionStatus(false);
	}

	@Override
    public void initComponent() {
        EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
        eventMulticaster.addDocumentListener(plantUmlDocumentListener);
    }

    @Override
    public void disposeComponent() {
        EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
        eventMulticaster.removeDocumentListener(plantUmlDocumentListener);
    }

    @Override
    @NotNull
    public String getComponentName() {
        return "PlantUmlApplicationComponent";
    }

}

  <application-components>
    <!-- Add your application components here -->
    <component>
      <implementation-class>com.pingan.core.PlantUmlApplicationComponent</implementation-class>
    </component>
  </application-components>

  

四十五:監聽字符變化

1、實現CaretListener接口
public class PfcCaretListener implements CaretListener {

    @Override
    public void caretPositionChanged(@NotNull CaretEvent event) {
        System.out.println("========");
    }

    @Override
    public void caretAdded(@NotNull CaretEvent event) {
        System.out.println("=========");
    }
}

2、注冊監聽
public class PlantUmlApplicationComponent implements ApplicationComponent {
    private DocumentListener plantUmlDocumentListener = new PfcDocumentListener();
    private CaretListener pfcCaretListener = new PfcCaretListener();

    public PlantUmlApplicationComponent() {
		PlantUmlApplicationComponent.class.getClassLoader().setDefaultAssertionStatus(false);
	}

	@Override
    public void initComponent() {
        EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
        eventMulticaster.addDocumentListener(plantUmlDocumentListener);
        eventMulticaster.addCaretListener(pfcCaretListener);
    }

    @Override
    public void disposeComponent() {
        EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
        eventMulticaster.removeDocumentListener(plantUmlDocumentListener);
        eventMulticaster.removeCaretListener(pfcCaretListener);
    }

    @Override
    @NotNull
    public String getComponentName() {
        return "PlantUmlApplicationComponent";
    }

}

    <application-components>
      <!-- Add your application components here -->
      <component>
        <implementation-class>com.pingan.core.PlantUmlApplicationComponent</implementation-class>
      </component>
    </application-components>

  

四十六:添加鼠標事件

1、鼠標右鍵事件
        panel.addMouseListener(new PopupHandler() {
            @Override
            public void invokePopup(Component component, int x, int y) {
                ActionManager.getInstance().createActionPopupMenu("hello", new ActionGroup() {
                    @NotNull
                    @Override
                    public AnAction[] getChildren(@Nullable AnActionEvent anActionEvent) {
                        return new AnAction[]{new DownloadImageAction()};
                    }
                }).getComponent().show(component, x, y);
            }
        });

2、鼠標滾輪事件
addMouseWheelListener
imagePanel.addMouseWheelListener((wheelEvent) -> {
System.out.println(wheelEvent.getWheelRotation());
});

  

四十七:如果運行是報ClassNOtFoundException,考慮添加以下內容
  <depends>com.intellij.modules.java</depends>
  <depends>com.intellij.properties</depends>
  <depends>org.jetbrains.plugins.yaml</depends>
  <depends>org.jetbrains.kotlin</depends>
 
        

  

四十八:Tree使用SimpleTree

JTree tree = new SimpleTree();
DefaultTreeModel   model = (DefaultTreeModel) tree.getModel();
        DefaultTreeCellRenderer cellRenderer = (DefaultTreeCellRenderer) tree.getCellRenderer();
        cellRenderer.setLeafIcon(PinganIcons.TOOL_WINDOW);
        cellRenderer.setClosedIcon(PinganIcons.TOOL_WINDOW);
        cellRenderer.setOpenIcon(PinganIcons.TOOL_WINDOW);
        JBScrollPane scrollPane = new JBScrollPane(tree);
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode(rootNode);
        model.setRoot(rootTreeNode);
// 設置圖標
tree.setCellRenderer(new ColoredTreeCellRenderer() {
@Override
public void customizeCellRenderer(@NotNull JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (tree instanceof SimpleTree) {
setIcon(PinganIcons.TOOL_WINDOW);
append(String.valueOf(value));
}
}
});

  

四十九:修改過的文件
ChangeListManager changeListManager = ChangeListManager.getInstance(project);

五十:plugin.xml添加圖標方式:使用相對路勁引入

五十一:多個窗口共用一個window時,不能將組件進行單例化,否則多個項目面板會錯亂




免責聲明!

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



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