5. Zest和JFace的例子
5.1 创建工程
创建一个RCP应用"de.vogella.zest.jface",使用"RCP Application with a view"做为模板。增加zest的依赖项。修改Pespective.java如下:
package de.vogella.zest.jface;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(false);
layout.setFixed(true);
layout.addView(View.ID, IPageLayout.LEFT, 1.0f, editorArea);
}
}
5.2 模型
创建以下模型:
package de.vogella.zest.jface.model;
import java.util.ArrayList;
import java.util.List;
public class MyNode {
private final String id;
private final String name;
private List<MyNode> connections;
public MyNode(String id, String name) {
this.id = id;
this.name = name;
this.connections = new ArrayList<MyNode>();
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public List<MyNode> getConnectedTo() {
return connections;
}
}
package de.vogella.zest.jface.model;
public class MyConnection {
final String id;
final String label;
final MyNode source;
final MyNode destination;
public MyConnection(String id, String label, MyNode source, MyNode destination) {
this.id = id;
this.label = label;
this.source = source;
this.destination = destination;
}
public String getLabel() {
return label;
}
public MyNode getSource() {
return source;
}
public MyNode getDestination() {
return destination;
}
}
package de.vogella.zest.jface.model;
import java.util.ArrayList;
import java.util.List;
public class NodeModelContentProvider {
private List<MyConnection> connections;
private List<MyNode> nodes;
public NodeModelContentProvider() {
// Image here a fancy DB access
// Now create a few nodes
nodes = new ArrayList<MyNode>();
MyNode node = new MyNode("1", "Hamburg");
nodes.add(node);
node = new MyNode("2", "Frankfurt");
nodes.add(node);
node = new MyNode("3", "Berlin");
nodes.add(node);
node = new MyNode("4", "Munich");
nodes.add(node);
node = new MyNode("5", "Eppelheim");
nodes.add(node);
node = new MyNode("6", "Ahrensboek");
nodes.add(node);
connections = new ArrayList<MyConnection>();
MyConnection connect = new MyConnection("1", "1", nodes.get(0),
nodes.get(1));
connections.add(connect);
connect = new MyConnection("2", "2", nodes.get(0), nodes.get(4));
connections.add(connect);
connect = new MyConnection("3", "3", nodes.get(2), nodes.get(1));
connections.add(connect);
connect = new MyConnection("4", "3", nodes.get(1), nodes.get(3));
connections.add(connect);
// Because we are lasy we save the info about the connections in the
// nodes
for (MyConnection connection : connections) {
connection.getSource().getConnectedTo()
.add(connection.getDestination());
}
}
public List<MyNode> getNodes() {
return nodes;
}
}
5.3 providers
创建以下content和label providers
package de.vogella.zest.jface.zestviewer;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.zest.core.viewers.IGraphEntityContentProvider;
import de.vogella.zest.jface.model.MyNode;
public class ZestNodeContentProvider extends ArrayContentProvider implements IGraphEntityContentProvider {
@Override
public Object[] getConnectedTo(Object entity) {
if (entity instanceof MyNode) {
MyNode node = (MyNode) entity;
return node.getConnectedTo().toArray();
}
throw new RuntimeException("Type not supported");
}
}
package de.vogella.zest.jface.zestviewer;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.zest.core.viewers.EntityConnectionData;
import de.vogella.zest.jface.model.MyConnection;
import de.vogella.zest.jface.model.MyNode;
public class ZestLabelProvider extends LabelProvider {
@Override
public String getText(Object element) {
if (element instanceof MyNode) {
MyNode myNode = (MyNode) element;
return myNode.getName();
}
// Not called with the IGraphEntityContentProvider
if (element instanceof MyConnection) {
MyConnection myConnection = (MyConnection) element;
return myConnection.getLabel();
}
if (element instanceof EntityConnectionData) {
EntityConnectionData test = (EntityConnectionData) element;
return "";
}
throw new RuntimeException("Wrong type: "
+ element.getClass().toString());
}
}
5.4 view
修改view如下:
package de.vogella.zest.jface;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.zest.core.viewers.AbstractZoomableViewer;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.viewers.IZoomableWorkbenchPart;
import org.eclipse.zest.core.viewers.ZoomContributionViewItem;
import org.eclipse.zest.layouts.LayoutAlgorithm;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;
import de.vogella.zest.jface.model.NodeModelContentProvider;
import de.vogella.zest.jface.zestviewer.ZestLabelProvider;
import de.vogella.zest.jface.zestviewer.ZestNodeContentProvider;
public class View extends ViewPart implements IZoomableWorkbenchPart {
public static final String ID = "de.vogella.zest.jface.view";
private GraphViewer viewer;
public void createPartControl(Composite parent) {
viewer = new GraphViewer(parent, SWT.BORDER);
viewer.setContentProvider(new ZestNodeContentProvider());
viewer.setLabelProvider(new ZestLabelProvider());
NodeModelContentProvider model = new NodeModelContentProvider();
viewer.setInput(model.getNodes());
LayoutAlgorithm layout = setLayout();
viewer.setLayoutAlgorithm(layout, true);
viewer.applyLayout();
fillToolBar();
}
private LayoutAlgorithm setLayout() {
LayoutAlgorithm layout;
// layout = new
// SpringLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
layout = new TreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new
// GridLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new
// HorizontalTreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new
// RadialLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
return layout;
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
}
private void fillToolBar() {
ZoomContributionViewItem toolbarZoomContributionViewItem = new ZoomContributionViewItem(
this);
IActionBars bars = getViewSite().getActionBars();
bars.getMenuManager().add(toolbarZoomContributionViewItem);
}
@Override
public AbstractZoomableViewer getZoomableViewer() {
return viewer;
}
}
最后结果如下:
5.5 Filter
可以通过setFilter()来定义一个filter,例如:
package de.vogella.zest.jface.zestviewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import de.vogella.zest.jface.model.MyNode;
public class NodeFilter extends ViewerFilter {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof MyNode) {
MyNode node = (MyNode) element;
return node.getName().toLowerCase().contains("a");
}
return true;
}
}
把这个filter用在所有元素上:
package de.vogella.zest.jface;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.zest.core.viewers.AbstractZoomableViewer;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.viewers.IZoomableWorkbenchPart;
import org.eclipse.zest.core.viewers.ZoomContributionViewItem;
import org.eclipse.zest.layouts.LayoutAlgorithm;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;
import de.vogella.zest.jface.model.NodeModelContentProvider;
import de.vogella.zest.jface.zestviewer.NodeFilter;
import de.vogella.zest.jface.zestviewer.ZestLabelProvider;
import de.vogella.zest.jface.zestviewer.ZestNodeContentProvider;
public class View extends ViewPart implements IZoomableWorkbenchPart {
public static final String ID = "de.vogella.zest.jface.view";
private GraphViewer viewer;
public void createPartControl(Composite parent) {
viewer = new GraphViewer(parent, SWT.BORDER);
viewer.setContentProvider(new ZestNodeContentProvider());
viewer.setLabelProvider(new ZestLabelProvider());
NodeModelContentProvider model = new NodeModelContentProvider();
viewer.setInput(model.getNodes());
LayoutAlgorithm layout = setLayout();
viewer.setLayoutAlgorithm(layout, true);
viewer.applyLayout();
NodeFilter filter = new NodeFilter();
ViewerFilter[] filters = new ViewerFilter[1];
filters[0]= filter;
viewer.setFilters(filters);
fillToolBar();
}
private LayoutAlgorithm setLayout(){
LayoutAlgorithm layout;
// layout = new SpringLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
layout = new TreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new GridLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new HorizontalTreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new RadialLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
return layout;
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
}
private void fillToolBar() {
ZoomContributionViewItem toolbarZoomContributionViewItem = new ZoomContributionViewItem(this);
IActionBars bars = getViewSite().getActionBars();
bars.getMenuManager().add(toolbarZoomContributionViewItem);
}
@Override
public AbstractZoomableViewer getZoomableViewer() {
return viewer;
}
}
注:也可以在layout上注册filter,这样在计算布局的时候,特定的元素会被忽略。方法isObjectFiltered()。使用item.getGraphData()去得到底层的object对象。
6. 技巧和提示
6.1 使用结点不可移动
缺省情况下节点都可以移动,要禁用,可以如下实现:
package de.vogella.zest.movenodes.graph;
import org.eclipse.draw2d.SWTEventDispatcher;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.zest.core.widgets.Graph;
public class NonMovableGraph extends Graph {
public NonMovableGraph(Composite parent, int style) {
super(parent, style);
this.getLightweightSystem().setEventDispatcher(
new SWTEventDispatcher() {
public void dispatchMouseMoved(
org.eclipse.swt.events.MouseEvent me) {
// Doing nothing
}
});
}
}