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时,不能将组件进行单例化,否则多个项目面板会错乱
有志之士,共同学习