Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/widgets/AddRemoveListPane.java')
-rw-r--r--jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/widgets/AddRemoveListPane.java554
1 files changed, 554 insertions, 0 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/widgets/AddRemoveListPane.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/widgets/AddRemoveListPane.java
new file mode 100644
index 0000000000..89069c5d58
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/widgets/AddRemoveListPane.java
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Oracle. 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.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.ui.internal.widgets;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jpt.ui.internal.listeners.SWTPropertyChangeListenerWrapper;
+import org.eclipse.jpt.ui.internal.swt.ColumnAdapter;
+import org.eclipse.jpt.ui.internal.swt.TableModelAdapter;
+import org.eclipse.jpt.ui.internal.swt.TableModelAdapter.SelectionChangeEvent;
+import org.eclipse.jpt.ui.internal.swt.TableModelAdapter.SelectionChangeListener;
+import org.eclipse.jpt.ui.internal.util.SWTUtil;
+import org.eclipse.jpt.utility.internal.model.value.SimplePropertyValueModel;
+import org.eclipse.jpt.utility.internal.model.value.swing.ObjectListSelectionModel;
+import org.eclipse.jpt.utility.model.Model;
+import org.eclipse.jpt.utility.model.event.ListAddEvent;
+import org.eclipse.jpt.utility.model.event.ListChangeEvent;
+import org.eclipse.jpt.utility.model.event.ListClearEvent;
+import org.eclipse.jpt.utility.model.event.ListMoveEvent;
+import org.eclipse.jpt.utility.model.event.ListRemoveEvent;
+import org.eclipse.jpt.utility.model.event.ListReplaceEvent;
+import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
+import org.eclipse.jpt.utility.model.listener.PropertyChangeListener;
+import org.eclipse.jpt.utility.model.value.ListValueModel;
+import org.eclipse.jpt.utility.model.value.PropertyValueModel;
+import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel;
+import org.eclipse.swt.SWT;
+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.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * This implementation of the <code>AddRemovePane</code> uses a <code>Table</code>
+ * as its main widget, a <code>List</code> can't be used because it doesn't
+ * support showing images. However, the table is displayed like a list.
+ * <p>
+ * Here the layot of this pane:
+ * <pre>
+ * -----------------------------------------------------------------------------
+ * | ------------------------------------------------------------- ----------- |
+ * | | Item 1 | | Add... | |
+ * | | ... | ----------- |
+ * | | Item n | ----------- |
+ * | | | | Edit... | |
+ * | | | ----------- |
+ * | | | ----------- |
+ * | | | | Remove | |
+ * | | | ----------- |
+ * | ------------------------------------------------------------- |
+ * -----------------------------------------------------------------------------</pre>
+ *
+ * @version 2.0
+ * @since 1.0
+ */
+@SuppressWarnings("nls")
+public class AddRemoveListPane<T extends Model> extends AddRemovePane<T>
+{
+
+ /**
+ * The main widget of this add/remove pane.
+ */
+ private Table table;
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param parent The parent container
+ * @param adapter
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ */
+ public AddRemoveListPane(Pane<? extends T> parentPane,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider) {
+
+ super(parentPane,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider);
+ }
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param parent The parent container
+ * @param adapter
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ * @param helpId The topic help ID to be registered with this pane
+ */
+ public AddRemoveListPane(Pane<? extends T> parentPane,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider,
+ String helpId) {
+
+ super(parentPane,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ helpId);
+ }
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param parent The parent container
+ * @param adapter
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ * @param helpId The topic help ID to be registered with this pane
+ * @param parentManagePane <code>true</code> to have the parent pane manage
+ * the enabled state of this pane
+ */
+ public AddRemoveListPane(Pane<? extends T> parentPane,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider,
+ String helpId,
+ boolean parentManagePane) {
+
+ super(parentPane,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ helpId,
+ parentManagePane);
+ }
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param subjectHolder The holder of the subject
+ * @param adapter
+ * @param parent The parent container
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ */
+ public AddRemoveListPane(Pane<?> parentPane,
+ PropertyValueModel<? extends T> subjectHolder,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider) {
+
+ super(parentPane,
+ subjectHolder,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider);
+ }
+
+ /**
+ * Creates a new <code>AddRemoveListPane</code>.
+ *
+ * @param parentPane The parent container of this one
+ * @param subjectHolder The holder of the subject
+ * @param adapter
+ * @param parent The parent container
+ * @param listHolder The <code>ListValueModel</code> containing the items
+ * @param selectedItemHolder The holder of the selected item, if more than
+ * one item or no items are selected, then <code>null</code> will be passed
+ * @param labelProvider The renderer used to format the table holder's items
+ * @param helpId The topic help ID to be registered with this pane
+ */
+ public AddRemoveListPane(Pane<?> parentPane,
+ PropertyValueModel<? extends T> subjectHolder,
+ Composite parent,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ ILabelProvider labelProvider,
+ String helpId) {
+
+ super(parentPane,
+ subjectHolder,
+ parent,
+ adapter,
+ listHolder,
+ selectedItemHolder,
+ labelProvider,
+ helpId);
+ }
+
+ private ColumnAdapter<Object> buildColumnAdapter() {
+ return new ColumnAdapter<Object>() {
+ public WritablePropertyValueModel<?>[] cellModels(Object subject) {
+ WritablePropertyValueModel<?>[] valueHolders = new WritablePropertyValueModel<?>[1];
+ valueHolders[0] = new SimplePropertyValueModel<Object>(subject);
+ return valueHolders;
+ }
+
+ public int columnCount() {
+ return 1;
+ }
+
+ public String columnName(int columnIndex) {
+ return "";
+ }
+ };
+ }
+
+ @Override
+ protected void itemsAdded(ListAddEvent e) {
+ super.itemsAdded(e);
+ revalidateLayout();
+ }
+
+ @Override
+ protected void itemsMoved(ListMoveEvent e) {
+ super.itemsMoved(e);
+ revalidateLayout();
+ }
+
+ @Override
+ protected void itemsRemoved(ListRemoveEvent e) {
+ super.itemsRemoved(e);
+ revalidateLayout();
+ }
+
+ @Override
+ protected void itemsReplaced(ListReplaceEvent e) {
+ super.itemsReplaced(e);
+ revalidateLayout();
+ }
+
+ @Override
+ protected void listChanged(ListChangeEvent e) {
+ super.listChanged(e);
+ revalidateLayout();
+ }
+
+ @Override
+ protected void listCleared(ListClearEvent e) {
+ super.listCleared(e);
+ revalidateLayout();
+ }
+
+ /**
+ * Revalidates the table layout after the list of items has changed. The
+ * layout has to be done in a new UI thread because our listener might be
+ * notified before the table has been updated (table column added or removed).
+ */
+ private void revalidateLayout() {
+ SWTUtil.asyncExec(new Runnable() { public void run() {
+ if (!table.isDisposed()) {
+ table.getParent().computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ table.getParent().layout();
+ }
+ }});
+ }
+
+ private PropertyChangeListener buildSelectedItemPropertyChangeListener() {
+ return new SWTPropertyChangeListenerWrapper(
+ buildSelectedItemPropertyChangeListener_()
+ );
+ }
+
+ private PropertyChangeListener buildSelectedItemPropertyChangeListener_() {
+ return new PropertyChangeListener() {
+ public void propertyChanged(PropertyChangeEvent e) {
+ if (table.isDisposed()) {
+ return;
+ }
+ getSelectionModel().setSelectedValue(e.getNewValue());
+ updateButtons();
+ }
+ };
+ }
+
+ private SelectionChangeListener<Object> buildSelectionListener() {
+ return new SelectionChangeListener<Object>() {
+ public void selectionChanged(SelectionChangeEvent<Object> e) {
+ AddRemoveListPane.this.selectionChanged();
+ }
+ };
+ }
+
+ private Composite addTableContainer(Composite container) {
+
+ container = addPane(container, buildTableContainerLayout());
+ container.setLayoutData(new GridData(GridData.FILL_BOTH));
+ return container;
+ }
+
+ private Layout buildTableContainerLayout() {
+ return new Layout() {
+ @Override
+ protected Point computeSize(Composite composite,
+ int widthHint,
+ int heightHint,
+ boolean flushCache) {
+
+ Table table = (Table) composite.getChildren()[0];
+ TableColumn tableColumn = table.getColumn(0);
+ int columnWidth = tableColumn.getWidth();
+ packColumn(table);
+
+ // Calculate the table size and adjust it with the hints
+ Point size = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+
+ if (widthHint != SWT.DEFAULT) {
+ size.x = widthHint;
+ }
+
+ if (heightHint != SWT.DEFAULT) {
+ size.y = heightHint;
+ }
+
+ // Revert the column's width to its current value
+ table.setRedraw(false);
+ table.setLayoutDeferred(true);
+ tableColumn.setWidth(columnWidth);
+ table.setLayoutDeferred(false);
+ table.setRedraw(true);
+
+ return size;
+ }
+
+ private boolean isVerticalScrollbarBarVisible(Table table,
+ Rectangle clientArea) {
+
+ // Get the height of all the rows
+ int height = table.getItemCount() * table.getItemHeight();
+
+ // Remove the border from the height
+ height += (table.getBorderWidth() * 2);
+
+ return (clientArea.height < height);
+ }
+
+ @Override
+ protected void layout(Composite composite, boolean flushCache) {
+
+ Rectangle bounds = composite.getClientArea();
+
+ if (bounds.width > 0) {
+
+ Table table = (Table) composite.getChildren()[0];
+ table.setBounds(0, 0, bounds.width, bounds.height);
+
+ updateTableColumnWidth(
+ table,
+ bounds.width,
+ isVerticalScrollbarBarVisible(table, bounds)
+ );
+ }
+ }
+
+ private void packColumn(Table table) {
+
+ TableColumn tableColumn = table.getColumn(0);
+
+ table.setRedraw(false);
+ table.setLayoutDeferred(true);
+ tableColumn.pack();
+ table.setLayoutDeferred(false);
+ table.setRedraw(true);
+
+ // Cache the column width so it can be used in
+ // updateTableColumnWidth() when determine which width to use
+ table.setData(
+ "column.width",
+ Integer.valueOf(tableColumn.getWidth())
+ );
+ }
+
+ private void updateTableColumnWidth(Table table,
+ int width,
+ boolean verticalScrollbarBarVisible) {
+
+ // Remove the border from the width
+ width -= (table.getBorderWidth() * 2);
+
+ // Remove the scrollbar from the width if it is shown
+ if (verticalScrollbarBarVisible) {
+ width -= table.getVerticalBar().getSize().x;
+ }
+
+ TableColumn tableColumn = table.getColumn(0);
+
+ // Retrieve the cached column width, which is required for
+ // determining which width to use (the column width or the
+ // calculated width)
+ Integer columnWitdh = (Integer) table.getData("column.width");
+
+ // Use the calculated width if the column is smaller, otherwise
+ // use the column width and a horizontal scroll bar will show up
+ width = Math.max(width, columnWitdh);
+
+ // Adjust the column width
+ tableColumn.setWidth(width);
+ }
+ };
+ }
+
+ private ITableLabelProvider buildTableLabelProvider(IBaseLabelProvider labelProvider) {
+ return new TableLabelProvider((ILabelProvider) labelProvider);
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ public Table getMainControl() {
+ return table;
+ }
+
+ /*
+ * (non-Javadoc)
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void initializeMainComposite(Composite container,
+ Adapter adapter,
+ ListValueModel<?> listHolder,
+ WritablePropertyValueModel<?> selectedItemHolder,
+ IBaseLabelProvider labelProvider,
+ String helpId) {
+
+ table = addUnmanagedTable(
+ addTableContainer(container),
+ SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI,
+ helpId
+ );
+
+
+ TableModelAdapter model = TableModelAdapter.adapt(
+ (ListValueModel<Object>) listHolder,
+ getSelectedItemHolder(),
+ table,
+ buildColumnAdapter(),
+ buildTableLabelProvider(labelProvider)
+ );
+
+ model.addSelectionChangeListener(buildSelectionListener());
+
+ selectedItemHolder.addPropertyChangeListener(
+ PropertyValueModel.VALUE,
+ buildSelectedItemPropertyChangeListener()
+ );
+
+ initializeTable(table);
+ }
+
+ /**
+ * Initializes the given table, which acts like a list in our case.
+ *
+ * @param table The main widget of this pane
+ */
+ protected void initializeTable(Table table) {
+
+ table.setData("column.width", new Integer(0));
+ table.setHeaderVisible(false);
+ table.setLinesVisible(false);
+ }
+
+ /**
+ * The selection has changed, update (1) the selected item holder, (2) the
+ * selection model and (3) the buttons.
+ */
+ private void selectionChanged() {
+ WritablePropertyValueModel<Object> selectedItemHolder = getSelectedItemHolder();
+ ObjectListSelectionModel selectionModel = getSelectionModel();
+ int selectionCount = this.table.getSelectionCount();
+
+ if (selectionCount == 0) {
+ selectedItemHolder.setValue(null);
+ selectionModel.clearSelection();
+ }
+ else if (selectionCount != 1) {
+ selectedItemHolder.setValue(null);
+ selectionModel.clearSelection();
+
+ for (int index : this.table.getSelectionIndices()) {
+ selectionModel.addSelectionInterval(index, index);
+ }
+ }
+ else {
+ int selectedIndex = this.table.getSelectionIndex();
+ Object selectedItem = getListHolder().get(selectedIndex);
+
+ selectedItemHolder.setValue(selectedItem);
+ selectionModel.setSelectedValue(selectedItem);
+ }
+
+ updateButtons();
+ }
+
+ /**
+ * This label provider simply delegates the rendering to the provided
+ * <code>ILabelProvider</code>.
+ */
+ private class TableLabelProvider extends LabelProvider
+ implements ITableLabelProvider {
+
+ private ILabelProvider labelProvider;
+
+ TableLabelProvider(ILabelProvider labelProvider) {
+ super();
+ this.labelProvider = labelProvider;
+ }
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return labelProvider.getImage(element);
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ return labelProvider.getText(element);
+ }
+ }
+} \ No newline at end of file

Back to the top