Java tutorial
/** * This program and the accompanying materials * are made available under the terms of the License * which accompanies this distribution in the file LICENSE.txt */ package com.archimatetool.editor.propertysections; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.draw2d.ColorConstants; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.ECollections; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.CompoundCommand; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ColumnPixelData; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.IFilter; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableColorProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.DropTargetListener; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; 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.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.ui.PlatformUI; import com.archimatetool.editor.model.commands.EObjectFeatureCommand; import com.archimatetool.editor.model.commands.EObjectNonNotifyingCompoundCommand; import com.archimatetool.editor.ui.IArchimateImages; import com.archimatetool.editor.ui.components.CellEditorGlobalActionHandler; import com.archimatetool.editor.ui.components.ExtendedTitleAreaDialog; import com.archimatetool.editor.ui.components.StringComboBoxCellEditor; import com.archimatetool.editor.utils.HTMLUtils; import com.archimatetool.editor.utils.StringUtils; import com.archimatetool.model.IArchimateFactory; import com.archimatetool.model.IArchimateModel; import com.archimatetool.model.IArchimateModelElement; import com.archimatetool.model.IArchimatePackage; import com.archimatetool.model.IDiagramModelComponent; import com.archimatetool.model.IProperties; import com.archimatetool.model.IProperty; /** * User Properties Section for an Archimate Element, Archimate Model or Diagram Model * * @author Phillip Beauvoir */ public class UserPropertiesSection extends AbstractArchimatePropertySection { private static final String HELP_ID = "com.archimatetool.help.userProperties"; //$NON-NLS-1$ /** * Filter to show or reject this section depending on input value */ public static class Filter implements IFilter { @Override public boolean select(Object object) { if (object instanceof IProperties) { return true; } if (object instanceof IAdaptable) { return ((IAdaptable) object).getAdapter(IProperties.class) != null; } return false; } } /* * Adapter to listen to changes made elsewhere (including Undo/Redo commands) * This one is a EContentAdapter to listen to child IProperty changes */ private Adapter eAdapter = new EContentAdapter() { private boolean ignoreMessages; @Override public void notifyChanged(Notification msg) { super.notifyChanged(msg); if (msg.getEventType() == EObjectNonNotifyingCompoundCommand.START) { ignoreMessages = true; return; } else if (msg.getEventType() == EObjectNonNotifyingCompoundCommand.END) { ignoreMessages = false; fTableViewer.refresh(); fTableLayout.doRelayout(); } if (!ignoreMessages) { Object feature = msg.getFeature(); if (feature == IArchimatePackage.Literals.PROPERTIES__PROPERTIES) { fTableViewer.refresh(); fTableLayout.doRelayout(); } if (feature == IArchimatePackage.Literals.PROPERTY__KEY || feature == IArchimatePackage.Literals.PROPERTY__VALUE) { fTableViewer.update(msg.getNotifier(), null); } } } }; private IProperties fPropertiesElement; private TableViewer fTableViewer; private UpdatingTableColumnLayout fTableLayout; private IAction fActionNewProperty, fActionNewMultipleProperty, fActionRemoveProperty, fActionShowKeyEditor; @Override protected void createControls(Composite parent) { createTableControl(parent); } @Override protected void setElement(Object element) { if (element instanceof IProperties) { fPropertiesElement = (IProperties) element; } else if (element instanceof IAdaptable) { fPropertiesElement = (IProperties) ((IAdaptable) element).getAdapter(IProperties.class); } else { System.err.println(getClass() + " wants to display for " + element); //$NON-NLS-1$ } refreshControls(); } protected void refreshControls() { fTableViewer.setInput(fPropertiesElement); fTableLayout.doRelayout(); } @Override protected Adapter getECoreAdapter() { return eAdapter; } @Override protected EObject getEObject() { return fPropertiesElement; } /** * Return the Archimate model bound to the properties element * @return */ protected IArchimateModel getArchimateModel() { if (fPropertiesElement instanceof IArchimateModelElement) { return ((IArchimateModelElement) fPropertiesElement).getArchimateModel(); } if (fPropertiesElement instanceof IDiagramModelComponent) { return ((IDiagramModelComponent) fPropertiesElement).getDiagramModel().getArchimateModel(); } return null; } @Override public boolean shouldUseExtraSpace() { return true; } private void createTableControl(Composite parent) { // Table Composite Composite tableComp = createTableComposite(parent, SWT.NULL); fTableLayout = (UpdatingTableColumnLayout) tableComp.getLayout(); // Table Viewer fTableViewer = new TableViewer(tableComp, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION); fTableViewer.getTable().setHeaderVisible(true); fTableViewer.getTable().setLinesVisible(true); addDragSupport(); addDropSupport(); // Help ID on table PlatformUI.getWorkbench().getHelpSystem().setHelp(fTableViewer.getTable(), HELP_ID); // Columns TableViewerColumn columnBlank = new TableViewerColumn(fTableViewer, SWT.NONE, 0); fTableLayout.setColumnData(columnBlank.getColumn(), new ColumnPixelData(24, false)); TableViewerColumn columnKey = new TableViewerColumn(fTableViewer, SWT.NONE, 1); columnKey.getColumn().setText(Messages.UserPropertiesSection_0); fTableLayout.setColumnData(columnKey.getColumn(), new ColumnWeightData(20, true)); columnKey.setEditingSupport(new KeyEditingSupport(fTableViewer)); // Click on Key Table Header columnKey.getColumn().addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sortKeys(); } }); TableViewerColumn columnValue = new TableViewerColumn(fTableViewer, SWT.NONE, 2); columnValue.getColumn().setText(Messages.UserPropertiesSection_1); fTableLayout.setColumnData(columnValue.getColumn(), new ColumnWeightData(80, true)); columnValue.setEditingSupport(new ValueEditingSupport(fTableViewer)); // Content Provider fTableViewer.setContentProvider(new IStructuredContentProvider() { public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } public void dispose() { } public Object[] getElements(Object inputElement) { return ((IProperties) inputElement).getProperties().toArray(); } }); // Label Provider fTableViewer.setLabelProvider(new LabelCellProvider()); // Toolbar ToolBar toolBar = new ToolBar(parent, SWT.FLAT | SWT.VERTICAL); GridDataFactory.fillDefaults().align(SWT.END, SWT.TOP).applyTo(toolBar); ToolBarManager toolBarmanager = new ToolBarManager(toolBar); // New Property fActionNewProperty = new Action(Messages.UserPropertiesSection_2) { @Override public void run() { if (isAlive()) { int index = -1; IProperty selected = (IProperty) ((IStructuredSelection) fTableViewer.getSelection()) .getFirstElement(); if (selected != null) { index = fPropertiesElement.getProperties().indexOf(selected) + 1; } IProperty property = IArchimateFactory.eINSTANCE.createProperty(); getCommandStack() .execute(new NewPropertyCommand(fPropertiesElement.getProperties(), property, index)); fTableViewer.editElement(property, 1); } } @Override public String getToolTipText() { return getText(); } @Override public ImageDescriptor getImageDescriptor() { return IArchimateImages.ImageFactory.getImageDescriptor(IArchimateImages.ICON_PLUS); } }; // New Multiple Properties fActionNewMultipleProperty = new Action(Messages.UserPropertiesSection_3) { @Override public void run() { if (isAlive()) { MultipleAddDialog dialog = new MultipleAddDialog(fPage.getSite().getShell()); if (dialog.open() == Window.OK) { getCommandStack().execute(dialog.getCommand()); } } } @Override public String getToolTipText() { return getText(); } @Override public ImageDescriptor getImageDescriptor() { return IArchimateImages.ImageFactory.getImageDescriptor(IArchimateImages.ICON_MUTIPLE); } }; // Remove Property fActionRemoveProperty = new Action(Messages.UserPropertiesSection_4) { @Override public void run() { if (isAlive()) { CompoundCommand compoundCmd = new EObjectNonNotifyingCompoundCommand(fPropertiesElement) { @Override public String getLabel() { return getCommands().size() > 1 ? Messages.UserPropertiesSection_5 : Messages.UserPropertiesSection_6; } }; for (Object o : ((IStructuredSelection) fTableViewer.getSelection()).toList()) { Command cmd = new RemovePropertyCommand(fPropertiesElement.getProperties(), (IProperty) o); compoundCmd.add(cmd); } getCommandStack().execute(compoundCmd); } } @Override public String getToolTipText() { return getText(); } @Override public ImageDescriptor getImageDescriptor() { return IArchimateImages.ImageFactory.getImageDescriptor(IArchimateImages.ICON_SMALL_X); } }; fActionRemoveProperty.setEnabled(false); // Manage fActionShowKeyEditor = new Action(Messages.UserPropertiesSection_7) { @Override public void run() { if (isAlive()) { UserPropertiesManagerDialog dialog = new UserPropertiesManagerDialog(fPage.getSite().getShell(), getArchimateModel()); dialog.open(); } } @Override public String getToolTipText() { return getText(); } @Override public ImageDescriptor getImageDescriptor() { return IArchimateImages.ImageFactory.getImageDescriptor(IArchimateImages.ICON_COG); } }; toolBarmanager.add(fActionNewProperty); toolBarmanager.add(fActionNewMultipleProperty); toolBarmanager.add(fActionRemoveProperty); toolBarmanager.add(fActionShowKeyEditor); toolBarmanager.update(true); /* * Selection Listener */ fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { fActionRemoveProperty.setEnabled(!event.getSelection().isEmpty()); } }); /* * Table Double-click on cell */ fTableViewer.getTable().addListener(SWT.MouseDoubleClick, new Listener() { @Override public void handleEvent(Event event) { // Get Table item TableItem item = fTableViewer.getTable().getItem(new Point(event.x, event.y)); // Double-click into empty table creates new Property if (item == null) { fActionNewProperty.run(); } // Handle selected item property double-clicked else { if (item.getData() instanceof IProperty) { handleDoubleClick((IProperty) item.getData()); } } } }); hookContextMenu(); } /** * Hook into a right-click menu */ private void hookContextMenu() { MenuManager menuMgr = new MenuManager("#PropertiesPopupMenu"); //$NON-NLS-1$ menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { fillContextMenu(manager); } }); Menu menu = menuMgr.createContextMenu(fTableViewer.getControl()); fTableViewer.getControl().setMenu(menu); } private void fillContextMenu(IMenuManager manager) { manager.add(fActionNewProperty); manager.add(fActionNewMultipleProperty); manager.add(new Separator()); manager.add(fActionRemoveProperty); manager.add(new Separator()); manager.add(fActionShowKeyEditor); } /** * Sort Keys */ private void sortKeys() { if (isAlive()) { getCommandStack().execute(new SortPropertiesCommand(fPropertiesElement.getProperties())); } } /** * If it's a URL open in Browser */ private void handleDoubleClick(IProperty selected) { Matcher matcher = HTMLUtils.HTML_LINK_PATTERN.matcher(selected.getValue()); if (matcher.find()) { String href = matcher.group(); HTMLUtils.openLinkInBrowser(href); } } /** * @return All unique Property Keys for an entire model (sorted) */ private String[] getAllUniquePropertyKeysForModel() { IArchimateModel model = getArchimateModel(); List<String> list = new ArrayList<String>(); for (Iterator<EObject> iter = model.eAllContents(); iter.hasNext();) { EObject element = iter.next(); if (element instanceof IProperty) { String key = ((IProperty) element).getKey(); if (StringUtils.isSetAfterTrim(key) && !list.contains(key)) { list.add(key); } } } String[] items = list.toArray(new String[list.size()]); Arrays.sort(items, new Comparator<String>() { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); } }); return items; } // ----------------------------------------------------------------------------------------------------------------- // // Drag & Drop // // ----------------------------------------------------------------------------------------------------------------- private boolean fDragSourceValid; /* * Drag Source support */ private void addDragSupport() { int operations = DND.DROP_MOVE; Transfer[] transferTypes = new Transfer[] { LocalSelectionTransfer.getTransfer() }; fTableViewer.addDragSupport(operations, transferTypes, new DragSourceListener() { public void dragFinished(DragSourceEvent event) { LocalSelectionTransfer.getTransfer().setSelection(null); fDragSourceValid = false; } public void dragSetData(DragSourceEvent event) { // For consistency set the data to the selection even though // the selection is provided by the LocalSelectionTransfer // to the drop target adapter. event.data = LocalSelectionTransfer.getTransfer().getSelection(); } public void dragStart(DragSourceEvent event) { if (!isAlive()) { return; } IStructuredSelection selection = (IStructuredSelection) fTableViewer.getSelection(); LocalSelectionTransfer.getTransfer().setSelection(selection); event.doit = true; fDragSourceValid = true; } }); } private void addDropSupport() { int operations = DND.DROP_MOVE; Transfer[] transferTypes = new Transfer[] { LocalSelectionTransfer.getTransfer() }; fTableViewer.addDropSupport(operations, transferTypes, new DropTargetListener() { public void dragEnter(DropTargetEvent event) { } public void dragLeave(DropTargetEvent event) { } public void dragOperationChanged(DropTargetEvent event) { event.detail = getEventDetail(event); } public void dragOver(DropTargetEvent event) { event.detail = getEventDetail(event); if (event.detail == DND.DROP_NONE) { event.feedback = DND.FEEDBACK_NONE; } else { event.feedback = getDragFeedbackType(event); } event.feedback |= DND.FEEDBACK_SCROLL; } public void drop(DropTargetEvent event) { doDropOperation(event); } public void dropAccept(DropTargetEvent event) { } private int getEventDetail(DropTargetEvent event) { return fDragSourceValid ? DND.DROP_MOVE : DND.DROP_NONE; } }); } @SuppressWarnings("unchecked") private void doDropOperation(DropTargetEvent event) { if (!LocalSelectionTransfer.getTransfer().isSupportedType(event.currentDataType)) { return; } ISelection selection = LocalSelectionTransfer.getTransfer().getSelection(); if (selection == null || selection.isEmpty()) { return; } // Determine the index position of the drop int index = getDropTargetPosition(event); // Valid position? List<?> list = ((IStructuredSelection) selection).toList(); for (Object o : list) { IProperty property = (IProperty) o; int movedIndex = fPropertiesElement.getProperties().indexOf(property); if (movedIndex == index || (movedIndex + 1) == index) { return; } } movePropertiesToIndex((List<IProperty>) list, index); } private void movePropertiesToIndex(List<IProperty> propertiesToMove, int index) { EList<IProperty> properties = fPropertiesElement.getProperties(); // Sanity check if (index < 0) { index = 0; } if (index > properties.size()) { index = properties.size(); } CompoundCommand compoundCmd = new CompoundCommand(Messages.UserPropertiesSection_8); for (IProperty property : propertiesToMove) { int oldIndex = properties.indexOf(property); if (index > oldIndex) { index--; } if (index == oldIndex) { break; } compoundCmd.add(new MovePropertyCommand(properties, property, index)); index++; } getCommandStack().execute(compoundCmd.unwrap()); } private int getDropTargetPosition(DropTargetEvent event) { int index = -1; Point pt = fTableViewer.getControl().toControl(event.x, event.y); if (pt.y < 5) { index = 0; } else if (event.item != null) { IProperty property = (IProperty) event.item.getData(); index = fPropertiesElement.getProperties().indexOf(property); } else { index = fPropertiesElement.getProperties().size(); } // Dropped in after position int feedback = getDragFeedbackType(event); if (feedback == DND.FEEDBACK_INSERT_AFTER) { index += 1; } return index; } /** * Determine the feedback type for DND */ private int getDragFeedbackType(DropTargetEvent event) { if (event.item == null) { return DND.FEEDBACK_NONE; } Rectangle rect = ((TableItem) event.item).getBounds(); Point pt = fTableViewer.getControl().toControl(event.x, event.y); if (pt.y < rect.y + 3) { return DND.FEEDBACK_INSERT_BEFORE; } if (pt.y > rect.y + rect.height - 3) { return DND.FEEDBACK_INSERT_AFTER; } return DND.FEEDBACK_NONE; // <----- This is important otherwise we get unwanted selection cheese on XP } // ----------------------------------------------------------------------------------------------------------------- // // Table functions // // ----------------------------------------------------------------------------------------------------------------- /** * Label Provider */ private static class LabelCellProvider extends LabelProvider implements ITableLabelProvider, ITableColorProvider { public Image getColumnImage(Object element, int columnIndex) { return null; } @Override public String getColumnText(Object element, int columnIndex) { switch (columnIndex) { case 1: String key = ((IProperty) element).getKey(); if (!StringUtils.isSetAfterTrim(key)) { key = Messages.UserPropertiesSection_9; } return key; case 2: return ((IProperty) element).getValue(); default: return null; } } @Override public Color getForeground(Object element, int columnIndex) { if (columnIndex == 2) { Matcher matcher = HTMLUtils.HTML_LINK_PATTERN.matcher(((IProperty) element).getValue()); return matcher.find() ? ColorConstants.blue : null; } return null; } @Override public Color getBackground(Object element, int columnIndex) { return null; } } /** * Key Editor */ private class KeyEditingSupport extends EditingSupport { StringComboBoxCellEditor cellEditor; public KeyEditingSupport(ColumnViewer viewer) { super(viewer); cellEditor = new StringComboBoxCellEditor((Composite) viewer.getControl(), new String[0], true); // Nullify some global Action Handlers so that this cell editor can handle them hookCellEditorGlobalActionHandler(cellEditor); } @Override protected CellEditor getCellEditor(Object element) { String[] items = new String[0]; if (isAlive()) { items = getAllUniquePropertyKeysForModel(); } cellEditor.setItems(items); return cellEditor; } @Override protected boolean canEdit(Object element) { return true; } @Override protected Object getValue(Object element) { return ((IProperty) element).getKey(); } @Override protected void setValue(Object element, Object value) { if (isAlive()) { getCommandStack().execute(new EObjectFeatureCommand(Messages.UserPropertiesSection_10, (IProperty) element, IArchimatePackage.Literals.PROPERTY__KEY, value)); } } } /** * Value Editor */ private class ValueEditingSupport extends EditingSupport { TextCellEditor cellEditor; public ValueEditingSupport(ColumnViewer viewer) { super(viewer); cellEditor = new TextCellEditor((Composite) viewer.getControl()); // Nullify some global Action Handlers so that this cell editor can handle them hookCellEditorGlobalActionHandler(cellEditor); } @Override protected CellEditor getCellEditor(Object element) { return cellEditor; } @Override protected boolean canEdit(Object element) { return true; } @Override protected Object getValue(Object element) { return ((IProperty) element).getValue(); } @Override protected void setValue(Object element, Object value) { if (isAlive()) { getCommandStack().execute(new EObjectFeatureCommand(Messages.UserPropertiesSection_11, (IProperty) element, IArchimatePackage.Literals.PROPERTY__VALUE, value)); } } } /** * Set some editing global Action Handlers to null when the cell editor is activated * And restore them when the cell editor is deactivated. */ private void hookCellEditorGlobalActionHandler(CellEditor cellEditor) { Listener listener = new Listener() { CellEditorGlobalActionHandler globalActionHandler; @Override public void handleEvent(Event event) { switch (event.type) { case SWT.Activate: globalActionHandler = new CellEditorGlobalActionHandler(); globalActionHandler.clearGlobalActions(); break; case SWT.Deactivate: if (globalActionHandler != null) { globalActionHandler.restoreGlobalActions(); } break; default: break; } } }; cellEditor.getControl().addListener(SWT.Activate, listener); cellEditor.getControl().addListener(SWT.Deactivate, listener); } // ----------------------------------------------------------------------------------------------------------------- // // Commands // // ----------------------------------------------------------------------------------------------------------------- /** * New Property Command */ private static class NewPropertyCommand extends Command { private EList<IProperty> properties; private IProperty property; private int index; NewPropertyCommand(EList<IProperty> properties, IProperty property, int index) { this.properties = properties; this.property = property; this.index = index; setLabel(Messages.UserPropertiesSection_12); } @Override public void execute() { if (index < 0 || index > properties.size()) { properties.add(property); } else { properties.add(index, property); } } @Override public void undo() { properties.remove(property); } @Override public void dispose() { properties = null; property = null; } } /** * Remove Property Command */ private static class RemovePropertyCommand extends Command { private EList<IProperty> properties; private IProperty property; private int index; RemovePropertyCommand(EList<IProperty> properties, IProperty property) { this.properties = properties; this.property = property; } @Override public void execute() { // Ensure index is stored just before execute because if this is part of a composite action // then the index positions will have changed index = properties.indexOf(property); if (index != -1) { properties.remove(property); } } @Override public void undo() { if (index != -1) { properties.add(index, property); } } @Override public void dispose() { properties = null; property = null; } } /** * Move Property Command */ private static class MovePropertyCommand extends Command { private EList<IProperty> properties; private IProperty property; private int oldIndex; private int newIndex; MovePropertyCommand(EList<IProperty> properties, IProperty property, int newIndex) { this.properties = properties; this.property = property; this.newIndex = newIndex; setLabel(Messages.UserPropertiesSection_13); } @Override public void execute() { oldIndex = properties.indexOf(property); properties.move(newIndex, property); } @Override public void undo() { properties.move(oldIndex, property); } @Override public void dispose() { properties = null; property = null; } } /** * Sort Properties Command */ private static class SortPropertiesCommand extends Command implements Comparator<IProperty> { private EList<IProperty> properties; private List<IProperty> original; public SortPropertiesCommand(EList<IProperty> properties) { setLabel(Messages.UserPropertiesSection_14); this.properties = properties; // Keep a copy of the original order original = new ArrayList<IProperty>(properties); } @Override public boolean canExecute() { if (properties.size() < 2) { return false; } EList<IProperty> temp = new BasicEList<IProperty>(properties); ECollections.sort(temp, this); for (int i = 0; i < temp.size(); i++) { if (temp.get(i) != properties.get(i)) { return true; } } return false; } @Override public void execute() { ECollections.sort(properties, this); } @Override public void undo() { properties.clear(); properties.addAll(original); } @Override public int compare(IProperty p1, IProperty p2) { String key1 = StringUtils.safeString(p1.getKey()); String key2 = StringUtils.safeString(p2.getKey()); return key1.compareToIgnoreCase(key2); } @Override public void dispose() { properties = null; original = null; } } // ----------------------------------------------------------------------------------------------------------------- // // Multiple Add Dialog // // ----------------------------------------------------------------------------------------------------------------- private class MultipleAddDialog extends ExtendedTitleAreaDialog { private CheckboxTableViewer tableViewer; private Button buttonSelectAll, buttonDeselectAll; private CompoundCommand compoundCmd; private String[] keys; public MultipleAddDialog(Shell parentShell) { super(parentShell, "ArchimatePropertiesMultipleAddDialog"); //$NON-NLS-1$ setTitleImage( IArchimateImages.ImageFactory.getImage(IArchimateImages.ECLIPSE_IMAGE_IMPORT_PREF_WIZARD)); setShellStyle(getShellStyle() | SWT.RESIZE); keys = getAllUniquePropertyKeysForModel(); } @Override protected void configureShell(Shell shell) { super.configureShell(shell); shell.setText(Messages.UserPropertiesSection_15); } @Override protected Control createButtonBar(Composite parent) { Control c = super.createButtonBar(parent); if (keys.length == 0) { getButton(IDialogConstants.OK_ID).setEnabled(false); buttonSelectAll.setEnabled(false); buttonDeselectAll.setEnabled(false); } return c; } @Override protected Control createDialogArea(Composite parent) { // Help PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, HELP_ID); setTitle(Messages.UserPropertiesSection_16); setMessage(Messages.UserPropertiesSection_17); Composite composite = (Composite) super.createDialogArea(parent); Composite client = new Composite(composite, SWT.NULL); GridLayout layout = new GridLayout(2, false); client.setLayout(layout); client.setLayoutData(new GridData(GridData.FILL_BOTH)); createTableControl(client); createButtonPanel(client); return composite; } private void createTableControl(Composite parent) { Composite tableComp = new Composite(parent, SWT.BORDER); TableColumnLayout tableLayout = new TableColumnLayout(); tableComp.setLayout(tableLayout); tableComp.setLayoutData(new GridData(GridData.FILL_BOTH)); Table table = new Table(tableComp, SWT.MULTI | SWT.FULL_SELECTION | SWT.CHECK); tableViewer = new CheckboxTableViewer(table); tableViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH)); tableViewer.getTable().setLinesVisible(true); tableViewer.setSorter(new ViewerSorter()); // Column TableViewerColumn columnKey = new TableViewerColumn(tableViewer, SWT.NONE, 0); tableLayout.setColumnData(columnKey.getColumn(), new ColumnWeightData(100, true)); // Content Provider tableViewer.setContentProvider(new IStructuredContentProvider() { public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } public void dispose() { } public Object[] getElements(Object inputElement) { return keys; } }); // Label Provider tableViewer.setLabelProvider(new LabelProvider()); tableViewer.setInput(""); // anything will do //$NON-NLS-1$ } private void createButtonPanel(Composite parent) { Composite client = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; client.setLayout(layout); GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); client.setLayoutData(gd); buttonSelectAll = new Button(client, SWT.PUSH); buttonSelectAll.setText(Messages.UserPropertiesSection_18); gd = new GridData(GridData.FILL_HORIZONTAL); buttonSelectAll.setLayoutData(gd); buttonSelectAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { tableViewer.setCheckedElements(keys); } }); buttonDeselectAll = new Button(client, SWT.PUSH); buttonDeselectAll.setText(Messages.UserPropertiesSection_19); gd = new GridData(GridData.FILL_HORIZONTAL); buttonDeselectAll.setLayoutData(gd); buttonDeselectAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { tableViewer.setCheckedElements(new Object[] {}); } }); } @Override protected void okPressed() { compoundCmd = new EObjectNonNotifyingCompoundCommand(fPropertiesElement, Messages.UserPropertiesSection_20); for (Object o : tableViewer.getCheckedElements()) { IProperty property = IArchimateFactory.eINSTANCE.createProperty(); property.setKey((String) o); compoundCmd.add(new NewPropertyCommand(fPropertiesElement.getProperties(), property, -1)); } super.okPressed(); } Command getCommand() { return compoundCmd; } @Override protected Point getDefaultDialogSize() { return new Point(400, 250); } } }