/** * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * All rights reserved. This program and the accompanying materials are made available under * the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html. * */ package gov.redhawk.sca.internal.ui.properties; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.emf.common.util.EList; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import gov.redhawk.model.sca.ScaAbstractProperty; import gov.redhawk.sca.ui.ScaUiPlugin; import mil.jpeojtrs.sca.prf.PropertyValueType; import mil.jpeojtrs.sca.util.math.ComplexBoolean; import mil.jpeojtrs.sca.util.math.ComplexDouble; import mil.jpeojtrs.sca.util.math.ComplexFloat; import mil.jpeojtrs.sca.util.math.ComplexLong; import mil.jpeojtrs.sca.util.math.ComplexLongLong; import mil.jpeojtrs.sca.util.math.ComplexShort; import mil.jpeojtrs.sca.util.math.ComplexULong; import mil.jpeojtrs.sca.util.math.ComplexULongLong; import mil.jpeojtrs.sca.util.math.ComplexUShort; public abstract class AbstractSequencePropertyValueWizardPage extends WizardPage { protected final ScaAbstractProperty< ? > property; private StructuredViewer viewer; private Button removeButton; private Button downButton; private Button upButton; private Button resetButton; public AbstractSequencePropertyValueWizardPage(ScaAbstractProperty< ? > property) { super("valuePage", "Edit Value", null); this.property = property; String propDesc = property.getDescription(); if (propDesc == null) { propDesc = ""; } setDescription("Edit the values of the sequence property.\n" + propDesc); } @Override public void createControl(final Composite parent) { final Composite root = new Composite(parent, SWT.None); root.setLayout(new GridLayout(2, false)); final Composite tableComposite = new Composite(root, SWT.NO_FOCUS); viewer = createViewer(tableComposite); viewer.setInput(this.property); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { updateButtonState(); } }); tableComposite.setLayoutData(GridDataFactory.fillDefaults().hint(500, 300).span(2, 1).create()); // Create spacer new Label(root, SWT.None).setLayoutData(GridDataFactory.fillDefaults().span(1, 1).grab(true, false).create()); final Composite buttonComposite = createButtons(root); buttonComposite.setLayoutData(GridDataFactory.fillDefaults().span(1, 1).grab(false, false).create()); setControl(root); } protected Object getDefaultValue(final PropertyValueType type, boolean isComplex) { if (isComplex) { switch (type) { case BOOLEAN: return new ComplexBoolean(); case DOUBLE: return new ComplexDouble(); case FLOAT: return new ComplexFloat(); case LONG: return new ComplexLong(); case LONGLONG: return new ComplexLongLong(); case SHORT: return new ComplexShort(); case ULONG: return new ComplexULong(); case USHORT: return new ComplexUShort(); case ULONGLONG: return new ComplexULongLong(); case STRING: case OCTET: case OBJREF: case CHAR: default: throw new IllegalArgumentException("Unhandled property type"); } } else { switch (type) { case BOOLEAN: return Boolean.FALSE; case CHAR: return 'a'; case DOUBLE: return 0.00d; case FLOAT: return 0.00f; case LONG: return 0; case LONGLONG: return 0L; case OBJREF: return null; case OCTET: return (short) 0; case SHORT: return (short) 0; case STRING: return "newString"; case ULONG: return 0L; case USHORT: return 0; case ULONGLONG: return BigInteger.ZERO; default: throw new IllegalArgumentException("Unhandled property type"); } } } protected abstract EList< ? > getList(); protected abstract void handleAddValue(); private void handleRemoveValue() { IStructuredSelection selection = viewer.getStructuredSelection(); if (!selection.isEmpty()) { EList< ? > list = getList(); int index = indexOf(list, selection.getFirstElement()); for (Object item : selection.toList()) { list.remove(indexOf(list, item)); } if (!list.isEmpty()) { index = Math.min(index, list.size() - 1); setSelection(index); } } } private void handleMoveUp() { if (viewer.getSelection().isEmpty()) { return; } // Move the items up in ascending order to ensure that they do not overlap, and adjust the selection // indices while we're at it EList< ? > list = getList(); int[] indices = getSelectionIndices(); for (int ii = 0; ii < indices.length; ++ii) { int index = indices[ii]; list.move(index - 1, index); indices[ii] -= 1; } setSelection(indices); } private void handleMoveDown() { if (viewer.getSelection().isEmpty()) { return; } // Move the items down in descending order to ensure that they do not overlap, and adjust the selection // indices while we're at it int[] indices = getSelectionIndices(); EList< ? > list = getList(); for (int ii = indices.length - 1; ii >= 0; --ii) { int index = indices[ii]; list.move(index + 1, index); indices[ii] += 1; } setSelection(indices); } private void setSelection(int index) { setSelection(new int[] { index }); } private void setSelection(int[] indices) { // Fetch the model objects as seen from the viewer; these will differ from the list's elements if they are // wrapped (such as in a simple sequence) IStructuredContentProvider provider = (IStructuredContentProvider) viewer.getContentProvider(); Object[] elements = provider.getElements(viewer.getInput()); // Convert the indices into the list of model objects to ensure that the selection succeeds List<Object> selection = new ArrayList<Object>(indices.length); for (int index : indices) { selection.add(elements[index]); } viewer.setSelection(new StructuredSelection(selection)); } private int[] getSelectionIndices() { IStructuredSelection selection = viewer.getStructuredSelection(); int[] indices = new int[selection.size()]; int offset = 0; for (Object item : selection.toList()) { indices[offset++] = indexOf(getList(), item); } Arrays.sort(indices); return indices; } protected abstract int indexOf(List< ? > list, Object object); private Composite createButtons(final Composite root) { final Composite buttonRoot = new Composite(root, SWT.None); buttonRoot.setLayout(new GridLayout(5, false)); final ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); final Button addButton = new Button(buttonRoot, SWT.PUSH); addButton.setToolTipText("Add"); addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleAddValue(); } }); addButton.setImage(sharedImages.getImage(ISharedImages.IMG_OBJ_ADD)); this.removeButton = new Button(buttonRoot, SWT.PUSH); this.removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleRemoveValue(); } }); this.removeButton.setToolTipText("Remove"); this.removeButton.setImage(sharedImages.getImage(ISharedImages.IMG_ETOOL_DELETE)); this.upButton = new Button(buttonRoot, SWT.PUSH); this.upButton.setImage(ScaUiPlugin.getDefault().getImage("icons/clcl16/up.png")); this.upButton.setToolTipText("Move value up"); this.upButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleMoveUp(); } }); this.downButton = new Button(buttonRoot, SWT.PUSH); this.downButton.setImage(ScaUiPlugin.getDefault().getImage("icons/clcl16/down.png")); this.downButton.setToolTipText("Move value down"); this.downButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleMoveDown(); } }); this.resetButton = new Button(buttonRoot, SWT.PUSH); resetButton.setText("Reset"); this.resetButton.setToolTipText("Reset to default value"); this.resetButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleReset(); } }); updateButtonState(); return buttonRoot; } protected void handleReset() { property.restoreDefaultValue(); } protected abstract StructuredViewer createViewer(Composite parent); /** * Setter to allow us to enable / disable the remove button * * @param enabled Boolean representing whether we should or should not enable the remove button */ private void updateButtonState() { IStructuredSelection selection = viewer.getStructuredSelection(); if (selection.isEmpty()) { removeButton.setEnabled(false); upButton.setEnabled(false); downButton.setEnabled(false); } else { // Remove is always enabled because there must be at least one selection removeButton.setEnabled(true); // Find the lowest and highest selection indices List< ? > list = getList(); int minIndex = Integer.MAX_VALUE; int maxIndex = -1; for (Object item : selection.toList()) { int index = indexOf(list, item); minIndex = Math.min(minIndex, index); maxIndex = Math.max(maxIndex, index); } // The up and down buttons are enabled only if there is somewhere to go (i.e., not the first or last item, // respectively) upButton.setEnabled(minIndex > 0); downButton.setEnabled(maxIndex < (list.size() - 1)); } } }