I'm trying to create a connection between two ellipses on a canvas, AFTER having created the ellipses and storing their positions on the canvas. These stored positions need to be used to create the connection. The code I've written works for RectangleFigures but does not for Ellipses. I can't seem to see the difference between the two cases. Could someone please help? Thanks.*I've added short testable code to illustrate my problem. To see it working with Rectangles, please uncomment the line saying UNCOMMENT THIS
import java.util.ArrayList;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.Ellipse;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Label;
public class EllipseProblem
{
private Shell shell;
private Display display;
private final Label lblUnicorn;
private final Canvas canvas;
final IFigure panel;
public static ArrayList canvasElements= new ArrayList();
public static void main(String args[])
{
new EllipseProblem();
}
public EllipseProblem()
{
display = new Display();
shell = new Shell(display);
shell.setText("SWT Application");
shell.setLayout(new GridLayout(2, false));
Group grpPalette = new Group(shell, SWT.NONE);
grpPalette.setText("Palette");
grpPalette.setLayout(new GridLayout());
grpPalette.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, true));
lblUnicorn = new Label(grpPalette, SWT.BORDER | SWT.HORIZONTAL | SWT.CENTER);
lblUnicorn.setText("UNICORN");
lblUnicorn.setAlignment(SWT.CENTER);
final Group grpCanvas = new Group(shell, SWT.NONE);
grpCanvas.setText("Canvas");
grpCanvas.setLayout(new GridLayout());
grpCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
canvas = new Canvas(grpCanvas, SWT.NONE);
canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Button btnCreate = new Button(grpPalette, SWT.CENTER);
GridData gd_btnCreate = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
gd_btnCreate.widthHint = 87;
gd_btnCreate.heightHint = 33;
btnCreate.setLayoutData(gd_btnCreate);
btnCreate.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
drawConnection();
}
});
btnCreate.setText("Make Connection");
LightweightSystem lws = new LightweightSystem(canvas);
panel = new Figure();
lws.setContents(panel);
DragSource dragSource1 = new DragSource(lblUnicorn, DND.DROP_COPY);
Transfer[] transfers1 = new Transfer[] { TextTransfer.getInstance() };
dragSource1.setTransfer(transfers1);
dragSource1.addDragListener(new DragSourceListener()
{
public void dragStart(DragSourceEvent event)
{
if (lblUnicorn.getText().length() == 0)
{
event.doit = false;
}
}
public void dragSetData(DragSourceEvent event)
{
if (TextTransfer.getInstance().isSupportedType(event.dataType))
{
event.data = lblUnicorn.getText();
}
}
public void dragFinished(DragSourceEvent event)
{
}
});
Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
DropTarget dropTarget = new DropTarget(canvas, DND.DROP_COPY | DND.DROP_DEFAULT);
dropTarget.setTransfer(types);
dropTarget.addDropListener(new DropTargetListener()
{
public void dragEnter(DropTargetEvent event)
{
if (event.detail == DND.DROP_DEFAULT)
{
if ((event.operations & DND.DROP_COPY) != 0)
{
event.detail = DND.DROP_COPY;
}
else
{
event.detail = DND.DROP_NONE;
}
}
}
public void dragLeave(DropTargetEvent event)
{
}
public void dragOperationChanged(DropTargetEvent event)
{
}
public void dragOver(DropTargetEvent event)
{
}
public void drop(DropTargetEvent event)
{
}
public void dropAccept(final DropTargetEvent event)
{
if (TextTransfer.getInstance().isSupportedType(event.currentDataType))
{
String d = (String) TextTransfer.getInstance().nativeToJava(event.currentDataType);
final String finald= d;
org.eclipse.swt.graphics.Point droppoint = canvas.toControl(event.x, event.y);
canvasElements.add(droppoint);
Rectangle rect=new Rectangle(droppoint.x, droppoint.y, 40, 20);
Rectangle rect2=new Rectangle(droppoint.x+20, droppoint.y, 100, 25);
Ellipse node= new Ellipse();
//RectangleFigure node= new RectangleFigure(); UNCOMMENT THIS
node.setBounds(rect);
System.out.println(node.getBounds());
node.setLocation(new Point(droppoint.x, droppoint.y));
node.setBackgroundColor(ColorConstants.red);
panel.add(node);
org.eclipse.draw2d.Label droppedName=
new org.eclipse.draw2d.Label(finald);
droppedName.setLocation(new Point(droppoint.x, droppoint.y)); //draw2d. point
droppedName.setBounds(rect2);
panel.add(node);
panel.add(droppedName);
canvas.redraw();
}
}
});
shell.pack();
shell.setSize(400, 300);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
}
protected void drawConnection()
{
org.eclipse.swt.graphics.Point swt_origin= (org.eclipse.swt.graphics.Point) canvasElements.get(0);
org.eclipse.draw2d.geometry.Point origin_point= new org.eclipse.draw2d.geometry.Point(swt_origin.x, swt_origin.y);
org.eclipse.swt.graphics.Point swt_destination= (org.eclipse.swt.graphics.Point) canvasElements.get(1);
org.eclipse.draw2d.geometry.Point destination_point= new org.eclipse.draw2d.geometry.Point(swt_destination.x, swt_destination.y);
IFigure origin = panel.findFigureAt(origin_point);
IFigure destination = panel.findFigureAt(destination_point);
PolylineConnection conn = new PolylineConnection();
conn.setSourceAnchor(new ChopboxAnchor(origin));
conn.setTargetAnchor(new ChopboxAnchor(destination));
conn.setTargetDecoration(new PolygonDecoration());
panel.add(conn);
}
}
Your problem is caused by the fact, that your method to determine the source and target IFigures is flawed.
You store the top left corner for the lookup. That works just fine for the RectangleFigure, since that rectangle actually contains the top left corner. The Ellipse, however, doesn't (which is why the source and target of the PolylineConnection is their parent).
Best illustrated with an image:
If you instead store the center of the figure you'll end up with this:
Related
I have two elements in a horizontal RowLayout.
I am able to specify a (minimal) with for the second element (e.g. 200 px). Furthermore...
a) If the total width of the shell is too small, the second element wraps to a new line. That works fine with the RowLayout.
b) If the total with is "large", the second (=last) element should grab the excess horizontal space.
Is b) possible with the RowLayout? Or do I need to use a GridLayout and implement the wrapping on my own (e.g. use one or two columns in the grid layout, depending on the size of the elements)?
public class RowLayoutDemo {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new RowLayout());
Text firstElement = new Text(shell, SWT.NONE);
firstElement.setText("firstElement");
Text secondElement = new Text(shell, SWT.NONE);
secondElement.setText("secondElement");
secondElement.setBackground(new Color(null, 200, 0, 0));
int minWidth = 200;
RowData rowData = new RowData();
rowData.width = minWidth;
secondElement.setLayoutData(rowData);
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
The RowLayout does not support what you are looking for. I recommend using a GridLayout with a resize listener as you suggested or implement your own layout.
I first tried to write a custom layout which turned out to be be hard. The second strategy based on GridLayout was easier. Here is a first draft for a custom Composite that switches the number of columns of its GridLayout to have one or two columns, depending on the size of its children.
(I still have an issues with flickering when resizing my Sections.)
package org.treez.core.adaptable.composite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;
/**
* A row composite for only two children. If the children are too large for a single line, the second child is wrapped
* on a second line. The second child always grabs excess horizontal space. This composite automatically sets the
* LayoutData of its children. Therefore the LayoutData of the children should not be set manually.
*/
public class GrabbingRowComposite extends Composite {
//#region ATTRIBUTES
private int widthHintForFirstChild = 80;
private int minWidthForSecondChild = 200;
private boolean isSingleLine = true;
//#end region
//#region CONSTRUCTORS
public GrabbingRowComposite(Composite parent) {
super(parent);
super.setLayout(createLayout());
if (parent.getLayout() instanceof GridLayout) {
GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
setLayoutData(gridData);
}
}
//#end region
//#region METHODS
private GridLayout createLayout() {
//create default layout for single line
GridLayout gridLayout = new GridLayout(2, false);
//change layout to use several lines if required
this.addControlListener(new ControlAdapter() {
#Override
public void controlResized(ControlEvent e) {
adaptLayout();
}
});
return gridLayout;
}
private void adaptLayout() {
int totalWidth = this.getBounds().width;
Control[] children = getChildren();
if (children.length < 2) {
return;
}
Control firstChild = children[0];
Control secondChild = children[1];
int firstChildWidth = children[0].getBounds().width;
setWidthHintForFirstChild(firstChild);
setGrapHorizontalSpaceForSecondChild(secondChild);
boolean isTooSmallForOneLine = totalWidth < firstChildWidth + minWidthForSecondChild;
if (isTooSmallForOneLine) {
setTwoLineLayout();
} else {
setSingleLineLayout();
}
}
private void setTwoLineLayout() {
if (isSingleLine) {
super.setLayout(new GridLayout(1, false));
updateLayoutOfParentAndGrandParent();
isSingleLine = false;
}
}
private void setSingleLineLayout() {
if (!isSingleLine) {
super.setLayout(new GridLayout(2, false));
updateLayoutOfParentAndGrandParent();
isSingleLine = true;
}
}
private void setWidthHintForFirstChild(Control firstChild) {
GridData firstGridData = new GridData();
firstGridData.widthHint = widthHintForFirstChild;
firstChild.setLayoutData(firstGridData);
}
private static void setGrapHorizontalSpaceForSecondChild(Control secondChild) {
GridData secondGridData = new GridData(SWT.FILL, SWT.FILL, true, false);
secondChild.setLayoutData(secondGridData);
}
private void updateLayoutOfParentAndGrandParent() {
Composite parent = getParent();
if (parent != null) {
parent.layout(true);
Composite grandParent = parent.getParent();
if (grandParent != null) {
grandParent.layout(true);
}
}
}
//#end region
//#region ACCESSORS
#Override
public void setLayout(Layout layout) {
throw new IllegalStateException("The layout of this composite must not be changed");
}
//#end region
}
Example usage
package org.treez.core.adaptable.composite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.Section;
public class GrabbingRowCompositeDemo {
public static void main(String[] args) {
Shell shell = createShell();
shell.setSize(500, 300);
Section section = createSection(shell);
Composite parentComposite = createParentComposite(section);
createRow(parentComposite, "first");
createRow(parentComposite, "second");
createRow(parentComposite, "third");
section.clientVerticalSpacing = 0;
showUntilClosed(shell);
}
private static Shell createShell() {
Display display = new Display();
Shell shell = new Shell(display);
GridLayout shellGridLayout = new GridLayout(1, false);
shell.setLayout(shellGridLayout);
return shell;
}
private static Section createSection(Shell shell) {
Section section = new Section(
shell,
ExpandableComposite.TWISTIE | //
ExpandableComposite.EXPANDED | //
ExpandableComposite.TITLE_BAR | //
ExpandableComposite.CLIENT_INDENT);
GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
section.setLayoutData(gridData);
return section;
}
private static Composite createParentComposite(Section section) {
Composite parentComposite = new Composite(section, SWT.NONE);
section.setClient(parentComposite);
parentComposite.setBackground(new Color(null, 0, 0, 255));
GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
parentComposite.setLayoutData(gridData);
GridLayout gridLayout = new GridLayout(1, false);
parentComposite.setLayout(gridLayout);
return parentComposite;
}
private static Composite createRow(Composite parent, String text) {
GrabbingRowComposite row = new GrabbingRowComposite(parent);
row.setBackground(new Color(null, 255, 255, 255));
Label label = new Label(row, SWT.NONE);
label.setText(text);
Button checkBox = new Button(row, SWT.CHECK);
checkBox.setBackground(new Color(null, 255, 0, 0));
return row;
}
private static void showUntilClosed(Shell shell) {
shell.open();
Display display = Display.getCurrent();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
Why does the MenuItem listener not get executed on a Canvas? Please see test program below. You would expect the "Got Here" to be printed to the console.
import java.util.ArrayList;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.layout.FillLayout;
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.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
public class MenuListenerTest {
//BufferedImage bitmapImage = null;
Image image = null;
Canvas canvas = null;
private void createContents(Shell shell) {
shell.setLayout(new FillLayout());
// Create a canvas to draw on
canvas = new Canvas(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED);
final Menu pixelContextMenu = new Menu(canvas);
canvas.setMenu(pixelContextMenu);
final MenuItem resetImageItem = new MenuItem(pixelContextMenu, SWT.NONE);
resetImageItem.setText("Reset Image");
resetImageItem.addListener(SWT.MenuDetect, new Listener() {
#Override
public void handleEvent(Event event) {
int x = event.x;
int y = event.y;
System.out.println("Got here");
}
});
}
public static void main(String[] args)
{
new MenuListenerTest().run();
}
public void run() {
Display display = new Display();
Shell shell = new Shell(display);
createContents(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
/**
* Creates the main window's contents
*
* #param shell the main window
*/
}
You should use a SelectionListener to intercept when the MenuItem is pressed:
resetImageItem.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent event) {
System.out.println("menu item pressed");
}
});
The event SWT.MenuDetect instead is fired when the menu become visible. To intercept it you would have to attach the listener directly to the Canvas:
canvas.addListener(SWT.MenuDetect, new Listener() {
#Override
public void handleEvent(Event event) {
System.out.println("menu visible");
}
});
I want to have checkboxes in a combo(Drop down) so that I can select more than one elements of combo at once. Can this be done? If yes, can you please explain or provide any link if possible.
Thank you.
Original poster asked for a drop down list with multi-selection support as an alternative. Custom implementation of MultiSelectionCombo can serve this purpose.
Selected items are displayed in text field:
Drop down with multi-selection support http://s12.postimg.org/7ee1y6j5n/Multi_Selection_Combo.png
Keep Ctrl pressed to select multiple items:
Select multiple items in drop down http://s3.postimg.org/ufkezh99t/Items_selected.png
Get indices of selected items:
Get selected items http://s11.postimg.org/8n9fa7fb5/Get_selected_items.png
Implementation and demo of MultiSelectionCombo:
import java.util.Arrays;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
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.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class MultiSelectionCombo extends Composite {
Shell shell = null;
List list = null;
Text txtCurrentSelection = null;
String[] textItems = null;
int[] currentSelection = null;
public MultiSelectionCombo(Composite parent, String[] items, int[] selection, int style) {
super(parent, style);
currentSelection = selection;
textItems = items;
init();
}
private void init() {
GridLayout layout = new GridLayout();
layout.marginBottom = 0;
layout.marginTop = 0;
layout.marginLeft = 0;
layout.marginRight = 0;
layout.marginWidth = 0;
layout.marginHeight = 0;
setLayout(new GridLayout());
txtCurrentSelection = new Text(this, SWT.BORDER | SWT.READ_ONLY);
txtCurrentSelection.setLayoutData(new GridData(GridData.FILL_BOTH));
displayText();
txtCurrentSelection.addMouseListener(new MouseAdapter() {
#Override
public void mouseDown(MouseEvent event) {
super.mouseDown(event);
initFloatShell();
}
});
}
private void initFloatShell() {
Point p = txtCurrentSelection.getParent().toDisplay(txtCurrentSelection.getLocation());
Point size = txtCurrentSelection.getSize();
Rectangle shellRect = new Rectangle(p.x, p.y + size.y, size.x, 0);
shell = new Shell(MultiSelectionCombo.this.getShell(), SWT.NO_TRIM);
GridLayout gl = new GridLayout();
gl.marginBottom = 2;
gl.marginTop = 2;
gl.marginRight = 2;
gl.marginLeft = 2;
gl.marginWidth = 0;
gl.marginHeight = 0;
shell.setLayout(gl);
list = new List(shell, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
for (String value: textItems) {
list.add(value);
}
list.setSelection(currentSelection);
GridData gd = new GridData(GridData.FILL_BOTH);
list.setLayoutData(gd);
shell.setSize(shellRect.width, 100);
shell.setLocation(shellRect.x, shellRect.y);
list.addMouseListener(new MouseAdapter() {
#Override
public void mouseUp(MouseEvent event) {
super.mouseUp(event);
currentSelection = list.getSelectionIndices();
if ((event.stateMask & SWT.CTRL) == 0) {
shell.dispose();
displayText();
}
}
});
shell.addShellListener(new ShellAdapter() {
public void shellDeactivated(ShellEvent arg0) {
if (shell != null && !shell.isDisposed()) {
currentSelection = list.getSelectionIndices();
displayText();
shell.dispose();
}
}
});
shell.open();
}
private void displayText() {
if (currentSelection != null && currentSelection.length > 0) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < currentSelection.length; i++) {
if (i > 0)
sb.append(", ");
sb.append(textItems[currentSelection[i]]);
}
txtCurrentSelection.setText(sb.toString());
}
else {
txtCurrentSelection.setText("");
}
}
public int[] getSelections() {
return this.currentSelection;
}
// Main method to showcase MultiSelectionCombo
// (can be removed from productive code)
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setText("MultiSelectionCombo Demo");
// Items and pre-selected items in combo box
String[] items = new String[] { "Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa" };
int[] selection = new int[] { 0, 2 };
// Create MultiSelectCombo box
final MultiSelectionCombo combo = new MultiSelectionCombo(shell, items, selection, SWT.NONE);
combo.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
((GridData)combo.getLayoutData()).widthHint = 300;
// Add button to print current selection on console
Button button = new Button(shell, SWT.NONE);
button.setText("What is selected?");
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
System.out.println("Selected items: " + Arrays.toString(combo.getSelections()));
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
screenshot
https://github.com/lawhcd/SWTMultiCheckSelectionCombo
For anyone who is looking for a widget that allows user to select multiple options from a list of check box style options.
It is based on user1438038's idea and extended to provide nearly all of the api required of a widget similar to Combo.
This isn't possible with the SWT Combo (or CCombo).
The Eclipse Nebula project TableCombo supports a Table shown as a Combo, so you may be able to use an SWT.CHECK style table with this.
There is no such control in SWT on default. However, you can extend either Combo or CCombo to implement checkboxes yourself.
A Table with SWT.CHECK style might be a better option, though:
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
public class TableCheckBoxCell {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
Table table = new Table(shell, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
for (int i = 0; i < 12; i++) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText("Item " + i);
}
table.setSize(100, 100);
shell.setSize(200, 200);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Source: Table With CheckBox Cell
I've written code that allows drag and drop onto a canvas. On 'dropping', a RectangleFigure is drawn on the canvas at that point. The problem is that when I drop onto the canvas for the second time, another copy of the first dropped element is made on the screen. Similarly, the third time, the first two elements are recreated.(We know this, to be true because if you drag one of the elements from it's original position, you can see the recreated elements underneath it) Can someone please tell me how to prevent this recreation from taking place? *I have added short testable code illustrating the problem
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseListener;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.wb.swt.SWTResourceManager;
import org.eclipse.swt.widgets.Label;
/**
*
*Shortest complete testable code demonstrating the repeated creation problem
*/
public class RepeatDrop
{
/**
* Launch the application.
*
* #param args
*/
private Shell shell;
private Display display;
private Menu menu;
private Group grpPalette;
private final Label lblUnicorn;
private Group grpCanvas;
private final Canvas canvas;
public static void main(String args[]) {
new RepeatDrop();
}
/**
* Create the shell.
*
* #param display
*/
public RepeatDrop() {
display = new Display();
shell = new Shell(display);
shell.setText("SWT Application");
shell.setSize(450, 393);
Group grpPalette = new Group(shell, SWT.NONE);
grpPalette.setText("Palette");
grpPalette.setBounds(0, 0, 88, 325);
lblUnicorn = new Label(grpPalette, SWT.BORDER | SWT.HORIZONTAL
| SWT.CENTER);
lblUnicorn.setText("UNICORN");
// ADDED A FINAL HERE!!
lblUnicorn.setAlignment(SWT.CENTER);
lblUnicorn.setBounds(10, 24, 68, 53);
final Group grpCanvas = new Group(shell, SWT.NONE);
grpCanvas.setText("Canvas");
grpCanvas.setBounds(94, 0, 330, 325);
canvas = new Canvas(grpCanvas, SWT.NONE);
canvas.setBackground(SWTResourceManager.getColor(253, 245, 230));
canvas.setBounds(10, 20, 320, 295);
LightweightSystem lws = new LightweightSystem(canvas); //
final IFigure panel = new Figure(); //
lws.setContents(panel); //
DragSource dragSource1 = new DragSource(lblUnicorn, DND.DROP_COPY);
Transfer[] transfers1 = new Transfer[] { TextTransfer.getInstance() };
dragSource1.setTransfer(transfers1);
dragSource1.addDragListener(new DragSourceListener() {
public void dragStart(DragSourceEvent event) {
if (lblUnicorn.getText().length() == 0) {
event.doit = false;
}
}
public void dragSetData(DragSourceEvent event) {
if (TextTransfer.getInstance().isSupportedType (event.dataType)) {
event.data = lblUnicorn.getText();
}
}
public void dragFinished(DragSourceEvent event) {
}
});
Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
DropTarget dropTarget = new DropTarget(canvas, DND.DROP_COPY
| DND.DROP_DEFAULT);
dropTarget.setTransfer(types);
dropTarget.addDropListener(new DropTargetListener() {
public void dragEnter(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
} else {
event.detail = DND.DROP_NONE;
}
}
}
public void dragLeave(DropTargetEvent event) {
}
public void dragOperationChanged(DropTargetEvent event) {
}
public void dragOver(DropTargetEvent event) {
}
public void drop(DropTargetEvent event) {
}
public void dropAccept(final DropTargetEvent event)
{
if (TextTransfer.getInstance().isSupportedType(
event.currentDataType)) {
String d = (String) TextTransfer.getInstance()
.nativeToJava(event.currentDataType);
final String finald= d;
GC gc = new GC(canvas);
canvas.redraw();
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
org.eclipse.swt.graphics.Point droppoint = canvas.toControl(event.x, event.y);
//DRAW 2D SECTION
RectangleFigure node1 = new RectangleFigure();
Rectangle rect=new Rectangle(droppoint.x, droppoint.y, 20, 20);
Rectangle rect2=new Rectangle(droppoint.x, droppoint.y, 100, 25);
node1.setBounds(rect);
node1.setBackgroundColor(ColorConstants.cyan);
org.eclipse.draw2d.Label droppedName=
new org.eclipse.draw2d.Label(finald);
droppedName.setLocation(new Point(droppoint.x, droppoint.y)); //draw2d. point
droppedName.setBounds(rect2);
node1.add(droppedName);
panel.add(node1);
panel.add(droppedName);
Dragger fig = new Dragger(node1);
Dragger caption = new Dragger(droppedName);
//DRAW 2D SECTION
}
});
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
static class Dragger extends MouseMotionListener.Stub implements MouseListener
{
public Dragger(IFigure figure){
figure.addMouseMotionListener(this);
figure.addMouseListener(this);
}
Point last;
public void mouseReleased(MouseEvent e){
}
public void mouseClicked(MouseEvent e){
}
public void mouseDoubleClicked(MouseEvent e){
}
public void mousePressed(MouseEvent e){
last = e.getLocation();
}
public void mouseDragged(MouseEvent e){
Point p = e.getLocation();
Dimension delta = p.getDifference(last);
{
last = p;
Figure f = ((Figure)e.getSource());
f.setBounds(f.getBounds().getTranslated(delta.width, delta.height));
}
}
}
}
Your issue is caused by the fact that you add a new PaintListener each time you add a new figure. That isn't necessary. In fact, you don't need to add any PaintListener at all. The LightweightSystem will take care of that for you.
Here is your code now working fine:
public class RepeatDrop
{
private Shell shell;
private Display display;
private final Label lblUnicorn;
private final Canvas canvas;
public static void main(String args[])
{
new RepeatDrop();
}
public RepeatDrop()
{
display = new Display();
shell = new Shell(display);
shell.setText("SWT Application");
shell.setLayout(new GridLayout(2, false));
Group grpPalette = new Group(shell, SWT.NONE);
grpPalette.setText("Palette");
grpPalette.setLayout(new GridLayout());
grpPalette.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, true));
lblUnicorn = new Label(grpPalette, SWT.BORDER | SWT.HORIZONTAL | SWT.CENTER);
lblUnicorn.setText("UNICORN");
// ADDED A FINAL HERE!!
lblUnicorn.setAlignment(SWT.CENTER);
final Group grpCanvas = new Group(shell, SWT.NONE);
grpCanvas.setText("Canvas");
grpCanvas.setLayout(new GridLayout());
grpCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
canvas = new Canvas(grpCanvas, SWT.NONE);
canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
LightweightSystem lws = new LightweightSystem(canvas); //
final IFigure panel = new Figure(); //
lws.setContents(panel); //
DragSource dragSource1 = new DragSource(lblUnicorn, DND.DROP_COPY);
Transfer[] transfers1 = new Transfer[] { TextTransfer.getInstance() };
dragSource1.setTransfer(transfers1);
dragSource1.addDragListener(new DragSourceListener()
{
public void dragStart(DragSourceEvent event)
{
if (lblUnicorn.getText().length() == 0)
{
event.doit = false;
}
}
public void dragSetData(DragSourceEvent event)
{
if (TextTransfer.getInstance().isSupportedType(event.dataType))
{
event.data = lblUnicorn.getText();
}
}
public void dragFinished(DragSourceEvent event)
{
}
});
Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
DropTarget dropTarget = new DropTarget(canvas, DND.DROP_COPY | DND.DROP_DEFAULT);
dropTarget.setTransfer(types);
dropTarget.addDropListener(new DropTargetListener()
{
public void dragEnter(DropTargetEvent event)
{
if (event.detail == DND.DROP_DEFAULT)
{
if ((event.operations & DND.DROP_COPY) != 0)
{
event.detail = DND.DROP_COPY;
}
else
{
event.detail = DND.DROP_NONE;
}
}
}
public void dragLeave(DropTargetEvent event)
{
}
public void dragOperationChanged(DropTargetEvent event)
{
}
public void dragOver(DropTargetEvent event)
{
}
public void drop(DropTargetEvent event)
{
}
public void dropAccept(final DropTargetEvent event)
{
if (TextTransfer.getInstance().isSupportedType(event.currentDataType))
{
String d = (String) TextTransfer.getInstance().nativeToJava(event.currentDataType);
org.eclipse.swt.graphics.Point droppoint = canvas.toControl(event.x, event.y);
// DRAW 2D SECTION
RectangleFigure node1 = new RectangleFigure();
Rectangle rect = new Rectangle(droppoint.x, droppoint.y, 20, 20);
Rectangle rect2 = new Rectangle(droppoint.x, droppoint.y, 100, 25);
node1.setBounds(rect);
node1.setBackgroundColor(ColorConstants.cyan);
org.eclipse.draw2d.Label droppedName = new org.eclipse.draw2d.Label(d);
droppedName.setLocation(new Point(droppoint.x, droppoint.y)); // draw2d.
// point
droppedName.setBounds(rect2);
node1.add(droppedName);
panel.add(node1);
panel.add(droppedName);
new Dragger(node1);
new Dragger(droppedName);
canvas.redraw();
}
}
});
shell.pack();
shell.setSize(400, 300);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
}
static class Dragger extends MouseMotionListener.Stub implements MouseListener
{
public Dragger(IFigure figure)
{
figure.addMouseMotionListener(this);
figure.addMouseListener(this);
}
Point last;
public void mouseReleased(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseDoubleClicked(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
last = e.getLocation();
}
public void mouseDragged(MouseEvent e)
{
Point p = e.getLocation();
Dimension delta = p.getDifference(last);
{
last = p;
Figure f = ((Figure) e.getSource());
f.setBounds(f.getBounds().getTranslated(delta.width, delta.height));
}
}
}
}
Please have a look at the way I used Layouts. It's far more reliable and will work better on different window sizes and screen resolutions.
Please also read this: Understanding Layouts in SWT
I am trying to create a browse button with FileDialog and composite in Java SWT. (Composite because, I am use CTabFolder and CTabItem. I felt to add components to CTabItem composite is good enough)
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.StringTokenizer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.custom.CBanner;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.wb.swt.SWTResourceManager;
public class DemoShell extends Shell {
protected Composite composite;
private Text filename;
private Table table;
protected Shell shell;
public static void main(String args[]) {
try {
Display display = Display.getDefault();
DemoShell shell = new DemoShell(display);
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean parseFile(Table table, String filename) {
try {
BufferedReader br = new BufferedReader( new FileReader(filename) );
String line = "";
StringTokenizer token = null, subtoken = null;
int tokenNum = 1;
while((line = br.readLine()) != null) {
// lineNum++;
// break comma separated file line by line
token = new StringTokenizer(line, ";");
String sno = null;
while(token.hasMoreTokens()) {
subtoken = new StringTokenizer(token.nextToken().toString(), ",");
sno = "";
sno = Integer.toString(tokenNum);
TableItem item = new TableItem (table, SWT.NONE);
item.setText (0, sno );
item.setText (1, subtoken.nextToken());
item.setText (2, subtoken.nextToken());
item.setText (3, subtoken.nextToken());
item.setText (4, subtoken.nextToken());
item.setText (5, subtoken.nextToken());
tokenNum++;
System.out.println("S.No # " + tokenNum + token.nextToken());
}
tokenNum = 0;
}
br.close();
return true;
} catch(Exception e) {
System.err.println("Parse Error: " + e.getMessage());
return false;
}
}
public void displayFiles(String[] files) {
for (int i = 0; files != null && i < files.length; i++) {
filename.setText(files[i]);
filename.setEditable(false);
}
}
/**
* Create the shell.
* #param display
*/
public DemoShell(Display display) {
super(display, SWT.SHELL_TRIM);
TabFolder tabFolder = new TabFolder(this, SWT.NONE);
tabFolder.setBounds(10, 10, 462, 268);
TabItem re_item = new TabItem(tabFolder, SWT.NONE);
re_item.setText("Road Network");
TabItem ttable_item = new TabItem(tabFolder, SWT.NONE);
ttable_item.setText("Time Table");
createContents_tt(tabFolder, ttable_item );
}
/**
* Create contents of the shell.
*/
protected void createContents_tt(TabFolder tabFolder, TabItem ttable_item) {
setText("SWT Application");
setSize(530, 326);
//Table declaration
table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
table.setBounds(10, 153, 450, 107);
table.setHeaderVisible(true);
table.setLinesVisible(true);
String[] titles = {"S.No", "Route", "Transport #", "Cross Point", "Start Time", "End Time"};
for (int i=0; i<titles.length; i++) {
TableColumn column = new TableColumn (table, SWT.NONE);
column.setText (titles [i]);
}
for (int i=0; i<titles.length; i++) {
table.getColumn (i).pack ();
}
Composite composite = new Composite(tabFolder, SWT.NONE);
composite.setLayout(new FillLayout());
Group group_1 = new Group(shell, SWT.NONE);
group_1.setBounds(10, 10, 450, 127);
filename = new Text(group_1, SWT.BORDER);
filename.setBounds(31, 95, 377, 21);
filename.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
Group group = new Group(group_1, SWT.NONE);
group.setBounds(81, 46, 245, 43);
Label lblEitherBrowseFor = new Label(group_1, SWT.NONE);
lblEitherBrowseFor.setBounds(10, 19, 430, 21);
lblEitherBrowseFor.setText("Either Browse for a file or Try to upload the time table data through Manual entry");
Button btnManual = new Button(group, SWT.NONE);
btnManual.setBounds(162, 10, 75, 25);
btnManual.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
}
});
btnManual.setText("Manual");
Button btnBrowser = new Button(group, SWT.NONE);
btnBrowser.setBounds(27, 10, 75, 25);
btnBrowser.setText("Browse");
btnBrowser.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
FileDialog dialog = new FileDialog(composite, SWT.NULL);
String path = dialog.open();
if (path != null) {
File file = new File(path);
if (file.isFile())
{
displayFiles(new String[] { file.getAbsolutePath().toString()});
DemoShell.parseFile(table, file.toString());
}
else
displayFiles(file.list());
}
}
});
ttable_item.setControl(composite);
}
#Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
}
I am getting the following error when trying to add in the above manner.
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The constructor FileDialog(Composite, int) is undefined
Cannot refer to a non-final variable composite inside an inner class defined in a different method
I request for suggestions/help to clear the bug or re-do with any other way.
You are trying to access composite from within the Listener you define (SelectionAdapter). The notation you use to create the listener implicitly creates a new class. So you are effectively trying to access the variable composite from an inner class, which can only be done if composite is a static field of your outer class or if you make the composite final.
So just do the following:
final Composite composite = new Composite(tabFolder, SWT.NONE);
and it will work.
Moreover, as the error states, there is no constructor that takes a Composite. You have to use a Shell. So just do the following:
FileDialog dialog = new FileDialog(composite.getShell(), SWT.NULL);
This however will give you another exception, since you use the field shell somewhere above that line which is null. Since your class is a Shell, replace all occurences of shell with this and it will work.