package org.eclipse.emf.examples.jet.article2.ui; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; 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.graphics.Image; 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.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.emf.examples.jet.article2.model.Attribute; import org.eclipse.emf.examples.jet.article2.model.Instance; import org.eclipse.emf.examples.jet.article2.model.NameUtil; import org.eclipse.emf.examples.jet.article2.model.TypesafeEnum; /** * Wizard page where the user can specify the instances of the typesafe * enumeration class, and the attribute values for each instance. * * @author Remko Popma * @version $Revision: 1.3 $ ($Date: 2006/12/29 18:36:19 $) */ public class NewTypesafeEnumCreationWizardPageInstances extends WizardPage { private final static String PAGE_NAME = "InstancesPage"; //$NON-NLS-1$ private String[] mColumnNames = new String []{ WizardMessages.getString("NewEnumWizPageInst.col.Default"), WizardMessages.getString("NewEnumWizPageInst.col.Name"), }; private static final int COL_DEFAULT = 0; private static final int COL_NAME = 1; private int[] mColumnWidths = new int []{ 30, 400, }; private static final int TABLE_ROWS = 15; // show 15 rows private boolean mIgnoreCheckEvents = false; private CheckboxTableViewer mTableViewer = null; private Table mTableWidget = null; private Button mButtonAdd = null; private Button mButtonEdit = null; private Button mButtonRemove = null; /** * Helper class that provides content for the table widget. */ protected class InstanceContentProvider implements IStructuredContentProvider { public Object[] getElements(Object inputElement) { List<Instance> result = new ArrayList<Instance>(); for (Iterator<Instance> i = ((TypesafeEnum)inputElement).instances(); i.hasNext();) { result.add(i.next()); } return result.toArray(); } public void dispose() { // Ignore } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // Ignore } } /** * Helper class that knows how to display a table widget row. */ protected class InstanceLabelProvider extends LabelProvider implements ITableLabelProvider { public Image getColumnImage(Object element, int columnIndex) { return null; } public String getColumnText(Object element, int columnIndex) { if (element instanceof Instance) { Instance instance = (Instance)element; switch (columnIndex) { case COL_DEFAULT: mTableViewer.setChecked(instance, instance.isDefault()); return ""; case COL_NAME: return instance.getName() == null ? "" : instance.getName(); default: String property = mColumnNames[columnIndex]; String result = instance.getAttributeValue(property); return (result == null) ? "" : result; } } return ""; } } /** * Constructs a new <code>NewTypesafeEnumCreationWizardPageInstances</code>. */ public NewTypesafeEnumCreationWizardPageInstances() { super(PAGE_NAME); setTitle(WizardMessages.getString("NewEnumWizPageInst.title")); //$NON-NLS-1$ setDescription(WizardMessages.getString("NewEnumWizPageInst.description")); //$NON-NLS-1$ } /* * (non-Javadoc) * * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ public void createControl(Composite parent) { initializeDialogUnits(parent); Composite container = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; container.setLayout(layout); container.setLayoutData(new GridData(GridData.FILL_BOTH)); createTableWidget(container); createButtonsPanel(container); hookListeners(); updateEnabledState(); mButtonAdd.forceFocus(); setControl(container); Dialog.applyDialogFont(container); setPageComplete(false); } /** * Registers listeners with the widgets. */ private void hookListeners() { mTableViewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { if (mIgnoreCheckEvents) { return; } Object element = event.getElement(); if (element instanceof TableItem) { // workaround for bug in older versions of Eclipse element = ((TableItem)element).getData(); } if (element instanceof Instance) { Instance instance = (Instance)element; if (event.getChecked()) { instance.setDefault(); } else { instance.getType().setDefaultInstance(null); } syncTableCheckWithModel(); validatePage(); } } }); mTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { updateEnabledState(); } }); mTableViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { handleEditPressed(); } }); mButtonAdd.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleAddPressed(); } }); mButtonEdit.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleEditPressed(); } }); mButtonRemove.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleRemovePressed(); } }); } private void syncTableCheckWithModel() { mIgnoreCheckEvents = true; for (Iterator<Instance> i = getTypesafeEnumModel().instances(); i.hasNext();) { Instance inst = i.next(); mTableViewer.setChecked(inst, inst.isDefault()); } mIgnoreCheckEvents = false; } private void updateEnabledState() { mTableWidget.setEnabled(mTableWidget.getItemCount() > 0); boolean enabled = (mTableWidget.getSelectionCount() > 0); mButtonEdit.setEnabled(enabled); mButtonRemove.setEnabled(enabled); } private void handleAddPressed() { EditInstanceDialog dialog = new EditInstanceDialog(getShell()); Instance instance = new Instance(); getTypesafeEnumModel().addInstance(instance); // or cannot setDefault... dialog.setInstance(instance); dialog.setAttributes(getTypesafeEnumModel().attributeArray()); dialog.setTitle(WizardMessages.getString("NewEnumWizPageInst.Add_Instance")); int reply = dialog.open(); if (reply == Window.OK) { mTableViewer.refresh(); mTableViewer.setSelection(new StructuredSelection(dialog.getInstance())); syncTableCheckWithModel(); } else { getTypesafeEnumModel().removeInstance(dialog.getInstance()); mTableViewer.refresh(); } updateEnabledState(); validatePage(); mButtonAdd.forceFocus(); } private void handleEditPressed() { Instance instance = getSelectedInstance(); if (instance == null) { return; } EditInstanceDialog dialog = new EditInstanceDialog(getShell()); dialog.setInstance(instance); dialog.setAttributes(getTypesafeEnumModel().attributeArray()); dialog.setTitle(WizardMessages.getString("NewEnumWizPageInst.Edit_Instance")); dialog.open(); mTableViewer.refresh(); mTableViewer.setSelection(new StructuredSelection(dialog.getInstance())); syncTableCheckWithModel(); updateEnabledState(); validatePage(); } private void handleRemovePressed() { Instance instance = getSelectedInstance(); if (instance == null) { return; } getTypesafeEnumModel().removeInstance(instance); mTableViewer.refresh(); updateEnabledState(); validatePage(); } private Instance getSelectedInstance() { IStructuredSelection selection = (IStructuredSelection)mTableViewer.getSelection(); if (selection.isEmpty()) { return null; } Object element = selection.getFirstElement(); if (element instanceof TableItem) { // workaround for bug in older versions of Eclipse element = ((TableItem)element).getData(); } Instance result = (Instance)element; return result; } /** * Create the button panel. */ private void createButtonsPanel(Composite parent) { Composite panel = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 3; panel.setLayout(layout); mButtonAdd = new Button(panel, SWT.PUSH); mButtonEdit = new Button(panel, SWT.PUSH); mButtonRemove = new Button(panel, SWT.PUSH); mButtonAdd.setText(WizardMessages.getString("NewEnumWizPageAttr.button.Add")); mButtonEdit.setText(WizardMessages.getString("NewEnumWizPageAttr.button.Edit")); mButtonRemove.setText(WizardMessages.getString("NewEnumWizPageAttr.button.Remove")); } /** * Create the table widget. */ private void createTableWidget(Composite container) { mTableWidget = new Table(container, SWT.CHECK | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); mTableWidget.setHeaderVisible(true); mTableWidget.setLinesVisible(true); initTableLayoutData(TABLE_ROWS); initTableColumns(); mTableWidget.pack(); mTableViewer = new CheckboxTableViewer(mTableWidget); mTableViewer.setColumnProperties(mColumnNames); // must be same as // TableColumn text mTableViewer.setLabelProvider(new InstanceLabelProvider()); mTableViewer.setContentProvider(new InstanceContentProvider()); mTableViewer.setInput(getTypesafeEnumModel()); } /** * Recalculate the table height needed for the specified number of rows. */ private void initTableLayoutData(int rows) { int listHeight = mTableWidget.getItemHeight() * rows; Rectangle trim = mTableWidget.computeTrim(0, 0, 0, listHeight); GridData tblGD = new GridData(GridData.FILL_BOTH); tblGD.heightHint = trim.height; tblGD.horizontalSpan = 2; // use both columns of grid mTableWidget.setLayoutData(tblGD); } private void initTableColumns() { TableColumn[] existing = mTableWidget.getColumns(); // erase existing table column headers for (int i = 0; i < existing.length; i++) { existing[i].setText(""); } // add table columns if necessary for (int i = existing.length; i < mColumnNames.length; i++) { new TableColumn(mTableWidget, SWT.NONE); } // set table column headers for (int i = 0; i < mColumnNames.length; i++) { TableColumn column = mTableWidget.getColumn(i); column.setText(mColumnNames[i]); } // set table column widths TableLayout tableLayout = new TableLayout(); for (int i = 0; i < mColumnWidths.length; i++) { tableLayout.addColumnData(new ColumnWeightData(1, mColumnWidths[i], true)); } mTableWidget.setLayout(tableLayout); } /** * Validates the attributes of the <code>TypesafeEnum</code>. */ /* package */void validatePage() { TypesafeEnum type = getTypesafeEnumModel(); if (type.instanceCount() == 0) { setErrorMessage(WizardMessages.getString("NewEnumWizPageInst.Must_have_at_least_one_instance")); setPageComplete(false); return; } for (Iterator<Instance> i = type.instances(); i.hasNext();) { Instance instance = i.next(); if (instance.getName().length() == 0) { setErrorMessage(WizardMessages.getString("NewEnumWizPageInst.Every_instance_must_have_a_name")); setPageComplete(false); return; } if (!NameUtil.isValidIdentifier(instance.getName())) { setErrorMessage(WizardMessages.getFormattedString("NewEnumWizPageInst.invalid_instance_name", instance.getName())); setPageComplete(false); return; } for (Iterator<Attribute> attributes = type.attributes(); attributes.hasNext();) { Attribute attribute = attributes.next(); String value = instance.getAttributeValue(attribute); if (value == null || value.trim().length() == 0) { setErrorMessage(WizardMessages.getFormattedString( "NewEnumWizPageInst.Instance_does_not_have_a_value_for_attribute", new String []{ instance.getName(), attribute.getName() })); setPageComplete(false); return; } } } setErrorMessage(null); setPageComplete(true); } /* * Attributes may have changed. Re-initialize the table widget. */ @Override public void setVisible(boolean visible) { if (visible) { mapAttributesToTableModel(); mTableViewer.setInput(getTypesafeEnumModel()); getControl().pack(true); // redo layout mTableViewer.refresh(); } super.setVisible(visible); } /** * Re-initializes the member variables containing the column names, column * widths, and finally re-initializes the table widget. */ private void mapAttributesToTableModel() { reinitColumnNames(); reinitColumnWidths(); initTableLayoutData(TABLE_ROWS); initTableColumns(); } private void reinitColumnNames() { mColumnNames = new String [2 + getTypesafeEnumModel().attributeCount()]; //System.out.println("Init Column names, length = " + mColumnNames.length); int col = 0; mColumnNames[col++] = WizardMessages.getString("NewEnumWizPageInst.col.Default"); mColumnNames[col++] = WizardMessages.getString("NewEnumWizPageInst.col.Name"); for (Iterator<Attribute> i = getTypesafeEnumModel().attributes(); i.hasNext();) { Attribute attribute = i.next(); mColumnNames[col++] = attribute.getName(); //System.out.println("colname[" + (col-1) + "] = " + // attribute.getName()); } } private void reinitColumnWidths() { mColumnWidths = new int [2 + getTypesafeEnumModel().attributeCount()]; //System.out.println("Init Column widths, length = " + // mColumnWidths.length); mColumnWidths[0] = 30; mColumnWidths[1] = 120; for (int i = 2; i < mColumnWidths.length; i++) { mColumnWidths[i] = 250 / (mColumnWidths.length - 2); //System.out.println("colwidth[" + i + "] = " + mColumnWidths[i]); } } /** * Returns the <code>TypesafeEnum</code> to edit. * * @return the <code>TypesafeEnum</code> to edit */ public TypesafeEnum getTypesafeEnumModel() { return ((NewTypesafeEnumCreationWizardPageAttributes)getPreviousPage()).getTypesafeEnumModel(); } }