/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.gui.xpathchooser;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
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.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.xml.sax.SAXException;
import de.rcenvironment.core.gui.resources.api.ImageManager;
import de.rcenvironment.core.gui.resources.api.StandardImages;
import de.rcenvironment.core.gui.xpathchooser.model.XSDElement;
import de.rcenvironment.core.gui.xpathchooser.model.XSDGenerator;
import de.rcenvironment.core.utils.common.variables.legacy.VariableType;
/**
* The GUI creating class used in dialogs and views.
*
* @author Arne Bachmann
* @author Markus Kunde
*/
public class XPathChooserHelper {
/**
* For sash creation.
*/
static final int PERCENT_100 = 100;
/**
* For sash creation.
*/
private static final int PERCENT_SEP = 70;
/**
* Constant for row detection.
*/
private static final int NOT_FOUND = -1;
/**
* Number of columns in the cpacs tree table.
*/
private static final int TREE_COLUMNS = 3;
/**
* Number of columns in the variables table.
*/
private static final int TABLE_COLUMNS = 1;
/**
* The tree table containing the cpacs.
*/
private Tree tree;
/**
* The JFace mechanism to provide custom contents.
*/
private TreeViewer treeViewer;
/**
* The table containing defined variables.
*/
private Table table;
/**
* The table viewer.
*/
private TableViewer tableViewer;
/**
* The loaded and parsed CPACS.
*/
private XSDElement doc;
/**
* The "input" model for the table viewer.
*/
private List<VariableEntry> tableModel;
/**
* The "last line" entry.
*/
private VariableEntry newEntry;
/**
* Remove a line or chart.
*/
private Image imageRemove;
/**
* The allowed number of selections in the list.
*/
private int maxEntries = 1;
/**
* Create the view.
*
* @param root The XML document root
*/
public XPathChooserHelper(final XSDElement root) {
doc = root;
}
/**
* Create the view's contents.
*
* @param parent The parent component (e.g. shell, dialog)
* @return The created contents
*/
public Composite createContents(final Composite parent) {
imageRemove = ImageManager.getInstance().getSharedImage(StandardImages.DELETE_16);
parent.setLayout(new FormLayout());
final Group firstGroup = new Group(parent, SWT.None);
firstGroup.setText("CPACS");
firstGroup.setLayout(new FillLayout());
createTree(firstGroup);
final Sash sash = new Sash(parent, SWT.HORIZONTAL);
final Group secondGroup = new Group(parent, SWT.None);
secondGroup.setText("Variables");
secondGroup.setLayout(new FillLayout());
createTable(secondGroup);
// set layout data to allow sash
final FormData firstData = new FormData();
firstData.top = new FormAttachment(/* numerator */0, /* offset */0);
firstData.bottom = new FormAttachment(sash, 0);
firstData.left = new FormAttachment(0, 0);
firstData.right = new FormAttachment(PERCENT_100, 0);
firstGroup.setLayoutData(firstData);
final FormData sashData = new FormData();
sashData.top = new FormAttachment(PERCENT_SEP, 0);
sashData.left = new FormAttachment(0, 0);
sashData.right = new FormAttachment(PERCENT_100, 0);
sash.setLayoutData(sashData);
final FormData secondData = new FormData();
secondData.top = new FormAttachment(sash, 0);
secondData.bottom = new FormAttachment(PERCENT_100, 0);
secondData.left = new FormAttachment(0, 0);
secondData.right = new FormAttachment(PERCENT_100, 0);
secondGroup.setLayoutData(secondData);
// make sash movable
sash.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
((FormData) sash.getLayoutData()).top = new FormAttachment(0, event.y);
sash.getParent().layout();
}
});
return secondGroup; // to allow further attachments
}
/**
* Create the left/top part of the dialog, the tree table containing the CPACS.
*
* @param parent The parent component to add the child to.
*/
private void createTree(final Composite parent) {
tree = new Tree(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION);
tree.setHeaderVisible(true);
tree.setLinesVisible(true);
tree.setDragDetect(true);
treeViewer = new TreeViewer(tree);
final String[] columnNames = new String[] { "Element", "UID Name", "Values" };
final int[] columnWidths = new int[] { 300, 100, 100 };
for (int c = 0; c < TREE_COLUMNS; c++) {
final TreeViewerColumn tvc = new TreeViewerColumn(treeViewer, SWT.None);
tvc.getColumn().setText(columnNames[c]);
tvc.getColumn().setWidth(columnWidths[c]);
tvc.getColumn().setResizable(true);
tvc.getColumn().setMoveable(true);
if (c >= 1) { // ignore column "tree"
tvc.setEditingSupport(new XSDEditingSupport(this, treeViewer, c));
}
}
treeViewer.setContentProvider(new XSDContentProvider());
treeViewer.setLabelProvider(new XSDLabelProvider(parent.getDisplay()));
fillTree();
// set up drag facilities
final DragSource dragSource = new DragSource(tree, DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { TextTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
/**
* Detect if drag allowed from the location.
*
* @see org.eclipse.swt.dnd.DragSourceListener#dragStart(org.eclipse.swt.dnd.DragSourceEvent)
*/
@Override
public void dragStart(final DragSourceEvent event) {
if (tree.getSelectionCount() == 0) {
event.doit = false;
return;
}
final TreeItem item = tree.getSelection()[0]; // single selection
if (item == null) {
event.doit = false;
return;
}
final Point clickLocation = new Point(event.x, event.y);
final int column = getTreeColumnFromClickLocation(item, clickLocation);
if (column > 0) {
event.doit = false;
return;
}
}
/**
* Set the transferable data.
*
* @see org.eclipse.swt.dnd.DragSourceListener#dragSetData(org.eclipse.swt.dnd.DragSourceEvent)
*/
@Override
public void dragSetData(final DragSourceEvent event) {
if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
if (tree.getSelectionCount() == 0) {
return;
}
final TreeItem item = tree.getSelection()[0]; // single selection
if (item == null) {
return;
}
final VariableEntry var = getVariableFromViewItem(item);
event.data = var.toString();
}
}
/**
* Clean up, e.g. after a MOVE.
*
* @see org.eclipse.swt.dnd.DragSourceListener#dragFinished(org.eclipse.swt.dnd.DragSourceEvent)
*/
@Override
public void dragFinished(final DragSourceEvent event) {}
});
}
/**
* Create the right/bottom part of the dialog, the table containing the created variables.
*
* @param parent The parent component to add the child to.
*/
private void createTable(final Composite parent) {
table = new Table(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION);
table.setHeaderVisible(true);
table.setLinesVisible(true);
tableViewer = new TableViewer(table);
final String[] columnNames = new String[] { "XPath" };
final int[] columnWidths = new int[] { 600 };
for (int c = 0; c < TABLE_COLUMNS; c++) {
final TableViewerColumn tvc = new TableViewerColumn(tableViewer, SWT.None);
tvc.getColumn().setText(columnNames[c]);
tvc.getColumn().setWidth(columnWidths[c]);
tvc.getColumn().setMoveable(true);
if (c >= 1) { // ignore column "direction"
tvc.setEditingSupport(new VariableEditingSupport(this, tableViewer, c));
}
}
tableViewer.setContentProvider(new VariableContentProvider());
final VariableLabelProvider labelProvider = new VariableLabelProvider();
tableViewer.setLabelProvider(labelProvider);
newEntry = fillTable();
addTableListeners(labelProvider);
// set up drop facilities
final DropTarget dropTarget = new DropTarget(table, DND.DROP_COPY | DND.DROP_DEFAULT);
dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance() });
dropTarget.addDropListener(new DropTargetListener() {
@Override
public void drop(final DropTargetEvent event) {
if (TextTransfer.getInstance().isSupportedType(event.currentDataType)) {
final String text = (String) event.data;
final VariableEntry var = new VariableEntry(text);
if ((maxEntries == 1) || (tableModel.size() <= maxEntries)) { // if only 1 entry
// allowed, then
// replace it
if ((maxEntries == 1) && (tableModel.size() > 1)) {
tableModel.remove(tableModel.size() - 2);
}
tableModel.add(tableModel.size() - 1, var);
tableViewer.refresh();
}
}
}
@Override
public void dragEnter(final 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;
}
} else {
event.detail = DND.DROP_NONE;
}
}
@Override
public void dragOperationChanged(final DropTargetEvent event) {
dragEnter(event); // it's exactly the same
}
@Override
public void dragOver(final DropTargetEvent event) {
event.feedback = DND.FEEDBACK_INSERT_BEFORE | DND.FEEDBACK_SCROLL;
}
@Override
public void dropAccept(final DropTargetEvent event) {}
@Override
public void dragLeave(DropTargetEvent droptargetevent) {}
});
// add popup-context menu
table.addListener(SWT.MenuDetect, new Listener() {
@Override
public void handleEvent(final Event event) {
final int rowIndex = table.getSelectionIndex();
final Point clickLocation = new Point(event.x, event.y);
if ((rowIndex < 0) || ((rowIndex + 1) >= tableModel.size())) {
return;
}
final Menu popup = new Menu(parent.getShell(), SWT.POP_UP);
final MenuItem removeItem = new MenuItem(popup, SWT.PUSH);
removeItem.setText("Remove definition");
removeItem.setImage(imageRemove);
removeItem.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(final Event event) {
tableModel.remove(rowIndex);
tableViewer.refresh();
}
});
popup.setLocation(clickLocation);
popup.setVisible(true);
while (!popup.isDisposed() && popup.isVisible()) {
if (!popup.getDisplay().readAndDispatch()) {
popup.getDisplay().sleep();
}
}
popup.dispose();
}
});
}
/**
* Fill the tree with the documents' contents.
*/
private void fillTree() {
treeViewer.setInput(doc);
treeViewer.expandAll();
for (int c = 0; c < TREE_COLUMNS; c++) {
tree.getColumn(c).pack();
}
}
/**
* Fill the table with some stuff.
*
* @return The last (empty) entry
*/
private VariableEntry fillTable() {
final List<VariableEntry> entries = new ArrayList<VariableEntry>();
final VariableEntry emptyNewEntry = new VariableEntry(EVariableDirection.Incoming, "", "", VariableType.String);
entries.add(emptyNewEntry);
tableViewer.setInput(entries);
tableModel = entries;
return emptyNewEntry;
}
/**
* Helper to set all the table listeners.
*
* @param labelProvider l
*/
private void addTableListeners(final VariableLabelProvider labelProvider) {
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(final MouseEvent event) {
if (!(event.button != 1)) {
final Point clickLocation = new Point(event.x, event.y);
final Point location = getTableIndexFromClickLocation(clickLocation); // TODO
// does
// it
// work?
if ((location.x == NOT_FOUND) || (table.getSelectionCount() == 0)) {
return;
}
final TableItem item = table.getSelection()[0]; // single selection
if (item == null) {
return;
}
// find column of click
int col = 0;
for (int i = 1; i < TABLE_COLUMNS; i++) {
final Rectangle rect = item.getBounds(i);
if (rect.contains(clickLocation)) {
col = i;
break;
}
}
final int column = col;
final VariableEntry entry = tableModel.get(table.getSelectionIndex());
if (column == 0) { // direction switch
if (entry.getDirection() == EVariableDirection.Incoming) {
entry.setDirection(EVariableDirection.Outgoing);
item.setText(0, entry.getDirection().toString());
} else { // switch the other way around
entry.setDirection(EVariableDirection.Incoming);
item.setText(0, entry.getDirection().toString());
}
tableViewer.refresh();
return;
}
}
}
});
}
/**
* Before editing, determine model value of tree item.
*
* @param element The selected model entry
* @param column The column to create choices for
* @return The values
*/
String[] getAttributeValuesForCurrentTreeItem(final XSDElement element, final int column) {
assert element != null;
assert column >= 1;
if (column == 1) {
return element.getAttributeNames();
} else if (column == 2) {
return element.getAttributeValues();
}
return XSDElement.EMPTY_STRING;
}
/**
* Before editing, determine model value of tree item.
*
* @param item The item selected
* @param column The column to create choices for
* @return The values
*/
String[] getAttributeValuesForCurrentTreeItem(final TreeItem item, final int column) {
final XSDElement element = findModelItemFromViewItem(item);
return getAttributeValuesForCurrentTreeItem(element, column);
}
/**
* Get the value from the model.
*
* @param element The selected model entry
* @param column The column to create choices for
* @return The string
*/
static String getCurrentElementValue(final XSDElement element, final int column) {
assert column >= 1;
if (column == 1) {
return element.getCurrentAttributeName();
} else if (column == 2) {
return element.getCurrentAttributeValue();
}
return null; // should never happen
}
/**
* Set the value to the model.
*
* @param element The selected model entry
* @param column The column to create choices for
* @param value The string
*/
static void setCurrentElementValue(final XSDElement element, final int column, final String value) {
assert column >= 1;
if (column == 1) {
element.setCurrentAttributeName(value);
} else if (column == 2) {
element.setCurrentAttributeValue(value);
}
}
/**
* After editing, set the value back to the model.
*
* @param element The selected model entry
* @param text The string to set
* @param column The column to create choices for
*/
static void setElementValue(final XSDElement element, final String text, final int column) {
assert column >= 1;
if (column == 1) {
element.setAttributeName(text);
} else if (column == 2) {
element.setAttributeValue(text);
}
}
/**
* After editing, set the value back to the model.
*
* @param item The item selected
* @param text The string to set
* @param column The column to create choices for
*/
void setElementValue(final TreeItem item, final String text, final int column) {
final XSDElement element = findModelItemFromViewItem(item);
setElementValue(element, text, column);
}
/**
* Restrict the number of entries allowed to choose. This is useful for e.g. single-selections.
*
* @param num The allowed number of selections in the list. If 1, then replacing an already set variable is allowed by dropping.
*/
void setMaximumNumberOfEntries(final int num) {
maxEntries = num;
}
/**
* Determine path to tree (view) root from a selected/pointed at tree item.
*
* @param item The (sub)item to start from
* @return The list of tree items from root to leaf
*/
private List<String> getPathFromViewItems(final TreeItem item) {
final List<String> path = new LinkedList<String>(); // don't use "Generics.new*" here Why?
// because we need a linked list?)
path.add(item.getText());
TreeItem current = item;
// traverse upwards to view root
while (current.getParentItem() != null) {
current = current.getParentItem();
path.add(0, current.getText());
}
return path;
}
/**
* Determine model entries for a previously calculated view path.
*
* @param path The path
* @return The model entries
*/
private List<XSDElement> getModelEntriesFromPath(final List<String> path) {
final List<XSDElement> elements = new ArrayList<XSDElement>();
XSDElement element = doc;
// traverse downwards to model item
for (final String name : path) {
for (final XSDElement e : element.getElements()) {
if (e.getName().equals(name)) {
element = e;
elements.add(element);
continue;
}
}
}
return elements;
}
/**
* Useful helper before and after editing.
*
* @param item The tree item on which any action is performed
* @return The corresponding model element
*/
private XSDElement findModelItemFromViewItem(final TreeItem item) {
final List<String> path = getPathFromViewItems(item);
final List<XSDElement> elements = getModelEntriesFromPath(path);
return elements.get(elements.size() - 1);
}
/**
* Helper to create an XPath from a drag operation on the tree.
*
* @param item The item dragged
* @return The XPath for all the parent elements and selected attribute/values
*/
private VariableEntry getVariableFromViewItem(final TreeItem item) {
final List<String> path = getPathFromViewItems(item);
final List<XSDElement> elements = getModelEntriesFromPath(path);
final StringBuilder sb = new StringBuilder();
for (final XSDElement element : elements) {
if ((element.getCurrentAttributeName() == null)
|| (element.getCurrentAttributeValue() == null)
|| element.getCurrentAttributeName().equals("")
|| element.getCurrentAttributeValue().equals("")) {
sb.append("/").append(element.getName()); // not predicate
} else {
sb.append("/").append(element.getName())
.append("[@").append(element.getCurrentAttributeName())
.append("='").append(element.getCurrentAttributeValue()).append("']");
}
}
final String baseName = elements.get(elements.size() - 1).getName();
final VariableEntry var = new VariableEntry(
EVariableDirection.Incoming,
createUniqueVariableName(baseName),
sb.toString(),
VariableType.String);
return var;
}
/**
* Check if an automatically created variable name already exists. If it exists, create a new non-existing numbered version
*
* @param baseName The original name
* @return The unique name version
*/
private String createUniqueVariableName(final String baseName) {
final Set<String> names = new HashSet<String>();
final int max = tableModel.size() - 1;
for (int i = 0; i < max; i++) {
names.add(tableModel.get(i).getName().intern());
}
if (!names.contains(baseName)) {
return baseName;
}
int counter = 1;
String newName;
do {
newName = baseName + "_" + Integer.toString(counter);
if (names.contains(newName)) {
counter++;
continue;
}
break;
} while (true);
return newName;
}
/**
* Copies a "last line" entry to a new one and shifts the "empty" entry down one position. This leads to the reference staying untouched
* and able to detect new "new last line entries" again.
*
* @param entry The just edited variable entry (possibly the last one)
*/
void copyNewEntryIfNecessary(final VariableEntry entry) {
if (entry == newEntry) { // reference comparison
final int row = table.getSelectionIndex();
final VariableEntry copyEntry = new VariableEntry(entry);
// now reset "new entry" entry
newEntry.setDirection(EVariableDirection.Incoming);
newEntry.setName("");
newEntry.setXpath("");
tableModel.add(row, copyEntry);
updateTreeAttributesFromTableEntry(copyEntry);
} else {
updateTreeAttributesFromTableEntry(entry);
}
tableViewer.refresh();
}
/**
* Performed when an existing variable entry is selected in the table. Then the attribute names and values in the tree get updated.
* WARNING: This method assumes predicates to be only
*
* @key='value', nothing more complex TODO
*
* @param entry The entry to update
*/
void updateTreeAttributesFromTableEntry(final VariableEntry entry) {
final XPathLocation xpath = XPathParser.parse(entry.getXpath());
XSDElement element = doc;
for (final XPathStep step : xpath.getSteps()) {
for (final XSDElement child : element.getElements()) {
if (child.getName().equals(step.getValue())) { // found step in model
element = child;
if (step instanceof XPathNode) {
final XPathNode node = (XPathNode) step;
final XPathPredicate predicate = node.getPredicate();
if (predicate != null) {
final String pred = predicate.getValue();
final int splitPos = pred.indexOf("=");
if (splitPos >= 0) {
child.setAttributeName(pred.substring(1, splitPos));
child.setAttributeValue(pred.substring(splitPos + 2, pred.length() - 1));
}
}
}
break;
}
}
}
treeViewer.refresh();
}
/**
* Determine the horizontal click location.
*
* @param item The item (row) clicked on
* @param clickLocation The mouse event location
* @return The column clicked or NOT_FOUND
*/
private int getTreeColumnFromClickLocation(final TreeItem item, final Point clickLocation) {
int column = NOT_FOUND;
for (int i = 0; i < TREE_COLUMNS; i++) {
final Rectangle rect = item.getBounds(i);
if (rect.contains(clickLocation)) {
column = i;
break;
}
}
return column;
}
/**
* Determine click location on table.
*
* @param clickLocation The mouse event location (mouse down)
* @return A point containing x = column and y = row index
*/
private Point getTableIndexFromClickLocation(final Point clickLocation) {
final Rectangle clientArea = table.getClientArea();
int index = table.getTopIndex(); // top-visible index
while (index < table.getItemCount()) {
boolean visible = false;
final TableItem item = table.getItem(index);
for (int i = 0; i < TABLE_COLUMNS; i++) {
final Rectangle rect = item.getBounds(i);
if (rect.contains(clickLocation)) {
return new Point(i, index);
}
if (!visible && rect.intersects(clientArea)) {
visible = true;
}
}
if (!visible) {
return new Point(NOT_FOUND, NOT_FOUND);
}
index++;
}
return new Point(NOT_FOUND, NOT_FOUND);
}
/**
* Accessor for using classes.
*
* @return The model (all defined variables).
*/
Set<VariableEntry> getVariables() {
final Set<VariableEntry> vars = new HashSet<VariableEntry>();
vars.addAll(tableModel);
vars.remove(newEntry); // remove the "empty next new entry"
return vars;
}
/**
* This is for testing purposes only.
*
* @param args Args
* @throws ParserConfigurationException
* @throws SAXException ex
* @throws IOException ex
* @throws ParserConfigurationException ex
* @throws XMLStreamException ex
*/
public static void main(final String[] args) throws SAXException, IOException, ParserConfigurationException, XMLStreamException {
final XSDElement doc = new XSDElement(null, "root");
doc.setElements(XSDGenerator.generate("test.xml").getElements());
doc.getElements().get(0).getAttributes().remove(0); // remove schema location
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
shell.setText("Test");
final Button ok = new Button(shell, SWT.None);
ok.setText("Open");
ok.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(final Event event) {
final XPathChooserDialog dialog = new XPathChooserDialog(shell, doc);
dialog.setMaximumNumberOfEntries(1);
Set<VariableEntry> selectedVariables = new HashSet<VariableEntry>();
selectedVariables.add(new VariableEntry(
EVariableDirection.Outgoing, "bla", "/cpacs/header[@xyz='abc']/name", VariableType.String));
dialog.setSelectedVariables(selectedVariables);
if (dialog.open() == SWT.OK) {
dialog.getSelectedVariables();
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
/**
* Initialize the view with already known variables.
*
* @param variables The variables
*/
public void setSelectedVariables(final Collection<VariableEntry> variables) {
Set<VariableEntry> toRetain = new HashSet<VariableEntry>();
toRetain.add(newEntry);
tableModel.retainAll(toRetain);
for (final VariableEntry variable : variables) {
tableModel.add(tableModel.size() - 1, variable);
}
tableViewer.refresh();
}
}