问题
I am new be in RCP development.
I want to create two tables with, each table contains different data. Data from two tables have either 1 to 1 , 1 to many or many to 1 relationship. And that can be done by drawing arrows between two tables. For example,
**Row 1** **Row 2**
R1 V1 R2 V1
R1 V2 R2 V2
R1 V3 R2 V3
I want to draw arrows from R1V1 to ( R2V1 and R2V3 ) or vice a versa. How can I show it graphically.
How can I find that which rows are combined by arrows.
Any help is appreciated.
--- Mandar
回答1:
Here is the code that is based on the idea proposed by Nick. It is just to give an idea for someone who might wonder where to start to implement something like this shown below
This would let you click on any column on the left hand side table, then draws a line as your mouse moves on towards the right table, and anchors the line as soon as a column on the right hand side table is selected. It keeps a mapping between the left table row and right table row in a linked list as the mapping data model.
package sample;
import java.util.LinkedList;
import org.eclipse.draw2d.AutomaticRouter;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayeredPane;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.PolylineDecoration;
import org.eclipse.draw2d.XYAnchor;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
public class GraphicTableMapper {
private static Point sourcePosition;
private static PathFigure currentPath;
private static Figure bf;
private static Canvas canvas;
private static int sourceRow;
private static int targetRow;
private static LinkedList<RowMapper> rowmapList = new LinkedList<RowMapper>();
public static void main(String[] args) {
Display display = Display.getDefault();
final Shell shell = new Shell(display);
shell.setSize(550, 500);
shell.setLayout(new GridLayout(3, false));
final Table table = new Table(shell, SWT.MULTI | SWT.BORDER
| SWT.FULL_SELECTION);
table.setLinesVisible(true);
table.setHeaderVisible(true);
final String[] titles = { "Serial Number", "Whatever" };
for (int i = 0; i < titles.length; i++) {
TableColumn column = new TableColumn(table, SWT.NONE);
column.setText(titles[i]);
}
int count = 100;// create 100 rows in table
for (int i = 0; i < count; i++) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(0, "x");
item.setText(1, "y");
item.setText(2, "!");
item.setText(3, "this stuff behaves the way I expect");
item.setText(4, "almost everywhere");
item.setText(5, "some.folder");
item.setText(6, "line " + i + " in nowhere");
}
for (int i = 0; i < titles.length; i++) {
table.getColumn(i).pack();
}
table.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
Point pt = new Point(event.x, event.y);
TableItem item = table.getItem(pt);
if (item == null)
return;
for (int i = 0; i < titles.length; i++) {
Rectangle rect = item.getBounds(i);
if (rect.contains(pt)) {
int index = table.indexOf(item);
System.out.println("Item " + index + "-" + i);
sourcePosition = pt;
sourceRow = index;
currentPath = new PathFigure();
currentPath.setSourceAnchor(new XYAnchor(
new org.eclipse.draw2d.geometry.Point(-10,
event.y)));
currentPath
.setTargetAnchor(new XYAnchor(
new org.eclipse.draw2d.geometry.Point(
0, pt.y)));
bf.add(currentPath);
}
}
}
});
table.addMouseMoveListener(new MouseMoveListener() {
public void mouseMove(MouseEvent arg0) {
if (currentPath != null) {
((XYAnchor) (currentPath.getTargetAnchor()))
.setLocation(new org.eclipse.draw2d.geometry.Point(
0, arg0.y));
}
}
});
canvas = new Canvas(shell, SWT.None);
canvas.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_GREEN));
LightweightSystem lws = new LightweightSystem(canvas);
bf = new BaseFigure();
lws.setContents(bf);
canvas.addMouseMoveListener(new MouseMoveListener() {
public void mouseMove(MouseEvent arg0) {
if (currentPath != null) {
((XYAnchor) (currentPath.getTargetAnchor()))
.setLocation(new org.eclipse.draw2d.geometry.Point(
arg0.x > canvas.getSize().x - 5 ? canvas
.getSize().x - 5 : arg0.x, arg0.y));
}
}
});
GridData data2 = new GridData();
data2.verticalAlignment = SWT.TOP;
data2.grabExcessHorizontalSpace = false;
data2.grabExcessVerticalSpace = true;
data2.horizontalIndent = -10;
data2.widthHint = 200;
data2.heightHint = 1000;
canvas.setLayoutData(data2);
final Table table2 = new Table(shell, SWT.MULTI | SWT.BORDER
| SWT.FULL_SELECTION);
table2.setLinesVisible(true);
table2.setHeaderVisible(true);
data2 = new GridData();
data2.grabExcessHorizontalSpace = false;
data2.horizontalIndent = -10;
table2.setLayoutData(data2);
final String[] titles2 = { "Serial Number", "Whatever" };
for (int i = 0; i < titles.length; i++) {
TableColumn column = new TableColumn(table2, SWT.NONE);
column.setText(titles[i]);
canvas.redraw();
}
table2.addMouseMoveListener(new MouseMoveListener() {
public void mouseMove(MouseEvent event) {
if (currentPath != null) {
Point pt = new Point(event.x, event.y);
TableItem item = table2.getItem(pt);
if (item == null)
return;
for (int i = 0; i < titles2.length; i++) {
Rectangle rect = item.getBounds(i);
if (rect.contains(pt)) {
((XYAnchor) (currentPath.getTargetAnchor()))
.setLocation(new org.eclipse.draw2d.geometry.Point(
canvas.getSize().x - 5, event.y));
}
}
}
}
});
int count2 = 100;// create 100 rows in table 2
for (int i = 0; i < count2; i++) {
TableItem item = new TableItem(table2, SWT.NONE);
item.setText(0, "x");
item.setText(1, "y");
item.setText(2, "!");
item.setText(3, "this stuff behaves the way I expect");
item.setText(4, "almost everywhere");
item.setText(5, "some.folder");
item.setText(6, "line " + i + " in nowhere");
}
for (int i = 0; i < titles.length; i++) {
table2.getColumn(i).pack();
}
table2.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
try {
Point pt = new Point(event.x, event.y);
TableItem item = table2.getItem(pt);
if (item == null)
return;
for (int i = 0; i < titles2.length; i++) {
Rectangle rect = item.getBounds(i);
if (rect.contains(pt)) {
int index = table2.indexOf(item);
targetRow = index;
System.out.println("Item " + index + "-" + i);
if (sourcePosition != null) {
add(event);
}
}
}
} finally {
sourcePosition = null;
sourceRow = -1;
targetRow = -1;
}
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}
public static void add(Event event) {
bf.remove(currentPath);
PathFigure figure = new PathFigure();
figure.setSourceAnchor(currentPath.getSourceAnchor());
figure.setTargetAnchor(currentPath.getTargetAnchor());
bf.add(figure);
currentPath = null;
RowMapper mapper = new RowMapper();
mapper.sourceRow = sourceRow;
mapper.targetRow = targetRow;
if (!rowmapList.contains(mapper)) {
rowmapList.add(mapper);
}
}
class BaseFigure extends FreeformLayeredPane {
public BaseFigure() {
setLayoutManager(new FreeformLayout());
setBorder(new MarginBorder(5));
setBackgroundColor(ColorConstants.white);
setOpaque(true);
}
}
class PathFigure extends PolylineConnection {
public PathFigure() {
setTargetDecoration(new PolylineDecoration());
setConnectionRouter(new AutomaticRouter() {
@Override
protected void handleCollision(PointList list, int index) {
}
});
}
}
class RowMapper {
int sourceRow;
int targetRow;
@Override
public boolean equals(Object obj) {
if (obj instanceof RowMapper) {
RowMapper mapper = (RowMapper) obj;
return (sourceRow == mapper.sourceRow && targetRow == mapper.targetRow);
}
return false;
}
}
回答2:
This is quite a difficult component to implement, I did one of these for Tibco Business Studio some time ago.
You'll need to place a Canvas between your two tables to draw the links on. You presumably have data models for your two tables, you'll also need a third model for storing the links and ensure that any modifications to this model trigger a refresh of the Canvas.
Next add drag and drop support to the two tables, dropping an item from table 1 onto table 2 should create a new item in your link model (thus triggering a Canvas refresh to draw the link).
Actually drawing the links in the right locations you'll have to work out yourself, but hopefully this gives you some ideas to start with.
回答3:
Am I right in thinking that this implementation uses the mouse location to draw the arrows? So if you wanted to save / load a relationship you would have to save the x,y positions of the arrows and you'd have to make sure your components always stayed the same size?
来源:https://stackoverflow.com/questions/12560452/eclipse-rcp-combining-table-rows-by-drag-and-drop-the-arrows