summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Drossel2009-03-27 11:11:26 (EDT)
committerCarsten Drossel2009-03-27 11:11:26 (EDT)
commit8eb7389900b7dd6a6d3331e7ffaf185907b59428 (patch)
tree136c434ffc3e2e49291b776178e0008dd7db9e76
parent44d07fa9655d78864e462fcf7ecd3cb899ab98cf (diff)
downloadorg.eclipse.riena-8eb7389900b7dd6a6d3331e7ffaf185907b59428.zip
org.eclipse.riena-8eb7389900b7dd6a6d3331e7ffaf185907b59428.tar.gz
org.eclipse.riena-8eb7389900b7dd6a6d3331e7ffaf185907b59428.tar.bz2
extracted superclass AbstractListRidget and moved it to an exported package to allow its reuse for custom ridgets. Also moved SortableComparator to exported package
-rw-r--r--org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/CompositeTableRidget.java1
-rw-r--r--org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/ListRidget.java390
-rw-r--r--org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableComparator.java2
-rw-r--r--org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableRidget.java1
-rw-r--r--org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TreeTableRidget.java2
-rw-r--r--org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/ui/ridgets/swt/AbstractListRidget.java407
-rw-r--r--org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/ui/ridgets/swt/SortableComparator.java (renamed from org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/SortableComparator.java)12
7 files changed, 453 insertions, 362 deletions
diff --git a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/CompositeTableRidget.java b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/CompositeTableRidget.java
index c8b7dbf..a18b58a 100644
--- a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/CompositeTableRidget.java
+++ b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/CompositeTableRidget.java
@@ -54,6 +54,7 @@ import org.eclipse.riena.ui.ridgets.IRowRidget;
import org.eclipse.riena.ui.ridgets.databinding.IUnboundPropertyObservable;
import org.eclipse.riena.ui.ridgets.databinding.UnboundPropertyWritableList;
import org.eclipse.riena.ui.ridgets.swt.AbstractSWTRidget;
+import org.eclipse.riena.ui.ridgets.swt.SortableComparator;
import org.eclipse.riena.ui.ridgets.swt.uibinding.SwtControlRidgetMapper;
import org.eclipse.riena.ui.ridgets.uibinding.IBindingPropertyLocator;
import org.eclipse.riena.ui.ridgets.uibinding.IControlRidgetMapper;
diff --git a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/ListRidget.java b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/ListRidget.java
index 80bc73f..7e436af 100644
--- a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/ListRidget.java
+++ b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/ListRidget.java
@@ -10,110 +10,30 @@
*******************************************************************************/
package org.eclipse.riena.internal.ui.ridgets.swt;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.Comparator;
-
-import org.eclipse.core.databinding.Binding;
-import org.eclipse.core.databinding.DataBindingContext;
-import org.eclipse.core.databinding.UpdateListStrategy;
-import org.eclipse.core.databinding.UpdateValueStrategy;
-import org.eclipse.core.databinding.beans.BeansObservables;
-import org.eclipse.core.databinding.observable.list.IListChangeListener;
-import org.eclipse.core.databinding.observable.list.IObservableList;
-import org.eclipse.core.databinding.observable.list.ListChangeEvent;
-import org.eclipse.core.databinding.observable.map.IObservableMap;
-import org.eclipse.core.databinding.observable.value.IObservableValue;
-import org.eclipse.core.databinding.observable.value.IValueChangeListener;
-import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
-import org.eclipse.core.runtime.Assert;
-import org.eclipse.jface.databinding.viewers.IViewerObservableList;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
-import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
-import org.eclipse.jface.databinding.viewers.ViewersObservables;
+import org.eclipse.jface.viewers.AbstractListViewer;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.ViewerComparator;
-import org.eclipse.riena.core.util.ListenerList;
-import org.eclipse.riena.ui.common.ISortableByColumn;
-import org.eclipse.riena.ui.ridgets.IActionListener;
-import org.eclipse.riena.ui.ridgets.IColumnFormatter;
-import org.eclipse.riena.ui.ridgets.IMarkableRidget;
-import org.eclipse.riena.ui.ridgets.ISelectableRidget;
-import org.eclipse.riena.ui.ridgets.ITableRidget;
-import org.eclipse.riena.ui.ridgets.databinding.IUnboundPropertyObservable;
-import org.eclipse.riena.ui.ridgets.databinding.UnboundPropertyWritableList;
-import org.eclipse.riena.ui.ridgets.swt.AbstractSWTRidget;
-
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.List;
+import org.eclipse.riena.ui.ridgets.ISelectableRidget;
+import org.eclipse.riena.ui.ridgets.swt.AbstractListRidget;
+import org.eclipse.riena.ui.ridgets.swt.AbstractSWTRidget;
+
/**
* Ridget for SWT {@link List} widgets.
*/
-public class ListRidget extends AbstractSelectableIndexedRidget implements ITableRidget {
-
- private final SelectionListener selectionTypeEnforcer;
- private final MouseListener doubleClickForwarder;
- private ListenerList<IActionListener> doubleClickListeners;
-
- private DataBindingContext dbc;
- private Binding viewerSSB;
- /*
- * Binds the viewer's multiple selection to the multiple selection
- * observable. This binding hsa to be disposed when the ridget is set to
- * output-only, to avoid updating the model. It has to be recreated when the
- * ridget is set to not-output-only.
- */
- private Binding viewerMSB;
+public class ListRidget extends AbstractListRidget {
private ListViewer viewer;
- private Class<?> rowBeanClass;
- private IObservableList rowObservables;
- private String renderingMethod;
-
- private boolean isSortedAscending;
- private int sortedColumn;
- private ViewerComparator comparator;
public ListRidget() {
selectionTypeEnforcer = new SelectionTypeEnforcer();
- doubleClickForwarder = new DoubleClickForwarder();
- isSortedAscending = true;
- sortedColumn = -1;
- getSingleSelectionObservable().addValueChangeListener(new IValueChangeListener() {
- public void handleValueChange(ValueChangeEvent event) {
- disableMandatoryMarkers(hasInput());
- }
- });
- getMultiSelectionObservable().addListChangeListener(new IListChangeListener() {
- public void handleListChange(ListChangeEvent event) {
- disableMandatoryMarkers(hasInput());
- }
- });
- addPropertyChangeListener(IMarkableRidget.PROPERTY_ENABLED, new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent evt) {
- boolean isEnabled = ((Boolean) evt.getNewValue()).booleanValue();
- updateEnabled(isEnabled);
- }
- });
- addPropertyChangeListener(IMarkableRidget.PROPERTY_OUTPUT_ONLY, new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent evt) {
- if (isOutputOnly()) {
- disposeMultipleSelectionBinding();
- } else {
- createMultipleSelectionBinding();
- }
- }
- });
}
@Override
@@ -122,23 +42,29 @@ public class ListRidget extends AbstractSelectableIndexedRidget implements ITabl
}
@Override
+ public List getUIControl() {
+ return (List) super.getUIControl();
+ }
+
+ protected int getUIControlSelectionIndex() {
+ return getUIControl().getSelectionIndex();
+ }
+
+ protected int[] getUIControlSelectionIndices() {
+ return getUIControl().getSelectionIndices();
+ }
+
+ protected int getUIControlItemCount() {
+ return getUIControl().getItemCount();
+ }
+
+ @Override
protected void bindUIControl() {
final List control = getUIControl();
if (control != null && rowObservables != null) {
viewer = new ListViewer(control);
final ObservableListContentProvider viewerCP = new ObservableListContentProvider();
- IObservableMap[] attrMap = BeansObservables.observeMaps(viewerCP.getKnownElements(), rowBeanClass,
- new String[] { renderingMethod });
- viewer.setLabelProvider(new ObservableMapLabelProvider(attrMap) {
- @Override
- public String getColumnText(Object element, int columnIndex) {
- if (MarkerSupport.HIDE_DISABLED_RIDGET_CONTENT && !isEnabled()) {
- return ""; //$NON-NLS-1$
- } else {
- return super.getColumnText(element, columnIndex);
- }
- }
- });
+ viewer.setLabelProvider(new ListLabelProvider(viewerCP.getKnownElements(), rowBeanClass, renderingMethod));
viewer.setContentProvider(viewerCP);
viewer.setInput(rowObservables);
@@ -152,11 +78,8 @@ public class ListRidget extends AbstractSelectableIndexedRidget implements ITabl
@Override
protected void unbindUIControl() {
- if (dbc != null) {
- disposeSelectionBindings();
- dbc.dispose();
- dbc = null;
- }
+ super.unbindUIControl();
+
List control = getUIControl();
if (control != null) {
control.removeSelectionListener(selectionTypeEnforcer);
@@ -166,247 +89,15 @@ public class ListRidget extends AbstractSelectableIndexedRidget implements ITabl
}
@Override
- protected java.util.List<?> getRowObservables() {
- return rowObservables;
- }
-
- @Override
- public List getUIControl() {
- return (List) super.getUIControl();
- }
-
- public void addDoubleClickListener(IActionListener listener) {
- Assert.isNotNull(listener, "listener is null"); //$NON-NLS-1$
- if (doubleClickListeners == null) {
- doubleClickListeners = new ListenerList<IActionListener>(IActionListener.class);
- }
- doubleClickListeners.add(listener);
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * Implementation note: the ListRidget ignoeres columnHeaders.
- */
- public void bindToModel(IObservableList listObservableValue, Class<? extends Object> rowBeanClass,
- String[] columnPropertyNames, String[] columnHeaders) {
-
- unbindUIControl();
-
- this.rowBeanClass = rowBeanClass;
- rowObservables = listObservableValue;
- renderingMethod = columnPropertyNames[0];
-
- bindUIControl();
- }
-
- public void bindToModel(Object listBean, String listPropertyName, Class<? extends Object> rowBeanClass,
- String[] columnPropertyNames, String[] columnHeaders) {
- IObservableList listObservableValue = new UnboundPropertyWritableList(listBean, listPropertyName);
- bindToModel(listObservableValue, rowBeanClass, columnPropertyNames, columnHeaders);
- }
-
- @Override
- public void updateFromModel() {
- super.updateFromModel();
- if (viewer != null) {
- viewer.getControl().setRedraw(false); // prevent flicker during
- // update
- StructuredSelection currentSelection = new StructuredSelection(getSelection());
- try {
- if (rowObservables instanceof IUnboundPropertyObservable) {
- ((UnboundPropertyWritableList) rowObservables).updateFromBean();
- }
- viewer.refresh(true);
- } finally {
- viewer.setSelection(currentSelection);
- viewer.getControl().setRedraw(true);
- }
- }
- }
-
- public IObservableList getObservableList() {
- return rowObservables;
+ protected AbstractListViewer getViewer() {
+ return viewer;
}
- public void removeDoubleClickListener(IActionListener listener) {
- if (doubleClickListeners != null) {
- doubleClickListeners.remove(listener);
- }
- }
-
- public void setComparator(int columnIndex, Comparator<Object> comparator) {
- Assert.isLegal(columnIndex == 0, "columnIndex out of bounds (must be 0)"); //$NON-NLS-1$
- if (comparator != null) {
- SortableComparator sortableComparator = new SortableComparator(this, comparator);
- this.comparator = new ViewerComparator(sortableComparator);
- } else {
- this.comparator = null;
- }
- updateComparator();
- }
-
- public int getSortedColumn() {
- return comparator != null && sortedColumn == 0 ? 0 : -1;
- }
-
- public boolean isColumnSortable(int columnIndex) {
- Assert.isLegal(columnIndex == 0, "columnIndex out of bounds (must be 0)"); //$NON-NLS-1$
- return comparator != null;
- }
-
- @Override
- public boolean isDisableMandatoryMarker() {
- return hasInput();
- }
-
- public boolean isSortedAscending() {
- return isSortedAscending;
- }
-
- /**
- * This method is not supported by this ridget.
- *
- * @throws UnsupportedOperationException
- * this is not supported by this ridget
- */
- public final void setColumnSortable(int columnIndex, boolean sortable) {
- throw new UnsupportedOperationException();
- }
-
- public void setSortedAscending(boolean ascending) {
- if (ascending != isSortedAscending) {
- boolean oldSortedAscending = isSortedAscending;
- isSortedAscending = ascending;
- if (viewer != null) {
- viewer.refresh();
- }
- firePropertyChange(ISortableByColumn.PROPERTY_SORT_ASCENDING, oldSortedAscending, isSortedAscending);
- }
- }
-
- public final void setSortedColumn(int columnIndex) {
- String msg = "columnIndex out of range (-1 - 0): " + columnIndex; //$NON-NLS-1$
- Assert.isLegal(columnIndex >= -1 && columnIndex <= 0, msg);
- if (sortedColumn != columnIndex) {
- int oldSortedColumn = sortedColumn;
- sortedColumn = columnIndex;
- updateComparator();
- firePropertyChange(ISortableByColumn.PROPERTY_SORTED_COLUMN, oldSortedColumn, sortedColumn);
- }
- }
-
- @Override
- public int getSelectionIndex() {
- List control = getUIControl();
- return control == null ? -1 : control.getSelectionIndex();
- }
-
- @Override
- public int[] getSelectionIndices() {
- List control = getUIControl();
- return control == null ? new int[0] : control.getSelectionIndices();
- }
-
- @Override
- public int indexOfOption(Object option) {
- List control = getUIControl();
- if (control != null) {
- int optionCount = control.getItemCount();
- for (int i = 0; i < optionCount; i++) {
- if (viewer.getElementAt(i).equals(option)) {
- return i;
- }
- }
- }
- return -1;
- }
-
- public final boolean hasMoveableColumns() {
- return false;
- }
-
- /**
- * This method is not supported by this ridget.
- *
- * @throws UnsupportedOperationException
- * this is not supported by this ridget
- */
- public final void setMoveableColumns(boolean moveableColumns) {
- throw new UnsupportedOperationException("not implemented"); //$NON-NLS-1$
- }
-
- /**
- * This method is not supported by this ridget.
- *
- * @throws UnsupportedOperationException
- * this is not supported by this ridget
- */
- public void setColumnFormatter(int columnIndex, IColumnFormatter formatter) {
- throw new UnsupportedOperationException();
- }
-
- // helping methods
- // ////////////////
-
- private void createMultipleSelectionBinding() {
- if (viewerMSB == null && dbc != null && viewer != null) {
- StructuredSelection currentSelection = new StructuredSelection(getSelection());
- IViewerObservableList viewerSelections = ViewersObservables.observeMultiSelection(viewer);
- viewerMSB = dbc.bindList(viewerSelections, getMultiSelectionObservable(), new UpdateListStrategy(
- UpdateListStrategy.POLICY_UPDATE), new UpdateListStrategy(UpdateListStrategy.POLICY_UPDATE));
- viewer.setSelection(currentSelection);
- }
- }
-
- private void disposeMultipleSelectionBinding() {
- if (viewerMSB != null) { // implies dbc != null
- viewerMSB.dispose();
- dbc.removeBinding(viewerMSB);
- viewerMSB = null;
- }
- }
-
- private void createSelectionBindings() {
- dbc = new DataBindingContext();
- // viewer to single selection binding
- IObservableValue viewerSelection = ViewersObservables.observeSingleSelection(viewer);
- viewerSSB = dbc.bindValue(viewerSelection, getSingleSelectionObservable(), new UpdateValueStrategy(
- UpdateValueStrategy.POLICY_UPDATE).setAfterGetValidator(new OutputAwareValidator(this)),
- new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE));
- // viewer to multiple selection binding
- viewerMSB = null;
- if (!isOutputOnly()) {
- createMultipleSelectionBinding();
- }
- }
-
- private void disposeSelectionBindings() {
- if (viewerSSB != null && !viewerSSB.isDisposed()) {
- viewerSSB.dispose();
- }
- disposeMultipleSelectionBinding();
- }
-
- private boolean hasInput() {
- return !getSelection().isEmpty();
- }
-
- private void updateComparator() {
- if (viewer != null) {
- if (sortedColumn == 0) {
- viewer.setComparator(this.comparator);
- } else {
- viewer.setComparator(null);
- }
- }
- }
-
- private void updateEnabled(boolean isEnabled) {
+ protected void updateEnabled(boolean isEnabled) {
final String savedBackgroundKey = "oldbg"; //$NON-NLS-1$
if (isEnabled) {
- if (viewer != null && rowObservables != null) {
- viewer.refresh();
+ if (isBound() && rowObservables != null) {
+ refreshViewer();
createSelectionBindings();
List list = viewer.getList();
list.setBackground((Color) list.getData(savedBackgroundKey));
@@ -414,8 +105,8 @@ public class ListRidget extends AbstractSelectableIndexedRidget implements ITabl
}
} else {
disposeSelectionBindings();
- if (viewer != null) {
- viewer.refresh();
+ if (isBound()) {
+ refreshViewer();
List list = viewer.getList();
if (MarkerSupport.HIDE_DISABLED_RIDGET_CONTENT) {
list.deselectAll();
@@ -432,7 +123,7 @@ public class ListRidget extends AbstractSelectableIndexedRidget implements ITabl
/**
* Enforces selection in the control:
* <ul>
- * <li>disallows selection changes when the ridget is "output only"</li>
+ * <li>disallows selection changes when the ridget is "output only"</li>
* <li>disallows multiple selection is the selection type of the ridget is
* {@link ISelectableRidget.SelectionType#SINGLE}</li>
* </ul>
@@ -475,17 +166,4 @@ public class ListRidget extends AbstractSelectableIndexedRidget implements ITabl
}
}
- /**
- * Notifies doubleClickListeners when the bound widget is double clicked.
- */
- private final class DoubleClickForwarder extends MouseAdapter {
- @Override
- public void mouseDoubleClick(MouseEvent e) {
- if (doubleClickListeners != null) {
- for (IActionListener listener : doubleClickListeners.getListeners()) {
- listener.callback();
- }
- }
- }
- }
}
diff --git a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableComparator.java b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableComparator.java
index 701199b..1351641 100644
--- a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableComparator.java
+++ b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableComparator.java
@@ -15,6 +15,8 @@ import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.riena.ui.ridgets.swt.SortableComparator;
+
/**
* This comparator uses the values of the column the table is sorted by.
*/
diff --git a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableRidget.java b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableRidget.java
index 8707ece..fd59d82 100644
--- a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableRidget.java
+++ b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TableRidget.java
@@ -54,6 +54,7 @@ import org.eclipse.riena.ui.ridgets.databinding.IUnboundPropertyObservable;
import org.eclipse.riena.ui.ridgets.databinding.UnboundPropertyWritableList;
import org.eclipse.riena.ui.ridgets.swt.AbstractSWTRidget;
import org.eclipse.riena.ui.ridgets.swt.ColumnFormatter;
+import org.eclipse.riena.ui.ridgets.swt.SortableComparator;
/**
* Ridget for SWT {@link Table} widgets.
diff --git a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TreeTableRidget.java b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TreeTableRidget.java
index 4c05a3c..3734146 100644
--- a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TreeTableRidget.java
+++ b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/TreeTableRidget.java
@@ -21,6 +21,8 @@ import org.eclipse.riena.ui.ridgets.IColumnFormatter;
import org.eclipse.riena.ui.ridgets.IGroupedTreeTableRidget;
import org.eclipse.riena.ui.ridgets.ITreeTableRidget;
import org.eclipse.riena.ui.ridgets.swt.ColumnFormatter;
+import org.eclipse.riena.ui.ridgets.swt.SortableComparator;
+
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
diff --git a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/ui/ridgets/swt/AbstractListRidget.java b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/ui/ridgets/swt/AbstractListRidget.java
new file mode 100644
index 0000000..146aa32
--- /dev/null
+++ b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/ui/ridgets/swt/AbstractListRidget.java
@@ -0,0 +1,407 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 compeople AG and others.
+ * 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:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.ui.ridgets.swt;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Comparator;
+
+import org.eclipse.core.databinding.Binding;
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.UpdateListStrategy;
+import org.eclipse.core.databinding.UpdateValueStrategy;
+import org.eclipse.core.databinding.beans.BeansObservables;
+import org.eclipse.core.databinding.observable.list.IListChangeListener;
+import org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.list.ListChangeEvent;
+import org.eclipse.core.databinding.observable.set.IObservableSet;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.databinding.observable.value.IValueChangeListener;
+import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.databinding.viewers.IViewerObservableList;
+import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
+import org.eclipse.jface.databinding.viewers.ViewersObservables;
+import org.eclipse.jface.viewers.AbstractListViewer;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionListener;
+
+import org.eclipse.riena.core.util.ListenerList;
+import org.eclipse.riena.internal.ui.ridgets.swt.AbstractSWTWidgetRidget;
+import org.eclipse.riena.internal.ui.ridgets.swt.AbstractSelectableIndexedRidget;
+import org.eclipse.riena.internal.ui.ridgets.swt.MarkerSupport;
+import org.eclipse.riena.internal.ui.ridgets.swt.OutputAwareValidator;
+import org.eclipse.riena.ui.common.ISortableByColumn;
+import org.eclipse.riena.ui.ridgets.IActionListener;
+import org.eclipse.riena.ui.ridgets.IColumnFormatter;
+import org.eclipse.riena.ui.ridgets.IMarkableRidget;
+import org.eclipse.riena.ui.ridgets.ITableRidget;
+import org.eclipse.riena.ui.ridgets.databinding.IUnboundPropertyObservable;
+import org.eclipse.riena.ui.ridgets.databinding.UnboundPropertyWritableList;
+
+/**
+ * An abstract Ridget for lists that does not depend on the class
+ * org.eclipse.swt.widgets.List. May be used for Ridgets for custom lists.
+ */
+public abstract class AbstractListRidget extends AbstractSelectableIndexedRidget implements ITableRidget {
+ protected SelectionListener selectionTypeEnforcer;
+ protected final MouseListener doubleClickForwarder;
+ private ListenerList<IActionListener> doubleClickListeners;
+
+ protected DataBindingContext dbc;
+ private Binding viewerSSB;
+ /*
+ * Binds the viewer's multiple selection to the multiple selection
+ * observable. This binding hsa to be disposed when the ridget is set to
+ * output-only, to avoid updating the model. It has to be recreated when the
+ * ridget is set to not-output-only.
+ */
+ private Binding viewerMSB;
+
+ protected Class<?> rowBeanClass;
+ protected IObservableList rowObservables;
+ protected String renderingMethod;
+
+ private boolean isSortedAscending;
+ private int sortedColumn;
+ private ViewerComparator comparator;
+
+ public AbstractListRidget() {
+ doubleClickForwarder = new DoubleClickForwarder();
+ isSortedAscending = true;
+ sortedColumn = -1;
+ getSingleSelectionObservable().addValueChangeListener(new IValueChangeListener() {
+ public void handleValueChange(ValueChangeEvent event) {
+ disableMandatoryMarkers(hasInput());
+ }
+ });
+ getMultiSelectionObservable().addListChangeListener(new IListChangeListener() {
+ public void handleListChange(ListChangeEvent event) {
+ disableMandatoryMarkers(hasInput());
+ }
+ });
+ addPropertyChangeListener(IMarkableRidget.PROPERTY_ENABLED, new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent evt) {
+ boolean isEnabled = ((Boolean) evt.getNewValue()).booleanValue();
+ updateEnabled(isEnabled);
+ }
+ });
+ addPropertyChangeListener(IMarkableRidget.PROPERTY_OUTPUT_ONLY, new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (isOutputOnly()) {
+ disposeMultipleSelectionBinding();
+ } else {
+ createMultipleSelectionBinding();
+ }
+ }
+ });
+ }
+
+ protected abstract void updateEnabled(boolean isEnabled);
+
+ /**
+ * @see org.eclipse.riena.internal.ui.ridgets.swt.AbstractSWTWidgetRidget#unbindUIControl()
+ */
+ @Override
+ protected void unbindUIControl() {
+ if (dbc != null) {
+ disposeSelectionBindings();
+ dbc.dispose();
+ dbc = null;
+ }
+ }
+
+ @Override
+ protected java.util.List<?> getRowObservables() {
+ return rowObservables;
+ }
+
+ public void addDoubleClickListener(IActionListener listener) {
+ Assert.isNotNull(listener, "listener is null"); //$NON-NLS-1$
+ if (doubleClickListeners == null) {
+ doubleClickListeners = new ListenerList<IActionListener>(IActionListener.class);
+ }
+ doubleClickListeners.add(listener);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Implementation note: the ListRidget ignoeres columnHeaders.
+ */
+ public void bindToModel(IObservableList listObservableValue, Class<? extends Object> rowBeanClass,
+ String[] columnPropertyNames, String[] columnHeaders) {
+
+ unbindUIControl();
+
+ this.rowBeanClass = rowBeanClass;
+ rowObservables = listObservableValue;
+ renderingMethod = columnPropertyNames[0];
+
+ bindUIControl();
+ }
+
+ public void bindToModel(Object listBean, String listPropertyName, Class<? extends Object> rowBeanClass,
+ String[] columnPropertyNames, String[] columnHeaders) {
+ IObservableList listObservableValue = new UnboundPropertyWritableList(listBean, listPropertyName);
+ bindToModel(listObservableValue, rowBeanClass, columnPropertyNames, columnHeaders);
+ }
+
+ @Override
+ public void updateFromModel() {
+ super.updateFromModel();
+ if (isBound()) {
+ getViewer().getControl().setRedraw(false); // prevent flicker during
+ // update
+ StructuredSelection currentSelection = new StructuredSelection(getSelection());
+ try {
+ if (rowObservables instanceof IUnboundPropertyObservable) {
+ ((UnboundPropertyWritableList) rowObservables).updateFromBean();
+ }
+ getViewer().refresh(true);
+ } finally {
+ getViewer().setSelection(currentSelection);
+ getViewer().getControl().setRedraw(true);
+ }
+ }
+ }
+
+ public IObservableList getObservableList() {
+ return rowObservables;
+ }
+
+ public void removeDoubleClickListener(IActionListener listener) {
+ if (doubleClickListeners != null) {
+ doubleClickListeners.remove(listener);
+ }
+ }
+
+ public void setComparator(int columnIndex, Comparator<Object> comparator) {
+ Assert.isLegal(columnIndex == 0, "columnIndex out of bounds (must be 0)"); //$NON-NLS-1$
+ if (comparator != null) {
+ SortableComparator sortableComparator = new SortableComparator(this, comparator);
+ this.comparator = new ViewerComparator(sortableComparator);
+ } else {
+ this.comparator = null;
+ }
+ updateComparator();
+ }
+
+ public int getSortedColumn() {
+ return comparator != null && sortedColumn == 0 ? 0 : -1;
+ }
+
+ public boolean isColumnSortable(int columnIndex) {
+ Assert.isLegal(columnIndex == 0, "columnIndex out of bounds (must be 0)"); //$NON-NLS-1$
+ return comparator != null;
+ }
+
+ @Override
+ public boolean isDisableMandatoryMarker() {
+ return hasInput();
+ }
+
+ public boolean isSortedAscending() {
+ return isSortedAscending;
+ }
+
+ /**
+ * This method is not supported by this ridget.
+ *
+ * @throws UnsupportedOperationException
+ * this is not supported by this ridget
+ */
+ public final void setColumnSortable(int columnIndex, boolean sortable) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setSortedAscending(boolean ascending) {
+ if (ascending != isSortedAscending) {
+ boolean oldSortedAscending = isSortedAscending;
+ isSortedAscending = ascending;
+ if (isBound()) {
+ refreshViewer();
+ }
+ firePropertyChange(ISortableByColumn.PROPERTY_SORT_ASCENDING, oldSortedAscending, isSortedAscending);
+ }
+ }
+
+ protected boolean isBound() {
+ return getViewer() != null;
+ }
+
+ protected void refreshViewer() {
+ getViewer().refresh();
+ }
+
+ public final void setSortedColumn(int columnIndex) {
+ String msg = "columnIndex out of range (-1 - 0): " + columnIndex; //$NON-NLS-1$
+ Assert.isLegal(columnIndex >= -1 && columnIndex <= 0, msg);
+ if (sortedColumn != columnIndex) {
+ int oldSortedColumn = sortedColumn;
+ sortedColumn = columnIndex;
+ updateComparator();
+ firePropertyChange(ISortableByColumn.PROPERTY_SORTED_COLUMN, oldSortedColumn, sortedColumn);
+ }
+ }
+
+ @Override
+ public int getSelectionIndex() {
+ return getUIControl() == null ? -1 : getUIControlSelectionIndex();
+ }
+
+ protected abstract int getUIControlSelectionIndex();
+
+ @Override
+ public int[] getSelectionIndices() {
+ return getUIControl() == null ? new int[0] : getUIControlSelectionIndices();
+ }
+
+ protected abstract int[] getUIControlSelectionIndices();
+
+ @Override
+ public int indexOfOption(Object option) {
+ if (getUIControl() != null) {
+ int optionCount = getUIControlItemCount();
+ for (int i = 0; i < optionCount; i++) {
+ if (getViewer().getElementAt(i).equals(option)) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ protected abstract int getUIControlItemCount();
+
+ public final boolean hasMoveableColumns() {
+ return false;
+ }
+
+ /**
+ * This method is not supported by this ridget.
+ *
+ * @throws UnsupportedOperationException
+ * this is not supported by this ridget
+ */
+ public final void setMoveableColumns(boolean moveableColumns) {
+ throw new UnsupportedOperationException("not implemented"); //$NON-NLS-1$
+ }
+
+ /**
+ * This method is not supported by this ridget.
+ *
+ * @throws UnsupportedOperationException
+ * this is not supported by this ridget
+ */
+ public void setColumnFormatter(int columnIndex, IColumnFormatter formatter) {
+ throw new UnsupportedOperationException();
+ }
+
+ // helping methods
+ // ////////////////
+
+ private void createMultipleSelectionBinding() {
+ if (viewerMSB == null && dbc != null && isBound()) {
+ StructuredSelection currentSelection = new StructuredSelection(getSelection());
+ IViewerObservableList viewerSelections = ViewersObservables.observeMultiSelection(getViewer());
+ viewerMSB = dbc.bindList(viewerSelections, getMultiSelectionObservable(), new UpdateListStrategy(
+ UpdateListStrategy.POLICY_UPDATE), new UpdateListStrategy(UpdateListStrategy.POLICY_UPDATE));
+ getViewer().setSelection(currentSelection);
+ }
+ }
+
+ protected abstract AbstractListViewer getViewer();
+
+ private void disposeMultipleSelectionBinding() {
+ if (viewerMSB != null) { // implies dbc != null
+ viewerMSB.dispose();
+ dbc.removeBinding(viewerMSB);
+ viewerMSB = null;
+ }
+ }
+
+ protected void createSelectionBindings() {
+ dbc = new DataBindingContext();
+ // viewer to single selection binding
+ IObservableValue viewerSelection = ViewersObservables.observeSingleSelection(getViewer());
+ viewerSSB = dbc.bindValue(viewerSelection, getSingleSelectionObservable(), new UpdateValueStrategy(
+ UpdateValueStrategy.POLICY_UPDATE).setAfterGetValidator(new OutputAwareValidator(this)),
+ new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE));
+ // viewer to multiple selection binding
+ viewerMSB = null;
+ if (!isOutputOnly()) {
+ createMultipleSelectionBinding();
+ }
+ }
+
+ protected void disposeSelectionBindings() {
+ if (viewerSSB != null && !viewerSSB.isDisposed()) {
+ viewerSSB.dispose();
+ }
+ disposeMultipleSelectionBinding();
+ }
+
+ private boolean hasInput() {
+ return !getSelection().isEmpty();
+ }
+
+ protected void updateComparator() {
+ if (isBound()) {
+ if (sortedColumn == 0) {
+ getViewer().setComparator(this.comparator);
+ } else {
+ getViewer().setComparator(null);
+ }
+ }
+ }
+
+ // helping classes
+ // ////////////////
+
+ /**
+ * Notifies doubleClickListeners when the bound widget is double clicked.
+ */
+ private final class DoubleClickForwarder extends MouseAdapter {
+ @Override
+ public void mouseDoubleClick(MouseEvent e) {
+ if (doubleClickListeners != null) {
+ for (IActionListener listener : doubleClickListeners.getListeners()) {
+ listener.callback();
+ }
+ }
+ }
+ }
+
+ protected class ListLabelProvider extends ObservableMapLabelProvider {
+
+ /**
+ * @param attributeMaps
+ */
+ public ListLabelProvider(IObservableSet domain, Class<?> beanClass, String propertyName) {
+ super(BeansObservables.observeMaps(domain, beanClass, new String[] { propertyName }));
+ }
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ if (MarkerSupport.HIDE_DISABLED_RIDGET_CONTENT && !isEnabled()) {
+ return ""; //$NON-NLS-1$
+ } else {
+ return super.getColumnText(element, columnIndex);
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/SortableComparator.java b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/ui/ridgets/swt/SortableComparator.java
index 5bf6485..d54b4b2 100644
--- a/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/internal/ui/ridgets/swt/SortableComparator.java
+++ b/org.eclipse.riena.ui.ridgets.swt/src/org/eclipse/riena/ui/ridgets/swt/SortableComparator.java
@@ -8,24 +8,24 @@
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
-package org.eclipse.riena.internal.ui.ridgets.swt;
+package org.eclipse.riena.ui.ridgets.swt;
import java.util.Comparator;
-import org.eclipse.riena.ui.common.ISortableByColumn;
-
import org.eclipse.core.runtime.Assert;
+import org.eclipse.riena.ui.common.ISortableByColumn;
+
/**
* Changes the result of the given <tt>comparator</tt> according to the
* <tt>sortedAscending</tt> setting in the ridget.
*/
-final class SortableComparator implements Comparator<Object> {
+public final class SortableComparator implements Comparator<Object> {
private final ISortableByColumn ridget;
private final Comparator<Object> orgComparator;
- SortableComparator(ISortableByColumn ridget, Comparator<Object> comparator) {
+ public SortableComparator(ISortableByColumn ridget, Comparator<Object> comparator) {
Assert.isNotNull(ridget);
Assert.isNotNull(comparator);
this.ridget = ridget;
@@ -37,7 +37,7 @@ final class SortableComparator implements Comparator<Object> {
return ridget.isSortedAscending() ? result : result * -1;
}
- int getSortedColumn() {
+ public int getSortedColumn() {
return ridget.getSortedColumn();
}
}