/******************************************************************************* * Copyright (c) 2006-2013, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text of * such license is available at www.eclipse.org. ******************************************************************************/ package org.eclipse.buckminster.ui.general.editor.structured; import org.eclipse.buckminster.ui.Messages; import org.eclipse.buckminster.ui.UiUtils; import org.eclipse.buckminster.ui.general.editor.ValidatorException; import org.eclipse.buckminster.ui.internal.DynamicTableLayout; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; 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.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; 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.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; /** * @author Karel Brezina * */ public abstract class StructuredTableEditor<T> extends Composite { class TableContentProvider implements IStructuredContentProvider { @Override public void dispose() { // Nothing to dispose } @Override public Object[] getElements(Object inputElement) { return table.getRows().toArray(); } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // Nothing to do } } class TableLabelProvider extends LabelProvider implements ITableLabelProvider { @Override public Image getColumnImage(Object element, int columnIndex) { return null; } @Override @SuppressWarnings("unchecked") public String getColumnText(Object element, int columnIndex) { Object field = table.getTableViewerField((T) element, columnIndex); return field == null ? "" //$NON-NLS-1$ : field.toString(); } } private final static int DONT_SAVE = -99; private final IStructuredTable<T> table; private final boolean swapButtonsFlag; private TableViewer tableViewer; private int lastSelectedRow = -1; private int lastEditedRow = -1; private Composite stackButtonComposite; private StackLayout stackButtonLayout; private Composite editButtonBox; private Composite viewButtonBox; private Button newButton; private Button editButton; private Button viewButton; private Button removeButton; private Button moveUpButton; private Button moveDownButton; private Tree stackOptions; private StackLayout stackLayout; private Composite stackComposite; private boolean enabled = true; public StructuredTableEditor(Composite parent, IStructuredTable<T> table, boolean swapButtonsFlag, int style) { super(parent, style); this.table = table; this.swapButtonsFlag = swapButtonsFlag; initComposite(); } @Override public boolean isEnabled() { return enabled; } public abstract void refresh(); public boolean selectRow(T row) { int idx = table.getRows().indexOf(row); if (idx == -1) return false; tableViewer.getTable().setSelection(idx); updateLastRow(); return true; } @Override public void setEnabled(boolean enabled) { this.enabled = enabled; enableDisableButtonGroup(); } protected void createStack(Composite parent) { stackComposite = new Composite(parent, SWT.NONE); stackComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); stackLayout = new StackLayout(); stackLayout.marginHeight = stackLayout.marginWidth = 0; stackComposite.setLayout(stackLayout); table.fillStackComposite(stackComposite); } protected void createStackOptions(Composite parent) { stackOptions = new Tree(parent, SWT.BORDER); stackOptions.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true)); stackOptions.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (e.item != null) { TreeItem item = (TreeItem) e.item; stackLayout.topControl = table.getStackControl(item.getText()); stackComposite.layout(); focusStackComposite(); } } }); } protected void createTableButtons(Composite parent) { stackButtonComposite = new Composite(parent, SWT.NONE); stackButtonComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); stackButtonLayout = new StackLayout(); stackButtonLayout.marginHeight = stackButtonLayout.marginWidth = 0; stackButtonComposite.setLayout(stackButtonLayout); editButtonBox = new Composite(stackButtonComposite, SWT.NONE); GridLayout gridLayout = new GridLayout(1, false); gridLayout.marginHeight = gridLayout.marginWidth = gridLayout.verticalSpacing = 0; editButtonBox.setLayout(gridLayout); editButtonBox.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); newButton = UiUtils.createPushButton(editButtonBox, Messages.new_label, new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { newRow(); } }); newButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); editButton = UiUtils.createPushButton(editButtonBox, Messages.edit, new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { editRow(false, false); } }); editButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); removeButton = UiUtils.createPushButton(editButtonBox, Messages.remove, new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { removeRow(); } }); removeButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); if (swapButtonsFlag) { moveUpButton = UiUtils.createPushButton(editButtonBox, Messages.move_up, new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { swapAndReselect(0, -1); } }); moveUpButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); moveDownButton = UiUtils.createPushButton(editButtonBox, Messages.move_down, new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { swapAndReselect(1, 0); } }); moveDownButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); } viewButtonBox = new Composite(stackButtonComposite, SWT.NONE); gridLayout = new GridLayout(1, false); gridLayout.marginHeight = gridLayout.marginWidth = 0; viewButtonBox.setLayout(gridLayout); viewButtonBox.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false)); viewButton = UiUtils.createPushButton(viewButtonBox, Messages.view, new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { editRow(false, true); } }); viewButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); } protected void createTableGroup(Composite parent) { Composite componentTableGroup = createTableGroupComposite(parent); Table tbl = new Table(componentTableGroup, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); // table.setHeaderVisible(false); tbl.setHeaderVisible(true); DynamicTableLayout layout = new DynamicTableLayout(50); int tableIdx = 0; for (int idx = 0; idx < table.getTableViewerColumns(); idx++) { if (table.getTableViewerColumnWeights()[idx] > 0) { TableColumn tableColumn = new TableColumn(tbl, SWT.LEFT, tableIdx); tableColumn.setText(table.getTableViewerColumnHeaders()[idx]); layout.addColumnData(new ColumnWeightData(table.getTableViewerColumnWeights()[idx], true)); tableIdx++; } } tbl.setLayout(layout); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); // gridData.widthHint = 600; tbl.setLayoutData(gridData); tableViewer = new TableViewer(tbl); tableViewer.setLabelProvider(new TableLabelProvider()); tableViewer.setContentProvider(new TableContentProvider()); tableViewer.setInput(table); tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { rowSelection(); } }); tableViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { if (tableViewer.getTable().getSelectionIndex() >= 0) editRow(false, !enabled || table.isReadOnly()); } }); createTableButtons(componentTableGroup); } protected abstract Composite createTableGroupComposite(Composite parent); protected abstract void editRow(boolean newRow, boolean readOnly); protected void enableDisableButtonGroup() { Table tbl = getTableViewer().getTable(); int top = tbl.getItemCount(); int idx = getSelectionIndex(); if (isEnabled() && !table.isReadOnly()) { newButton.setEnabled(true); editButton.setEnabled(idx >= 0); removeButton.setEnabled(idx >= 0); if (isSwapButtonAllowed()) { moveUpButton.setEnabled(idx > 0); moveDownButton.setEnabled(idx >= 0 && idx < top - 1); } stackButtonLayout.topControl = editButtonBox; } else { newButton.setEnabled(false); editButton.setEnabled(false); removeButton.setEnabled(false); if (isSwapButtonAllowed()) { moveUpButton.setEnabled(false); moveDownButton.setEnabled(false); } stackButtonLayout.topControl = viewButtonBox; } viewButton.setEnabled(idx >= 0); stackButtonComposite.layout(); } protected void enableFields(boolean flag) { table.enableFields(flag); } protected void fillStackOptions() { for (String stackKey : table.getStackKeys()) { TreeItem item = new TreeItem(stackOptions, SWT.NONE); item.setText(stackKey); } } protected void focusStackComposite() { Control focusControl = (Control) stackLayout.topControl.getData("focusControl"); //$NON-NLS-1$ if (focusControl != null) { focusControl.setFocus(); } } protected Button getEditButton() { return editButton; } protected int getLastEditedRow() { return lastEditedRow; } protected int getLastSelectedRow() { return lastSelectedRow; } protected Button getMoveDownButton() { return moveDownButton; } protected Button getMoveUpButton() { return moveUpButton; } protected Button getNewButton() { return newButton; } protected Button getRemoveButton() { return removeButton; } protected int getSelectionIndex() { return tableViewer.getTable().getSelectionIndex(); } protected IStructuredTable<T> getTable() { return table; } protected TableViewer getTableViewer() { return tableViewer; } protected Button getViewButton() { return viewButton; } protected abstract void initComposite(); protected boolean isSwapButtonAllowed() { return swapButtonsFlag; } protected abstract void newRow(); protected void refreshRow() { table.refreshRow(getSelectionIndex()); if (stackOptions.getSelectionCount() == 0) { setStackOption(0); } } protected void refreshTable() { table.refresh(); tableViewer.setInput(table); if (getSelectionIndex() == -1 && table.getRows().size() > 0) { if (lastSelectedRow == -1) { tableViewer.getTable().setSelection(0); } else { if (lastSelectedRow >= table.getRows().size()) { lastSelectedRow = table.getRows().size() - 1; } tableViewer.getTable().setSelection(lastSelectedRow); } } updateLastRow(); } protected void removeRow() { int row = getSelectionIndex(); if (row != -1) { table.removeRow(row); lastEditedRow = DONT_SAVE; refresh(); } } protected abstract boolean rowSelectionEvent(); protected void saveRow() throws ValidatorException { if (lastEditedRow == DONT_SAVE) return; table.save(lastEditedRow); refresh(); enableDisableButtonGroup(); } protected void setEditButton(Button editButton) { this.editButton = editButton; } protected void setMoveDownButton(Button moveDownButton) { this.moveDownButton = moveDownButton; } protected void setMoveUpButton(Button moveUpButton) { this.moveUpButton = moveUpButton; } protected void setNewButton(Button newButton) { this.newButton = newButton; } protected void setRemoveButton(Button removeButton) { this.removeButton = removeButton; } protected void setStackOption(int idx) { String stackKey = table.getStackKeys().get(idx); stackOptions.setSelection(stackOptions.getItem(idx)); stackLayout.topControl = table.getStackControl(stackKey); stackComposite.layout(); } protected void setViewButton(Button viewButton) { this.viewButton = viewButton; } protected void swapAndReselect(int idxOffset, int selectionOffset) { if (table.swapRows(getSelectionIndex(), idxOffset)) { refresh(); Table tbl = tableViewer.getTable(); int idx = tbl.getSelectionIndex() + idxOffset; tbl.select(idx + selectionOffset); enableDisableButtonGroup(); } } protected void updateLastRow() { if (getSelectionIndex() != -1) { lastSelectedRow = getSelectionIndex(); } lastEditedRow = getSelectionIndex(); } private void rowSelection() { if (rowSelectionEvent()) updateLastRow(); } }