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時,不能將組件進行單例化,否則多個項目面板會錯亂