本节实例的效果如图15.5所示。给TreeViewer加右键菜单的方法和TableViewer相似,也要用到Action、ActionGroup、MenuManager类,当然程序要根据树的特点稍做改动。
图15.5 右键菜单效果图
(1)在15.3节主程序的tv.setInput(input)之后插入如下两句:
//--------------完整代码见文件:TreeViewer2.java--------------
MyActionGroup actionGroup = new MyActionGroup(tv);// 生成一个ActionGroup对象
actionGroup.fillContextMenu(new MenuManager());// 将按钮注入到菜单对象中
(2)创建MyActionGroup类,其代码如下所示。MyActionGroup内含各Action类,在实现Action时,对传入的结点对象要记得进行空值判断,因为TreeViewer的大部分方法都不支持空值参数,会导致异常并中断程序。
public class MyActionGroup extends ActionGroup {
private TreeViewer tv;
public MyActionGroup(TreeViewer treeViewer) {
this.tv = treeViewer;
}
// 生成菜单Menu,并将两个Action传入
public void fillContextMenu(IMenuManager mgr) {
// 加入两个Action对象到菜单管理器
MenuManager menuManager = (MenuManager) mgr; // 类型转换
menuManager.add(new OpenAction());
menuManager.add(new RefreshAction());
menuManager.add(new ExpandAction());
menuManager.add(new CollapseAction());
menuManager.add(new AddEntryAction());
menuManager.add(new RemoveEntryAction());
menuManager.add(new ModifyEntryAction());
// 生成Menu并挂在树Tree上
Tree tree = tv.getTree();
Menu menu = menuManager.createContextMenu(tree);
tree.setMenu(menu);
}
// “打开”的Action类
private class OpenAction extends Action {
public OpenAction() {
setText("打开");
}
public void run() {
ITreeEntry entry = getSelTreeEntry();
if (entry != null)
MessageDialog.openInformation(null, null, entry.getName());
}
}
// 刷新的Action类
private class RefreshAction extends Action {
public RefreshAction() {
setText("刷新");
}
// 如果在删除结点时,不同时从数据模型里删除结点。则执行本刷新后,该结点又会从
// 数据模型中取出并显示在界面上
public void run() {
tv.refresh();
}
}
// 展开当前结点的Action类
private class ExpandAction extends Action {
public ExpandAction() {
setText("展开");
}
public void run() {
ITreeEntry entry = getSelTreeEntry();
if (entry != null)
tv.expandToLevel(entry, 1); // 参数2是展开的层数
}
}
// 收缩当前结点的Action类
private class CollapseAction extends Action {
public CollapseAction() {
setText("收缩");
}
public void run() {
ITreeEntry entry = getSelTreeEntry();
if (entry != null)
tv.collapseToLevel(entry, -1); // 参数2是收缩的层数,-1指收缩所有子结点
}
}
// 给当前结点增加一个子结点的Action类
private class AddEntryAction extends Action {
public AddEntryAction() {
setText("增加");
}
public void run() {
ITreeEntry entry = getSelTreeEntry();
if (entry == null || entry instanceof PeopleEntity)
return;// 不能给“人”结点增加子结点
InputDialog dialog = new InputDialog(null, "增加子结点", "输入名称:", "a", null);
if (dialog.open() == InputDialog.OK) {// 如果单击OK按钮
String entryName = dialog.getValue(); // 得到Dialog输入值
// 根据单击结点的不同类型生成相应的子结点
ITreeEntry newEntry = null;
if (entry instanceof CountryEntity)
newEntry = new CityEntity(entryName);
else if (entry instanceof CityEntity)
newEntry = new PeopleEntity(entryName);
entry.getChildren().add(newEntry); // 新结点增加到数据模型中
tv.add(entry, newEntry);// newEntry结点增加到entry之下,或用tv.refresh(entry,true)也行
if (!tv.getExpandedState(entry)) // 如果entry是未展开结点则展开它
tv.expandToLevel(entry, 1);
}
}
}
// 删除结点的Action类
private class RemoveEntryAction extends Action {
public RemoveEntryAction() {
setText("删除");
}
public void run() {
ITreeEntry entry = getSelTreeEntry();
if (entry == null)
return;
// 从数据模型里删除结点
List<ITreeEntry> list = (List<ITreeEntry>) tv.getInput();
remove(list, entry);
// 从界面删除结点,放在从模型删除之后,
//否则在删除某个结点的最后一个子结点时会出问题
tv.remove(entry);
}
private void remove(List<ITreeEntry> list, ITreeEntry entry) {
if (list == null) return;
for (Iterator it = list.iterator(); it.hasNext();) {
ITreeEntry o = (ITreeEntry) it.next();
if (o.getName().equals(entry.getName())) {
it.remove();
return;
} else {
remove(o.getChildren(), entry);
}
}
}
}
// 修改结点名称的Action类
private class ModifyEntryAction extends Action {
public ModifyEntryAction() {
setText("修改");
}
public void run() {
ITreeEntry entry = getSelTreeEntry();
if (entry == null) return;
InputDialog dialog = new InputDialog(null, "修改结点", "输入新名称", entry.getName(), null);
if (dialog.open() == InputDialog.OK) {
String entryName = dialog.getValue();
entry.setName(entryName);//修改数据模型
tv.refresh(entry); // 刷新结点,等效于tv.update(entry,null);
}
}
}
// 为共用而自定义的方法:取得当前选择的结点
private ITreeEntry getSelTreeEntry() {
IStructuredSelection selection = (IStructuredSelection) tv.getSelection();
return (ITreeEntry) (selection.getFirstElement());
}
}
<!-- page -->