(九)IntelliJ 插件开发—— List and Tree
2020-03-08 本文已影响0人
秋水畏寒
官方文档
https://www.jetbrains.org/intellij/sdk/docs/user_interface_components/lists_and_trees.html
Github
https://github.com/kungyutucheng/my_gradle_plugin
运行环境
macOS 10.14.5
IntelliJ idea 2019.2.4
图形素材来源
https://www.iconfont.cn/collections/detail?spm=a313x.7781069.1998910419.de12df413&cid=16957
定义
相比JList,JBList出了拥有JList相关功能,还具备以下几个优势:
- 元素内容长度超过组件宽度时,可以以tooltip的形式展示完整内容
- 没有元素时,可以通过调用getEmptyText().setText()来设置默认展示文本
- 可以通过调用setPaintBusy()展示一个icon在组件右上角,以显示当前有后台运行任务
相比JTree,Tree则多了拖拉等功能
JBList
效果
初始效果 查找模式 AddAction ExtraActionDemo
ListAction
package com.kungyu.jblist;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
/**
* @author wengyongcheng
* @since 2020/3/5 11:23 下午
*/
public class ListAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
new ListDialogWrapper().showAndGet();
}
}
注册Action
<action id="com.kungyu.jblist.ListAction" class="com.kungyu.jblist.ListAction"
text="ListAction" description="ListAction">
<add-to-group group-id="ToolsMenu" anchor="after" relative-to-action="com.kungyu.file.chooser.FileChooserAction"/>
</action>
ListDialogWrapper
package com.kungyu.jblist;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.ListSpeedSearch;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBList;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
/**
* @author wengyongcheng
* @since 2020/3/6 11:55 下午
*/
public class ListDialogWrapper extends DialogWrapper {
private JBList<Integer> list;
private DefaultListModel<Integer> defaultListModel;
public ListDialogWrapper(){
super(true);
init();
setTitle("JBList");
}
@Nullable
@Override
protected JComponent createCenterPanel() {
defaultListModel = new DefaultListModel<>();
for (int i = 0;i < 10; i++) {
defaultListModel.addElement(i);
}
list = new JBList<>(defaultListModel);
// 修饰每一行的元素
ColoredListCellRenderer<Integer> coloredListCellRenderer = new ColoredListCellRenderer<Integer>() {
@Override
protected void customizeCellRenderer(@NotNull JList<? extends Integer> list, Integer value, int index, boolean selected, boolean hasFocus) {
append(value + "-suffix");
}
};
list.setCellRenderer(coloredListCellRenderer);
// 触发快速查找
new ListSpeedSearch<>(list);
// 增加工具栏(新增按钮、删除按钮、上移按钮、下移按钮)
ToolbarDecorator decorator = ToolbarDecorator.createDecorator(list);
// 新增元素动作
decorator.setAddAction(actionButton -> addAction());
// 自定义按钮
decorator.addExtraAction(new ExtraButtonAction(defaultListModel,list));
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(decorator.createPanel(), BorderLayout.CENTER);
return panel;
}
private void addAction() {
String newItem = Messages.showInputDialog("Input A Item", "Add", Messages.getInformationIcon());
if (StringUtils.isNotBlank(newItem)) {
defaultListModel.addElement(Integer.valueOf(newItem));
}
}
@Nullable
@Override
protected ValidationInfo doValidate() {
Integer value = list.getSelectedValue();
if (value != null) {
Messages.showMessageDialog(value + "",value + "", Messages.getInformationIcon());
}
return null;
}
}
ExtraButtonAction
package com.kungyu.jblist;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.components.JBList;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author wengyongcheng
* @since 2020/3/7 9:38 下午
*/
public class ExtraButtonAction extends AnActionButton {
private JBList list;
private DefaultListModel<Integer> model;
public ExtraButtonAction(DefaultListModel<Integer> model,JBList list) {
super("Extra", IconLoader.getIcon("/icons/edit.svg"));
this.model = model;
this.list = list;
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
int index = list.getSelectedIndex();
String newValue = Messages.showInputDialog(model.get(index) + "", "Edit", Messages.getInformationIcon());
if (StringUtils.isNotBlank(newValue)) {
model.add(index, Integer.valueOf(newValue));
}
}
}
其中,数据集合还可以使用SortedListModel
等,也可以继承AbstractListModel
来自定义,若是使用自定义数据集合,新增元素时需触发以下方法
/**
* <code>AbstractListModel</code> subclasses must call this method
* <b>after</b>
* one or more elements are added to the model. The new elements
* are specified by a closed interval index0, index1 -- the enpoints
* are included. Note that
* index0 need not be less than or equal to index1.
*
* @param source the <code>ListModel</code> that changed, typically "this"
* @param index0 one end of the new interval
* @param index1 the other end of the new interval
* @see EventListenerList
* @see DefaultListModel
*/
protected void fireIntervalAdded(Object source, int index0, int index1)
{
Object[] listeners = listenerList.getListenerList();
ListDataEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ListDataListener.class) {
if (e == null) {
e = new ListDataEvent(source, ListDataEvent.INTERVAL_ADDED, index0, index1);
}
((ListDataListener)listeners[i+1]).intervalAdded(e);
}
}
}
以SortedListModel
为例,其添加元素的方法是这样的:
private void add(int index, T item) {
myItems.add(index, item);
fireIntervalAdded(this, index, index);
}
Tree
效果
TreeDemo
TreeAction
package com.kungyu.tree;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
/**
* @author wengyongcheng
* @since 2020/3/7 10:21 下午
*/
public class TreeAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
new TreeDialogWrapper().showAndGet();
}
}
注册Action
<action id="com.kungyu.tree.TreeAction" class="com.kungyu.tree.TreeAction"
text="TreeAction" description="TreeAction">
<add-to-group group-id="ToolsMenu" anchor="after" relative-to-action="com.kungyu.jblist.ListAction"/>
</action>
TreeDialogWrapper
package com.kungyu.tree;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ui.EditableTreeModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.util.Collection;
/**
* @author wengyongcheng
* @since 2020/3/7 10:22 下午
*/
public class TreeDialogWrapper extends DialogWrapper {
private Tree tree;
private DefaultTreeModel model;
public TreeDialogWrapper() {
super(true);
init();
setTitle("Tree");
}
@Nullable
@Override
protected JComponent createCenterPanel() {
// 创建节点
DefaultMutableTreeNode child1Leaf1 = new DefaultMutableTreeNode();
child1Leaf1.setUserObject("child1Leaf1");
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode();
child1.add(child1Leaf1);
child1.setUserObject("child1");
DefaultMutableTreeNode child1Leaf2 = new DefaultMutableTreeNode();
child1Leaf2.setUserObject("child1Leaf2");
DefaultMutableTreeNode child2 = new DefaultMutableTreeNode();
child2.add(child1Leaf2);
child2.setUserObject("child2");
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
root.setUserObject("root");
root.add(child1);
root.add(child2);
// 创建数据模型
model = new DefaultTreeModel(root);
tree = new Tree(model);
tree.setDragEnabled(true);
tree.setExpandableItemsEnabled(true);
// 快速查找
new TreeSpeedSearch(tree);
// 自定义样式
ColoredTreeCellRenderer coloredTreeCellRenderer = new ColoredTreeCellRenderer() {
@Override
public void customizeCellRenderer(@NotNull JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
append(value + "-suffix");
}
};
tree.setCellRenderer(coloredTreeCellRenderer);
// 工具栏
ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(tree);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(toolbarDecorator.createPanel(), BorderLayout.CENTER);
return panel;
}
}