# HG changeset patch
# User Frank Benoit You can only add the layout to a container whose
+ * only child is the table/tree control you want the layouts applied to.
+ *
+ * You can only add the {@link Layout} to a container whose only
+ * child is the {@link Table} control you want the {@link Layout} applied to.
+ * Don't assign the layout directly the {@link Table}
+ *
+ * Note: This class can open an error dialog and should not be used
+ * outside of the UI Thread.
+ *
+ * A static class providing utility methods to all of JFace.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ *
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ * @param ixs the indices of the items to select
+ */
+ protected abstract void listSetSelection(int[] ixs);
+
+ /**
+ * Shows the selection. If the selection is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the selection is visible.
+ */
+ protected abstract void listShowSelection();
+
+ /**
+ * Deselects all selected items in the underlying widget.
+ */
+ protected abstract void listDeselectAll();
+
+ public this(){
+ listMap = new ArraySeq!(Object);
+ }
+
+ /**
+ * Adds the given elements to this list viewer.
+ * If this viewer does not have a sorter, the elements are added at the end
+ * in the order given; otherwise the elements are inserted at appropriate positions.
+ *
+ * This method should be called (by the content provider) when elements
+ * have been added to the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * This method should be called (by the content provider) when elements have
+ * been added to the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * This method should be called (by the content provider) when a single element
+ * has been added to the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ * Note that there is another method for efficiently processing the simultaneous
+ * addition of multiple elements.
+ *
+ * Default implementation returns -1.
+ *
+ * Default implementation does nothing.
+ *
+ * This method should be called (by the content provider) when elements
+ * have been removed from the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * This method should be called (by the content provider) when a single element
+ * has been removed from the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ * Note that there is another method for efficiently processing the simultaneous
+ * removal of multiple elements.
+ *
+ * This method should be called (by the content provider) when elements have
+ * been added to the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * This method should be called (by the content provider) when a single
+ * element has been added to the model, in order to cause the viewer to
+ * accurately reflect the model. This method only affects the viewer, not
+ * the model. Note that there is another method for efficiently processing
+ * the simultaneous addition of multiple elements.
+ *
+ * This method is internal to the framework.
+ *
+ * This method should be called (by the content provider) when elements have
+ * been added to the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * This method should be called (by the content provider) when elements have
+ * been removed from the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * This method should be called (by the content provider) when a single
+ * element has been removed from the model, in order to cause the viewer to
+ * accurately reflect the model. This method only affects the viewer, not
+ * the model. Note that there is another method for efficiently processing
+ * the simultaneous removal of multiple elements.
+ *
+ * Items that are not in the receiver are ignored. If the receiver is
+ * single-select and multiple items are specified, then all items are
+ * ignored.
+ *
+ * Indices that are out of range and duplicate indices are ignored. If the
+ * receiver is single-select and multiple indices are specified, then all
+ * indices are ignored.
+ *
+ * If the item at a given index is not selected, it is selected.
+ * If the item at a given index was already selected, it remains selected.
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ * Nodes in the tree can be in either an expanded or a collapsed state,
+ * depending on whether the children on a node are visible. This class
+ * introduces public methods for controlling the expanding and collapsing of
+ * nodes.
+ *
+ * As of 3.2, AbstractTreeViewer supports multiple equal elements (each with a
+ * different parent chain) in the tree. This support requires that clients
+ * enable the element map by calling
+ * Content providers for abstract tree viewers must implement one of the
+ * interfaces
+ * This method should be called (by the content provider) when elements have
+ * been added to the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * EXPERIMENTAL. Not to be used except by JDT. This method was added to
+ * support JDT's explorations into grouping by working sets, which requires
+ * viewers to support multiple equal elements. See bug 76482 for more
+ * details. This support will likely be removed in Eclipse 3.2 in favor of
+ * proper support for multiple equal elements.
+ *
+ * This method should be called (by the content provider) when a single
+ * element has been added to the model, in order to cause the viewer to
+ * accurately reflect the model. This method only affects the viewer, not
+ * the model. Note that there is another method for efficiently processing
+ * the simultaneous addition of multiple elements.
+ *
+ * The default implementation of this framework method assumes that
+ *
+ * This method is not intended to be overridden by subclasses.
+ *
+ * This method is typically used when preserving the interesting state of a
+ * viewer;
+ *
+ *
+ * EXPERIMENTAL. Not to be used except by JDT. This method was added to
+ * support JDT's explorations into grouping by working sets, which requires
+ * viewers to support multiple equal elements. See bug 76482 for more
+ * details. This support will likely be removed in Eclipse 3.2 in favor of
+ * proper support for multiple equal elements.
+ *
+ * EXPERIMENTAL. Not to be used except by JDT. This method was added to
+ * support JDT's explorations into grouping by working sets, which requires
+ * viewers to support multiple equal elements. See bug 76482 for more
+ * details. This support will likely be removed in Eclipse 3.2 in favor of
+ * proper support for multiple equal elements.
+ *
+ * The default implementation of this framework method calls
+ *
+ * This method should be called (by the content provider) when elements have
+ * been removed from the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * This method should be called (by the content provider) when elements have
+ * been removed from the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ *
+ * This method should be called (by the content provider) when a single
+ * element has been removed from the model, in order to cause the viewer to
+ * accurately reflect the model. This method only affects the viewer, not
+ * the model. Note that there is another method for efficiently processing
+ * the simultaneous removal of multiple elements.
+ *
+ * The value
+ * This method is typically used when restoring the interesting state of a
+ * viewer captured by an earlier call to
+ * This method is typically used when restoring the interesting state of a
+ * viewer captured by an earlier call to
+ * This method is typically used when preserving the interesting state of a
+ * viewer;
+ * This method should be called (by the content provider) when elements have
+ * been added to the model, in order to cause the viewer to accurately
+ * reflect the model. This method only affects the viewer, not the model.
+ * Subclasses should overwrite this method, which has a default
+ * implementation (returning 0) for API backwards compatility reasons
+ * This class is not intended to be subclassed outside the viewer framework.
+ *
+ * Subclasses implement particular kinds of cell editors. This package contains various
+ * specialized cell editors:
+ * true
.
+ *
+ * @param scrollable
+ * @param width
+ * @param area
+ * @param increase
+ */
+ private void layoutTableTree(Scrollable scrollable, int width,
+ Rectangle area, bool increase) {
+ int size = getColumnCount(scrollable);
+ int[] widths = new int[size];
+
+ int[] weightIteration = new int[size];
+ int numberOfWeightColumns = 0;
+
+ int fixedWidth = 0;
+ int minWeightWidth = 0;
+ int totalWeight = 0;
+
+ // First calc space occupied by fixed columns
+ for (int i = 0; i < size; i++) {
+ ColumnLayoutData col = getLayoutData(scrollable,i);
+ if ( auto cpd = cast(ColumnPixelData)col ) {
+ int pixels = cpd.width;
+ if (cpd.addTrim) {
+ pixels += COLUMN_TRIM;
+ }
+ widths[i] = pixels;
+ fixedWidth += pixels;
+ } else if ( auto cw = cast(ColumnWeightData) col ) {
+ weightIteration[numberOfWeightColumns] = i;
+ numberOfWeightColumns++;
+ totalWeight += cw.weight;
+ minWeightWidth += cw.minimumWidth;
+ widths[i] = cw.minimumWidth;
+ } else {
+ Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
+ }
+ }
+
+ // Do we have columns that have a weight?
+ int restIncludingMinWidths = width - fixedWidth;
+ int rest = restIncludingMinWidths - minWeightWidth;
+ if (numberOfWeightColumns > 0 && rest > 0) {
+
+ // Modify the weights to reflect what each column already
+ // has due to its minimum. Otherwise, columns with low
+ // minimums get discriminated.
+ int totalWantedPixels = 0;
+ int[] wantedPixels = new int[numberOfWeightColumns];
+ for (int i = 0; i < numberOfWeightColumns; i++) {
+ ColumnWeightData cw = cast(ColumnWeightData) getLayoutData(scrollable,weightIteration[i]);
+ wantedPixels[i] = totalWeight is 0 ? 0 : cw.weight
+ * restIncludingMinWidths / totalWeight;
+ totalWantedPixels += wantedPixels[i];
+ }
+
+ // Now distribute the rest to the columns with weight.
+ int totalDistributed = 0;
+ for (int i = 0; i < numberOfWeightColumns; ++i) {
+ int pixels = totalWantedPixels is 0 ? 0 : wantedPixels[i]
+ * rest / totalWantedPixels;
+ totalDistributed += pixels;
+ widths[weightIteration[i]] += pixels;
+ }
+
+ // Distribute any remaining pixels to columns with weight.
+ int diff = rest - totalDistributed;
+ for (int i = 0; diff > 0; i = ((i + 1) % numberOfWeightColumns)) {
+ ++widths[weightIteration[i]];
+ --diff;
+ }
+ }
+
+ if (increase) {
+ scrollable.setSize(area.width, area.height);
+ }
+
+ inupdateMode = true;
+ setColumnWidths(scrollable, widths);
+ scrollable.update();
+ inupdateMode = false;
+
+ if (!increase) {
+ scrollable.setSize(area.width, area.height);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwt.widgets.Layout#computeSize(dwt.widgets.Composite,
+ * int, int, bool)
+ */
+ protected Point computeSize(Composite composite, int wHint, int hHint,
+ bool flushCache) {
+ return computeTableTreeSize(getControl(composite), wHint, hHint);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwt.widgets.Layout#layout(dwt.widgets.Composite,
+ * bool)
+ */
+ protected void layout(Composite composite, bool flushCache) {
+ Rectangle area = composite.getClientArea();
+ Scrollable table = getControl(composite);
+ int tableWidth = table.getSize().x;
+ int trim = computeTrim(area, table, tableWidth);
+ int width = Math.max(0, area.width - trim);
+
+ if (width > 1)
+ layoutTableTree(table, width, area, tableWidth < area.width);
+
+ // For the first time we need to relayout because Scrollbars are not
+ // calculate appropriately
+ if (relayout) {
+ relayout = false;
+ composite.layout();
+ }
+ }
+
+ /**
+ * Compute the area required for trim.
+ *
+ * @param area
+ * @param scrollable
+ * @param currentWidth
+ * @return int
+ */
+ private int computeTrim(Rectangle area, Scrollable scrollable,
+ int currentWidth) {
+ int trim;
+
+ if (currentWidth > 1) {
+ trim = currentWidth - scrollable.getClientArea().width;
+ } else {
+ // initially, the table has no extend and no client area - use the
+ // border with
+ // plus some padding as educated guess
+ trim = 2 * scrollable.getBorderWidth() + 1;
+ }
+
+ return trim;
+ }
+
+ /**
+ * Get the control being laid out.
+ *
+ * @param composite
+ * the composite with the layout
+ * @return {@link Scrollable}
+ */
+ Scrollable getControl(Composite composite) {
+ return cast(Scrollable) composite.getChildren()[0];
+ }
+
+ /**
+ * Get the number of columns for the receiver.
+ *
+ * @return the number of columns
+ */
+ abstract int getColumnCount(Scrollable tableTree);
+
+ /**
+ * Set the widths of the columns.
+ *
+ * @param widths
+ */
+ abstract void setColumnWidths(Scrollable tableTree, int[] widths);
+
+ abstract ColumnLayoutData getLayoutData(Scrollable tableTree, int columnIndex);
+
+ abstract void updateColumnData(Widget column);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/layout/TableColumnLayout.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/layout/TableColumnLayout.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation 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:
+ * Tom Schindl handleException
opens a message dialog.
+ * null
to reset to the
+ * default runner
+ * @since 3.1
+ */
+ public static void setRunner(ISafeRunnableRunner runner) {
+ SafeRunnable.runner = runner;
+ }
+
+ /**
+ * Runs the given safe runnable using the safe runnable runner. This is a
+ * convenience method, equivalent to:
+ * SafeRunnable.getRunner().run(runnable)
.
+ *
+ * @param runnable
+ * the runnable to run
+ * @since 3.1
+ */
+ public static void run(ISafeRunnable runnable) {
+ getRunner().run(runnable);
+ }
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/util/SafeRunnableDialog.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/util/SafeRunnableDialog.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,351 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
.
+ */
+ private IStatus getSingleSelection() {
+ ISelection rawSelection = statusListViewer.getSelection();
+ if (rawSelection !is null
+ && rawSelection instanceof IStructuredSelection) {
+ IStructuredSelection selection = (IStructuredSelection) rawSelection;
+ if (selection.size() is 1) {
+ return (IStatus) selection.getFirstElement();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * The selection in the multiple job list has changed. Update widget
+ * enablements and repopulate the list.
+ */
+ void handleSelectionChange() {
+ IStatus newSelection = getSingleSelection();
+ setStatus(newSelection);
+ updateEnablements();
+ showDetailsArea();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.dialogs.ErrorDialog#shouldShowDetailsButton()
+ */
+ protected bool shouldShowDetailsButton() {
+ return true;
+ }
+
+ /**
+ * Add the status to the receiver.
+ * @param status
+ */
+ public void addStatus(IStatus status) {
+ statuses.add(status);
+ refresh();
+
+ }
+
+
+}
+++/
\ No newline at end of file
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/util/Util.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/util/Util.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,474 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
.
+// */
+// public static final SortedSet EMPTY_SORTED_SET = Collections
+// .unmodifiableSortedSet(new TreeSet());
+
+ /**
+ * A common zero-length string. It avoids needing write NON-NLS
+ * next to code fragments. It's also a bit clearer to read.
+ */
+ public static final String ZERO_LENGTH_STRING = ""; //$NON-NLS-1$
+
+ /**
+ * Verifies that the given object is an instance of the given class.
+ *
+ * @param object
+ * The object to check; may be null
.
+ * @param c
+ * The class which the object should be; must not be
+ * null
.
+ */
+ public static final void assertInstance(Object object, ClassInfo c) {
+ assertInstance(object, c, false);
+ }
+
+ /**
+ * Verifies the given object is an instance of the given class. It is
+ * possible to specify whether the object is permitted to be
+ * null
.
+ *
+ * @param object
+ * The object to check; may be null
.
+ * @param c
+ * The class which the object should be; must not be
+ * null
.
+ * @param allowNull
+ * Whether the object is allowed to be null
.
+ */
+ private static final void assertInstance(Object object,
+ ClassInfo c, bool allowNull) {
+ if (object is null && allowNull) {
+ return;
+ }
+
+ if (object is null || c is null) {
+ throw new NullPointerException();
+ } else if (!_d_isbaseof( &object.classinfo, &c ) ) {
+ throw new IllegalArgumentException(null);
+ }
+ }
+
+ /**
+ * Compares two bool values. false
is considered to be
+ * "less than" true
.
+ *
+ * @param left
+ * The left value to compare
+ * @param right
+ * The right value to compare
+ * @return -1
if the left is false
and the
+ * right is true
. 1
if the opposite
+ * is true. If they are equal, then it returns 0
.
+ */
+ public static final int compare(bool left, bool right) {
+ return left is false ? (right is true ? -1 : 0) : 1;
+ }
+
+ /**
+ * Compares two integer values.
+ *
+ * @param left
+ * The left value to compare
+ * @param right
+ * The right value to compare
+ * @return left - right
+ */
+ public static final int compare(int left, int right) {
+ return left - right;
+ }
+
+ /**
+ * Compares to comparable objects -- defending against null
.
+ *
+ * @param left
+ * The left object to compare; may be null
.
+ * @param right
+ * The right object to compare; may be null
.
+ * @return The result of the comparison. null
is considered
+ * to be the least possible value.
+ */
+ public static final int compare(Comparable left,
+ Comparable right) {
+ if (left is null && right is null) {
+ return 0;
+ } else if (left is null) {
+ return -1;
+ } else if (right is null) {
+ return 1;
+ } else {
+ return left.compareTo(cast(Object)right);
+ }
+ }
+
+ /**
+ * Compares two arrays of comparable objects -- accounting for
+ * null
.
+ *
+ * @param left
+ * The left array to be compared; may be null
.
+ * @param right
+ * The right array to be compared; may be null
.
+ * @return The result of the comparison. null
is considered
+ * to be the least possible value. A shorter array is considered
+ * less than a longer array.
+ */
+ public static final int compare(Comparable[] left,
+ Comparable[] right) {
+ if (left is null && right is null) {
+ return 0;
+ } else if (left is null) {
+ return -1;
+ } else if (right is null) {
+ return 1;
+ } else {
+ int l = left.length;
+ int r = right.length;
+
+ if (l !is r) {
+ return l - r;
+ }
+
+ for (int i = 0; i < l; i++) {
+ int compareTo = compare(left[i], right[i]);
+
+ if (compareTo !is 0) {
+ return compareTo;
+ }
+ }
+
+ return 0;
+ }
+ }
+
+// /**
+// * Compares two lists -- account for null
. The lists must
+// * contain comparable objects.
+// *
+// * @param left
+// * The left list to compare; may be null
. This
+// * list must only contain instances of Comparable
.
+// * @param right
+// * The right list to compare; may be null
. This
+// * list must only contain instances of Comparable
.
+// * @return The result of the comparison. null
is considered
+// * to be the least possible value. A shorter list is considered less
+// * than a longer list.
+// */
+// public static final int compare(SeqView!(Object) left, SeqView!(Object) right) {
+// if (left is null && right is null) {
+// return 0;
+// } else if (left is null) {
+// return -1;
+// } else if (right is null) {
+// return 1;
+// } else {
+// int l = left.size();
+// int r = right.size();
+//
+// if (l !is r) {
+// return l - r;
+// }
+//
+// for (int i = 0; i < l; i++) {
+// int compareTo = compare((Comparable) left.get(i),
+// (Comparable) right.get(i));
+//
+// if (compareTo !is 0) {
+// return compareTo;
+// }
+// }
+//
+// return 0;
+// }
+// }
+
+ /**
+ * Tests whether the first array ends with the second array.
+ *
+ * @param left
+ * The array to check (larger); may be null
.
+ * @param right
+ * The array that should be a subsequence (smaller); may be
+ * null
.
+ * @param equals
+ * Whether the two array are allowed to be equal.
+ * @return true
if the second array is a subsequence of the
+ * array list, and they share end elements.
+ */
+ public static final bool endsWith(Object[] left,
+ Object[] right, bool equals) {
+ if (left is null || right is null) {
+ return false;
+ }
+
+ int l = left.length;
+ int r = right.length;
+
+ if (r > l || !equals && r is l) {
+ return false;
+ }
+
+ for (int i = 0; i < r; i++) {
+ if (!Util.opEquals(left[l - i - 1], right[r - i - 1])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks whether the two objects are null
-- allowing for
+ * null
.
+ *
+ * @param left
+ * The left object to compare; may be null
.
+ * @param right
+ * The right object to compare; may be null
.
+ * @return true
if the two objects are equivalent;
+ * false
otherwise.
+ */
+ public static final bool opEquals(Object left, Object right) {
+ return left is null ? right is null : ((right !is null) && left
+ .opEquals(right));
+ }
+
+ /**
+ * Tests whether two arrays of objects are equal to each other. The arrays
+ * must not be null
, but their elements may be
+ * null
.
+ *
+ * @param leftArray
+ * The left array to compare; may be null
, and
+ * may be empty and may contain null
elements.
+ * @param rightArray
+ * The right array to compare; may be null
, and
+ * may be empty and may contain null
elements.
+ * @return true
if the arrays are equal length and the
+ * elements at the same position are equal; false
+ * otherwise.
+ */
+ public static final bool opEquals(Object[] leftArray,
+ Object[] rightArray) {
+ if (leftArray is rightArray) {
+ return true;
+ }
+
+ if (leftArray is null) {
+ return (rightArray is null);
+ } else if (rightArray is null) {
+ return false;
+ }
+
+ if (leftArray.length !is rightArray.length) {
+ return false;
+ }
+
+ for (int i = 0; i < leftArray.length; i++) {
+ Object left = leftArray[i];
+ Object right = rightArray[i];
+ bool equal = ((left is null) ? (right is null) : (left.opEquals(right))) !is 0;
+ if (!equal) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Provides a hash code based on the given integer value.
+ *
+ * @param i
+ * The integer value
+ * @return i
+ */
+ public static final hash_t toHash(int i) {
+ return i;
+ }
+
+ /**
+ * Provides a hash code for the object -- defending against
+ * null
.
+ *
+ * @param object
+ * The object for which a hash code is required.
+ * @return object.hashCode
or 0
if
+ * object
if null
.
+ */
+ public static final hash_t toHash( Object object) {
+ return object !is null ? object.toHash() : 0;
+ }
+
+ /**
+ * Computes the hash code for an array of objects, but with defense against
+ * null
.
+ *
+ * @param objects
+ * The array of objects for which a hash code is needed; may be
+ * null
.
+ * @return The hash code for objects
; or 0
if
+ * objects
is null
.
+ */
+ public static final hash_t toHash(Object[] objects) {
+ if (objects is null) {
+ return 0;
+ }
+
+ int hashCode = 89;
+ for (int i = 0; i < objects.length; i++) {
+ final Object object = objects[i];
+ if (object !is null) {
+ hashCode = hashCode * 31 + object.toHash();
+ }
+ }
+
+ return hashCode;
+ }
+
+ /**
+ * Checks whether the second array is a subsequence of the first array, and
+ * that they share common starting elements.
+ *
+ * @param left
+ * The first array to compare (large); may be null
.
+ * @param right
+ * The second array to compare (small); may be null
.
+ * @param equals
+ * Whether it is allowed for the two arrays to be equivalent.
+ * @return true
if the first arrays starts with the second
+ * list; false
otherwise.
+ */
+ public static final bool startsWith(Object[] left,
+ Object[] right, bool equals) {
+ if (left is null || right is null) {
+ return false;
+ }
+
+ int l = left.length;
+ int r = right.length;
+
+ if (r > l || !equals && r is l) {
+ return false;
+ }
+
+ for (int i = 0; i < r; i++) {
+ if (!opEquals(left[i], right[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Converts an array into a string representation that is suitable for
+ * debugging.
+ *
+ * @param array
+ * The array to convert; may be null
.
+ * @return The string representation of the array; never null
.
+ */
+ public static final String toString(Object[] array) {
+ if (array is null) {
+ return "null"; //$NON-NLS-1$
+ }
+
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append('[');
+
+ final int length = array.length;
+ for (int i = 0; i < length; i++) {
+ if (i !is 0) {
+ buffer.append(',');
+ }
+ Object object = array[i];
+ String element = (object is null ) ? "null" : object.toString;
+ buffer.append(element);
+ }
+ buffer.append(']');
+
+ return buffer.toString();
+ }
+
+ /**
+ * Provides a translation of a particular key from the resource bundle.
+ *
+ * @param resourceBundle
+ * The key to look up in the resource bundle; should not be
+ * null
.
+ * @param key
+ * The key to look up in the resource bundle; should not be
+ * null
.
+ * @param defaultString
+ * The value to return if the resource cannot be found; may be
+ * null
.
+ * @return The value of the translated resource at key
. If
+ * the key cannot be found, then it is simply the
+ * defaultString
.
+ */
+ public static final String translateString(
+ ResourceBundle resourceBundle, String key,
+ String defaultString) {
+ if (resourceBundle !is null && key !is null) {
+ try {
+ String translatedString = resourceBundle.getString(key);
+
+ if (translatedString !is null) {
+ return translatedString;
+ }
+ } catch (MissingResourceException eMissingResource) {
+ // Such is life. We'll return the key
+ }
+ }
+
+ return defaultString;
+ }
+
+ /**
+ * This class should never be constructed.
+ */
+ private this() {
+ // Not allowed.
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/AbstractListViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/AbstractListViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,579 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Chris Longfield Object
).
+ */
+ private Seq!(Object) listMap;
+
+ /**
+ * Adds the given string to the underlying widget at the given index
+ *
+ * @param string the string to add
+ * @param index position to insert the string into
+ */
+ protected abstract void listAdd(String string, int index);
+
+ /**
+ * Sets the text of the item at the given index in the underlying widget.
+ *
+ * @param index index to modify
+ * @param string new text
+ */
+ protected abstract void listSetItem(int index, String string);
+
+ /**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the underlying widget. The array is empty if no items are selected.
+ * null
if the index is out of range.
+ *
+ * @param index the zero-based index
+ * @return the element at the given index, or null
if the
+ * index is out of range
+ */
+ public Object getElementAt(int index) {
+ if (index >= 0 && index < listMap.size()) {
+ return listMap.get(index);
+ }
+ return null;
+ }
+
+ /**
+ * The list viewer implementation of this Viewer
framework
+ * method returns the label provider, which in the case of list
+ * viewers will be an instance of ILabelProvider
.
+ */
+ public IBaseLabelProvider getLabelProvider() {
+ return super.getLabelProvider();
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Viewer.
+ */
+ /* (non-Javadoc)
+ * Method declared on StructuredViewer.
+ */
+ protected SeqView!(Object) getSelectionFromWidget() {
+ int[] ixs = listGetSelectionIndices();
+ ArraySeq!(Object) list = new ArraySeq!(Object);
+ list.capacity(ixs.length);
+ for (int i = 0; i < ixs.length; i++) {
+ Object e = getElementAt(ixs[i]);
+ if (e !is null) {
+ list.append(e);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * @param element the element to insert
+ * @return the index where the item should be inserted.
+ */
+ protected int indexForElement(Object element) {
+ ViewerComparator comparator = getComparator();
+ if (comparator is null) {
+ return listGetItemCount();
+ }
+ int count = listGetItemCount();
+ int min = 0, max = count - 1;
+ while (min <= max) {
+ int mid = (min + max) / 2;
+ Object data = listMap.get(mid);
+ int compare = comparator.compare(this, data, element);
+ if (compare is 0) {
+ // find first item > element
+ while (compare is 0) {
+ ++mid;
+ if (mid >= count) {
+ break;
+ }
+ data = listMap.get(mid);
+ compare = comparator.compare(this, data, element);
+ }
+ return mid;
+ }
+ if (compare < 0) {
+ min = mid + 1;
+ } else {
+ max = mid - 1;
+ }
+ }
+ return min;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Viewer.
+ */
+ protected void inputChanged(Object input, Object oldInput) {
+ listMap.clear();
+ Object[] children = getSortedChildren(getRoot());
+ int size = children.length;
+
+ listRemoveAll();
+ String[] labels = new String[size];
+ for (int i = 0; i < size; i++) {
+ Object el = children[i];
+ labels[i] = getLabelProviderText(cast(ILabelProvider) getLabelProvider(),el);
+ listMap.append(el);
+ mapElement(el, getControl()); // must map it, since findItem only looks in map, if enabled
+ }
+ listSetItems(labels);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on StructuredViewer.
+ */
+ protected void internalRefresh(Object element) {
+ Control list = getControl();
+ if (element is null || opEquals(element, getRoot())) {
+ // the parent
+ if (listMap !is null) {
+ listMap.clear();
+ }
+ unmapAllElements();
+ auto selection = getSelectionFromWidget();
+
+ int topIndex = -1;
+ if (selection is null || selection.drained()) {
+ topIndex = listGetTopIndex();
+ }
+
+ list.setRedraw(false);
+ listRemoveAll();
+
+ Object[] children = getSortedChildren(getRoot());
+ String[] items = new String[children.length];
+
+ ILabelProvider labelProvider = cast(ILabelProvider) getLabelProvider();
+
+ for (int i = 0; i < items.length; i++) {
+ Object el = children[i];
+ items[i] = getLabelProviderText(labelProvider, el);
+ listMap.append(el);
+ mapElement(el, list); // must map it, since findItem only looks in map, if enabled
+ }
+
+ listSetItems(items);
+ list.setRedraw(true);
+
+ if (topIndex is -1) {
+ setSelectionToWidget(selection, false);
+ } else {
+ listSetTopIndex(Math.min(topIndex, children.length));
+ }
+ } else {
+ doUpdateItem(list, element, true);
+ }
+ }
+
+ /**
+ * Returns the index of the item currently at the top of the viewable area.
+ * Viewer
framework
+ * method ensures that the given label provider is an instance of
+ * ILabelProvider
.
+ *
+ * The optional interfaces {@link IColorProvider} and
+ * {@link IFontProvider} have no effect for this type of viewer
+ */
+ public void setLabelProvider(IBaseLabelProvider labelProvider) {
+ Assert.isTrue( null !is cast(ILabelProvider)labelProvider );
+ super.setLabelProvider(labelProvider);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on StructuredViewer.
+ */
+ protected void setSelectionToWidget(SeqView!(Object) in_, bool reveal) {
+ if (in_ is null || in_.size() is 0) { // clear selection
+ listDeselectAll();
+ } else {
+ int n = in_.size();
+ int[] ixs = new int[n];
+ int count = 0;
+ for (int i = 0; i < n; ++i) {
+ Object el = in_.get(i);
+ int ix = getElementIndex(el);
+ if (ix >= 0) {
+ ixs[count++] = ix;
+ }
+ }
+ if (count < n) {
+ System.arraycopy(ixs, 0, ixs = new int[count], 0, count);
+ }
+ listSetSelection(ixs);
+ if (reveal) {
+ listShowSelection();
+ }
+ }
+ }
+
+ /**
+ * Returns the index of the given element in listMap, or -1 if the element cannot be found.
+ * As of 3.3, uses the element comparer if available.
+ *
+ * @param element
+ * @return the index
+ */
+ int getElementIndex(Object element) {
+ IElementComparer comparer = getComparer();
+ if (comparer is null) {
+ int idx = 0;
+ foreach( e; listMap ){
+ if( e == element ){
+ return idx;
+ }
+ idx++;
+ }
+ return -1;
+ }
+ int size = listMap.size();
+ for (int i = 0; i < size; i++) {
+ if (comparer.opEquals(element, listMap.get(i)))
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * @param element
+ * @return true if listMap contains the given element
+ *
+ * @since 3.3
+ */
+ private bool listMapContains(Object element) {
+ return getElementIndex(element) !is -1;
+ }
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/AbstractTableViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/AbstractTableViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,1362 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl null
if it could not be found
+ */
+ protected Object resolveElement(int index) {
+
+ Object element = null;
+ if (index < cachedElements.length) {
+ element = cachedElements[index];
+ }
+
+ return element;
+ }
+
+ /**
+ * A non visible item has been added.
+ *
+ * @param element
+ * @param index
+ */
+ public void notVisibleAdded(Object element, int index) {
+
+ int requiredCount = doGetItemCount() + 1;
+
+ Object[] newCache = new Object[requiredCount];
+ System.arraycopy(cachedElements, 0, newCache, 0, index);
+ if (index < cachedElements.length) {
+ System.arraycopy(cachedElements, index, newCache, index + 1,
+ cachedElements.length - index);
+ }
+ newCache[index] = element;
+ cachedElements = newCache;
+
+ doSetItemCount(requiredCount);
+ }
+
+ /**
+ * The elements with the given indices need to be removed from the
+ * cache.
+ *
+ * @param indices
+ */
+ public void removeIndices(int[] indices) {
+ if (indices.length is 1) {
+ removeIndicesFromTo(indices[0], indices[0]);
+ }
+ int requiredCount = doGetItemCount() - indices.length;
+
+ tango.core.Array.sort( indices );
+ Object[] newCache = new Object[requiredCount];
+ int indexInNewCache = 0;
+ int nextToSkip = 0;
+ for (int i = 0; i < cachedElements.length; i++) {
+ if (nextToSkip < indices.length && i is indices[nextToSkip]) {
+ nextToSkip++;
+ } else {
+ newCache[indexInNewCache++] = cachedElements[i];
+ }
+ }
+ cachedElements = newCache;
+ }
+
+ /**
+ * The elements between the given indices (inclusive) need to be removed
+ * from the cache.
+ *
+ * @param from
+ * @param to
+ */
+ public void removeIndicesFromTo(int from, int to) {
+ int indexAfterTo = to + 1;
+ Object[] newCache = new Object[cachedElements.length
+ - (indexAfterTo - from)];
+ System.arraycopy(cachedElements, 0, newCache, 0, from);
+ if (indexAfterTo < cachedElements.length) {
+ System.arraycopy(cachedElements, indexAfterTo, newCache, from,
+ cachedElements.length - indexAfterTo);
+ }
+ }
+
+ /**
+ * @param element
+ * @return the index of the element in the cache, or null
+ */
+ public int find(Object element) {
+ int res = tango.core.Array.find( cachedElements, element );
+ if( res is cachedElements.length ) res = -1;
+ return res;
+ }
+
+ /**
+ * @param count
+ */
+ public void adjustCacheSize(int count) {
+ if (count is cachedElements.length) {
+ return;
+ } else if (count < cachedElements.length) {
+ Object[] newCache = new Object[count];
+ System.arraycopy(cachedElements, 0, newCache, 0, count);
+ cachedElements = newCache;
+ } else {
+ Object[] newCache = new Object[count];
+ System.arraycopy(cachedElements, 0, newCache, 0,
+ cachedElements.length);
+ cachedElements = newCache;
+ }
+ }
+
+ }
+
+ private VirtualManager virtualManager;
+
+ /**
+ * Create the new viewer for table like widgets
+ */
+ public this() {
+ super();
+ }
+
+ protected void hookControl(Control control) {
+ super.hookControl(control);
+ initializeVirtualManager(getControl().getStyle());
+ }
+
+ /**
+ * Initialize the virtual manager to manage the virtual state if the table
+ * is VIRTUAL. If not use the default no-op version.
+ *
+ * @param style
+ */
+ private void initializeVirtualManager(int style) {
+ if ((style & DWT.VIRTUAL) is 0) {
+ return;
+ }
+
+ virtualManager = new VirtualManager();
+ }
+
+ /**
+ * Adds the given elements to this table viewer. If this viewer does not
+ * have a sorter, the elements are added at the end in the order given;
+ * otherwise the elements are inserted at appropriate positions.
+ * null
if the index is out of range.
+ * null
if the
+ * index is out of range
+ */
+ public Object getElementAt(int index) {
+ if (index >= 0 && index < doGetItemCount()) {
+ Item i = doGetItem(index);
+ if (i !is null) {
+ return i.getData();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * The table viewer implementation of this Viewer
framework
+ * method returns the label provider, which in the case of table viewers
+ * will be an instance of either ITableLabelProvider
or
+ * ILabelProvider
. If it is an
+ * ITableLabelProvider
, then it provides a separate label
+ * text and image for each column. If it is an ILabelProvider
,
+ * then it provides only the label text and image for the first column, and
+ * any remaining columns are blank.
+ */
+ public IBaseLabelProvider getLabelProvider() {
+ return super.getLabelProvider();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.StructuredViewer#getSelectionFromWidget()
+ */
+ protected SeqView!(Object) getSelectionFromWidget() {
+ if (virtualManager !is null) {
+ return getVirtualSelection();
+ }
+ Widget[] items = doGetSelection();
+ auto list = new ArraySeq!(Object);
+ list.capacity(items.length);
+ for (int i = 0; i < items.length; i++) {
+ Widget item = items[i];
+ Object e = item.getData();
+ if (e !is null) {
+ list.append(e);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Get the virtual selection. Avoid calling DWT whenever possible to prevent
+ * extra widget creation.
+ *
+ * @return List of Object
+ */
+
+ private SeqView!(Object) getVirtualSelection() {
+
+ auto result = new ArraySeq!(Object);
+ int[] selectionIndices = doGetSelectionIndices();
+ if (auto lazy_ = cast(ILazyContentProvider) getContentProvider() ) {
+ for (int i = 0; i < selectionIndices.length; i++) {
+ int selectionIndex = selectionIndices[i];
+ lazy_.updateElement(selectionIndex);// Start the update
+ Object element = doGetItem(selectionIndex).getData();
+ // Only add the element if it got updated.
+ // If this is done deferred the selection will
+ // be incomplete until selection is finished.
+ if (element !is null) {
+ result.append(element);
+ }
+ }
+ } else {
+ for (int i = 0; i < selectionIndices.length; i++) {
+ Object element = null;
+ // See if it is cached
+ int selectionIndex = selectionIndices[i];
+ if (selectionIndex < virtualManager.cachedElements.length) {
+ element = virtualManager.cachedElements[selectionIndex];
+ }
+ if (element is null) {
+ // Not cached so try the item's data
+ Item item = doGetItem(selectionIndex);
+ element = item.getData();
+ }
+ if (element !is null) {
+ result.append(element);
+ }
+ }
+
+ }
+ return result;
+ }
+
+ /**
+ * @param element
+ * the element to insert
+ * @return the index where the item should be inserted.
+ */
+ protected int indexForElement(Object element) {
+ ViewerComparator comparator = getComparator();
+ if (comparator is null) {
+ return doGetItemCount();
+ }
+ int count = doGetItemCount();
+ int min = 0, max = count - 1;
+ while (min <= max) {
+ int mid = (min + max) / 2;
+ Object data = doGetItem(mid).getData();
+ int compare = comparator.compare(this, data, element);
+ if (compare is 0) {
+ // find first item > element
+ while (compare is 0) {
+ ++mid;
+ if (mid >= count) {
+ break;
+ }
+ data = doGetItem(mid).getData();
+ compare = comparator.compare(this, data, element);
+ }
+ return mid;
+ }
+ if (compare < 0) {
+ min = mid + 1;
+ } else {
+ max = mid - 1;
+ }
+ }
+ return min;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.Viewer#inputChanged(java.lang.Object,
+ * java.lang.Object)
+ */
+ protected void inputChanged(Object input, Object oldInput) {
+ getControl().setRedraw(false);
+ try {
+ preservingSelection(new class Runnable {
+ public void run() {
+ internalRefresh(getRoot());
+ }
+ });
+ } finally {
+ getControl().setRedraw(true);
+ }
+ }
+
+ /**
+ * Inserts the given element into this table viewer at the given position.
+ * If this viewer has a sorter, the position is ignored and the element is
+ * inserted at the correct position in the sort order.
+ * DWT.VIRTUAL
style, these attributes are requested
+ * again as needed.
+ *
+ * @since 3.3
+ */
+ protected abstract void doClearAll();
+
+ /**
+ * Resets the given item in the receiver. The text, icon and other attributes
+ * of the item are set to their default values.
+ *
+ * @param item the item to reset
+ *
+ * @since 3.3
+ */
+ protected abstract void doResetItem(Item item);
+
+ /**
+ * Removes the items from the receiver which are between the given
+ * zero-relative start and end indices (inclusive).
+ *
+ * @param start
+ * the start of the range
+ * @param end
+ * the end of the range
+ *
+ * @exception IllegalArgumentException -
+ * if either the start or end are not between 0 and the
+ * number of elements in the list minus 1 (inclusive)
+ *
+ * @since 3.3
+ */
+ protected abstract void doRemove(int start, int end);
+
+ /**
+ * Removes all of the items from the receiver.
+ *
+ * @since 3.3
+ */
+ protected abstract void doRemoveAll();
+
+ /**
+ * Removes the items from the receiver's list at the given zero-relative
+ * indices.
+ *
+ * @param indices
+ * the array of indices of the items
+ *
+ * @exception IllegalArgumentException -
+ * if the array is null, or if any of the indices is not
+ * between 0 and the number of elements in the list minus 1
+ * (inclusive)
+ *
+ * @since 3.3
+ */
+ protected abstract void doRemove(int[] indices);
+
+ /**
+ * Shows the item. If the item is already showing in the receiver, this
+ * method simply returns. Otherwise, the items are scrolled until the item
+ * is visible.
+ *
+ * @param item
+ * the item to be shown
+ *
+ * @exception IllegalArgumentException -
+ * if the item is null
+ *
+ * @since 3.3
+ */
+ protected abstract void doShowItem(Item item);
+
+ /**
+ * Deselects all selected items in the receiver.
+ *
+ * @since 3.3
+ */
+ protected abstract void doDeselectAll();
+
+ /**
+ * Sets the receiver's selection to be the given array of items. The current
+ * selection is cleared before the new items are selected.
+ * DWT.VIRTUAL
style, these
+ * attributes are requested again as needed.
+ *
+ * @param index
+ * the index of the item to clear
+ *
+ * @exception IllegalArgumentException -
+ * if the index is not between 0 and the number of elements
+ * in the list minus 1 (inclusive)
+ *
+ * @see DWT#VIRTUAL
+ * @see DWT#SetData
+ *
+ * @since 3.3
+ */
+ protected abstract void doClear(int index);
+
+
+
+ /**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is not cleared before the new items are selected.
+ * setUseHashLookup(true)
.
+ * ITreeContentProvider
or (as of 3.2, to support
+ * multiple equal elements) ITreePathContentProvider
.
+ * TreeListener
).
+ */
+ private ListenerList treeListeners;
+
+ /**
+ * The level to which the tree is automatically expanded each time the
+ * viewer's input is changed (that is, by setInput
). A value
+ * of 0 means that auto-expand is off.
+ *
+ * @see #setAutoExpandLevel
+ */
+ private int expandToLevel_ = 0;
+
+ /**
+ * Safe runnable used to update an item.
+ */
+ class UpdateItemSafeRunnable : SafeRunnable {
+ private Object element;
+
+ private Item item;
+
+ this(Item item, Object element) {
+ this.item = item;
+ this.element = element;
+ }
+
+ public void run() {
+ doUpdateItem(item, element);
+ }
+
+ }
+
+ /**
+ * Creates an abstract tree viewer. The viewer has no input, no content
+ * provider, a default label provider, no sorter, no filters, and has
+ * auto-expand turned off.
+ */
+ protected this() {
+ treeListeners = new ListenerList();
+ // do nothing
+ }
+
+ /**
+ * Adds the given child elements to this viewer as children of the given
+ * parent element. If this viewer does not have a sorter, the elements are
+ * added at the end of the parent's list of children in the order given;
+ * otherwise, the elements are inserted at the appropriate positions.
+ * null
+ *
+ * @param path
+ * the path
+ * @return {@link Widget} the item at that path
+ */
+ private Widget internalFindItem(TreePath path) {
+ Widget[] widgets = findItems(path.getLastSegment());
+ for (int i = 0; i < widgets.length; i++) {
+ Widget widget = widgets[i];
+ if ( auto item = cast(Item)widget ) {
+ TreePath p = getTreePathFromItem(item);
+ if (p.opEquals(path)) {
+ return widget;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds the given child elements to this viewer as children of the given
+ * parent element.
+ * true
if the element matches.
+ */
+ private bool itemExists(Item[] items, Object element) {
+ if (usingElementMap()) {
+ Widget[] existingItems = findItems(element);
+ // optimization for two common cases
+ if (existingItems.length is 0) {
+ return false;
+ } else if (existingItems.length is 1) {
+ if (items.length > 0 && null !is cast(Item)existingItems[0] ) {
+ Item existingItem = cast(Item) existingItems[0];
+ return getParentItem(existingItem) is getParentItem(items[0]);
+ }
+ }
+ }
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].getData().opEquals(element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the index where the item should be inserted. It uses sorter to
+ * determine the correct position, if sorter is not assigned, returns the
+ * index of the element after the last.
+ *
+ * @param items
+ * the items to search
+ * @param comparator
+ * The comparator to use.
+ * @param lastInsertion
+ * the start index to start search for position from this allows
+ * optimizing search for multiple elements that are sorted
+ * themselves.
+ * @param element
+ * element to find position for.
+ * @param parentPath
+ * the tree path for the element's parent or null
+ * if the element is a root element or the sorter is not a
+ * {@link TreePathViewerSorter}
+ * @return the index to use when inserting the element.
+ *
+ */
+
+ private int insertionPosition(Item[] items, ViewerComparator comparator,
+ int lastInsertion, Object element, TreePath parentPath) {
+
+ int size = items.length;
+ if (comparator is null) {
+ return size;
+ }
+ int min = lastInsertion, max = size - 1;
+
+ while (min <= max) {
+ int mid = (min + max) / 2;
+ Object data = items[mid].getData();
+ int compare = internalCompare(comparator, parentPath, data, element);
+ if (compare is 0) {
+ return mid;// Return if we already match
+ }
+ if (compare < 0) {
+ min = mid + 1;
+ } else {
+ max = mid - 1;
+ }
+ }
+ return min;
+
+ }
+
+ /**
+ * Returns the index where the item should be inserted. It uses sorter to
+ * determine the correct position, if sorter is not assigned, returns the
+ * index of the element after the last.
+ *
+ * @param parent
+ * The parent widget
+ * @param sorter
+ * The sorter to use.
+ * @param startIndex
+ * the start index to start search for position from this allows
+ * optimizing search for multiple elements that are sorted
+ * themselves.
+ * @param element
+ * element to find position for.
+ * @param currentSize
+ * the current size of the collection
+ * @return the index to use when inserting the element.
+ *
+ */
+
+ /**
+ * Returns the index where the item should be inserted.
+ *
+ * @param parent
+ * The parent widget the element will be inserted into.
+ * @param element
+ * The element to insert.
+ * @return the index of the element
+ */
+ protected int indexForElement(Widget parent, Object element) {
+ ViewerComparator comparator = getComparator();
+ TreePath parentPath = internalGetSorterParentPath(parent, comparator);
+
+ Item[] items = getChildren(parent);
+ int count = items.length;
+
+ if (comparator is null) {
+ return count;
+ }
+ int min = 0, max = count - 1;
+
+ while (min <= max) {
+ int mid = (min + max) / 2;
+ Object data = items[mid].getData();
+ int compare = internalCompare(comparator, parentPath, data, element);
+ if (compare is 0) {
+ // find first item > element
+ while (compare is 0) {
+ ++mid;
+ if (mid >= count) {
+ break;
+ }
+ data = items[mid].getData();
+ compare = internalCompare(comparator, parentPath, data,
+ element);
+ }
+ return mid;
+ }
+ if (compare < 0) {
+ min = mid + 1;
+ } else {
+ max = mid - 1;
+ }
+ }
+ return min;
+ }
+
+ /**
+ * Return the tree path that should be used as the parent path for the given
+ * widget and sorter. A null
is returned if either the sorter
+ * is not a {@link TreePathViewerSorter} or if the parent widget is not an
+ * {@link Item} (i.e. is the root of the tree).
+ *
+ * @param parent
+ * the parent widget
+ * @param comparator
+ * the sorter
+ * @return the tree path that should be used as the parent path for the
+ * given widget and sorter
+ */
+ private TreePath internalGetSorterParentPath(Widget parent,
+ ViewerComparator comparator) {
+ TreePath path;
+ if ( null !is cast(TreePathViewerSorter)comparator
+ && null !is cast(Item)parent ) {
+ Item item = cast(Item) parent;
+ path = getTreePathFromItem(item);
+ } else {
+ path = null;
+ }
+ return path;
+ }
+
+ /**
+ * Compare the two elements using the given sorter. If the sorter is a
+ * {@link TreePathViewerSorter}, the provided tree path will be used. If
+ * the tree path is null and the sorter is a tree path sorter, then the
+ * elements are root elements
+ *
+ * @param comparator
+ * the sorter
+ * @param parentPath
+ * the path of the elements' parent
+ * @param e1
+ * the first element
+ * @param e2
+ * the second element
+ * @return the result of comparing the two elements
+ */
+ private int internalCompare(ViewerComparator comparator,
+ TreePath parentPath, Object e1, Object e2) {
+ if ( auto tpvs = cast(TreePathViewerSorter) comparator ) {
+ return tpvs.compare(this, parentPath, e1, e2);
+ }
+ return comparator.compare(this, e1, e2);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.StructuredViewer#getSortedChildren(java.lang.Object)
+ */
+ protected Object[] getSortedChildren(Object parentElementOrTreePath) {
+ Object[] result = getFilteredChildren(parentElementOrTreePath);
+ ViewerComparator comparator = getComparator();
+ if (parentElementOrTreePath !is null
+ && null !is cast(TreePathViewerSorter) comparator ) {
+ TreePathViewerSorter tpvs = cast(TreePathViewerSorter) comparator;
+
+ // be sure we're not modifying the original array from the model
+ result = result.dup;
+
+ TreePath path = null;
+ if ( auto p = cast(TreePath) parentElementOrTreePath ) {
+ path = p;
+ } else {
+ Object parent = parentElementOrTreePath;
+ Widget w = internalGetWidgetToSelect(parent);
+ if (w !is null) {
+ path = internalGetSorterParentPath(w, comparator);
+ }
+ }
+ tpvs.sort(this, path, result);
+ } else if (comparator !is null) {
+ // be sure we're not modifying the original array from the model
+ result = result.dup;
+ comparator.sort(this, result);
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.StructuredViewer#getFilteredChildren(java.lang.Object)
+ */
+ protected Object[] getFilteredChildren(Object parentElementOrTreePath) {
+ Object[] result = getRawChildren(parentElementOrTreePath);
+ ViewerFilter[] filters = getFilters();
+ for (int i = 0; i < filters.length; i++) {
+ ViewerFilter filter = filters[i];
+ result = filter.filter(this, parentElementOrTreePath, result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds the given child element to this viewer as a child of the given
+ * parent element. If this viewer does not have a sorter, the element is
+ * added at the end of the parent's list of children; otherwise, the element
+ * is inserted at the appropriate position.
+ * collapseToLevel(ALL_LEVELS)
.
+ */
+ public void collapseAll() {
+ Object root = getRoot();
+ if (root !is null) {
+ collapseToLevel(root, ALL_LEVELS);
+ }
+ }
+
+ /**
+ * Collapses the subtree rooted at the given element or tree path to the
+ * given level.
+ *
+ * @param elementOrTreePath
+ * the element or tree path
+ * @param level
+ * non-negative level, or ALL_LEVELS
to collapse
+ * all levels of the tree
+ */
+ public void collapseToLevel(Object elementOrTreePath, int level) {
+ Assert.isNotNull(elementOrTreePath);
+ Widget w = internalGetWidgetToSelect(elementOrTreePath);
+ if (w !is null) {
+ internalCollapseToLevel(w, level);
+ }
+ }
+
+ /**
+ * Creates all children for the given widget.
+ * widget.getData()
returns the element corresponding to the
+ * node. Note: the node is not visually expanded! You may have to call
+ * parent.setExpanded(true)
.
+ * AbstractTreeViewer
implementation of this method also
+ * recurses over children of the corresponding element.
+ */
+ protected void disassociate(Item item) {
+ super.disassociate(item);
+ // recursively unmapping the items is only required when
+ // the hash map is used. In the other case disposing
+ // an item will recursively dispose its children.
+ if (usingElementMap()) {
+ disassociateChildren(item);
+ }
+ }
+
+ /**
+ * Disassociates the children of the given DWT item from their corresponding
+ * elements.
+ *
+ * @param item
+ * the widget
+ */
+ private void disassociateChildren(Item item) {
+ Item[] items = getChildren(item);
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].getData() !is null) {
+ disassociate(items[i]);
+ }
+ }
+ }
+
+ /* (non-Javadoc) Method declared on StructuredViewer. */
+ protected Widget doFindInputItem(Object element) {
+ // compare with root
+ Object root = getRoot();
+ if (root is null) {
+ return null;
+ }
+
+ if (opEquals(root, element)) {
+ return getControl();
+ }
+ return null;
+ }
+
+ /* (non-Javadoc) Method declared on StructuredViewer. */
+ protected Widget doFindItem(Object element) {
+ // compare with root
+ Object root = getRoot();
+ if (root is null) {
+ return null;
+ }
+
+ Item[] items = getChildren(getControl());
+ if (items !is null) {
+ for (int i = 0; i < items.length; i++) {
+ Widget o = internalFindItem(items[i], element);
+ if (o !is null) {
+ return o;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Copies the attributes of the given element into the given DWT item.
+ *
+ * @param item
+ * the DWT item
+ * @param element
+ * the element
+ */
+ protected void doUpdateItem(Item item, Object element) {
+ if (item.isDisposed()) {
+ unmapElement(element, item);
+ return;
+ }
+
+ int columnCount = doGetColumnCount();
+ if (columnCount is 0)// If no columns are created then fake one
+ columnCount = 1;
+
+ ViewerRow viewerRowFromItem = getViewerRowFromItem(item);
+
+ bool isVirtual = (getControl().getStyle() & DWT.VIRTUAL) !is 0;
+
+ // If the control is virtual, we cannot use the cached viewer row object. See bug 188663.
+ if (isVirtual) {
+ viewerRowFromItem = cast(ViewerRow) viewerRowFromItem.clone();
+ }
+
+ for (int column = 0; column < columnCount; column++) {
+ ViewerColumn columnViewer = getViewerColumn(column);
+ ViewerCell cellToUpdate = updateCell(viewerRowFromItem, column,
+ element);
+
+ // If the control is virtual, we cannot use the cached cell object. See bug 188663.
+ if (isVirtual) {
+ cellToUpdate = new ViewerCell(cellToUpdate.getViewerRow(), cellToUpdate.getColumnIndex(), element);
+ }
+
+ columnViewer.refresh(cellToUpdate);
+
+ // clear cell (see bug 201280)
+ updateCell(null, 0, null);
+
+ // As it is possible for user code to run the event
+ // loop check here.
+ if (item.isDisposed()) {
+ unmapElement(element, item);
+ return;
+ }
+
+ }
+ }
+
+ /**
+ * Returns true
if the given list and array of items refer to
+ * the same model elements. Order is unimportant.
+ * true
if the refer to the same elements,
+ * false
otherwise
+ *
+ * @since 3.1 in TreeViewer, moved to AbstractTreeViewer in 3.3
+ */
+ protected bool isSameSelection(SeqView!(Item) items, Item[] current) {
+ // If they are not the same size then they are not equivalent
+ int n = items.size();
+ if (n !is current.length) {
+ return false;
+ }
+
+ CustomHashtable itemSet = newHashtable(n * 2 + 1);
+ foreach( item; items ){
+ Object element = item.getData();
+ itemSet.put(element, element);
+ }
+
+ // Go through the items of the current collection
+ // If there is a mismatch return false
+ for (int i = 0; i < current.length; i++) {
+ if (current[i].getData() is null
+ || !itemSet.containsKey(current[i].getData())) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+
+ /* (non-Javadoc) Method declared on StructuredViewer. */
+ protected void doUpdateItem(Widget widget, Object element, bool fullMap) {
+ bool oldBusy = busy;
+ busy = true;
+ try {
+ if ( auto item = cast(Item)widget ) {
+
+ // ensure that back pointer is correct
+ if (fullMap) {
+ associate(element, item);
+ } else {
+ Object data = item.getData();
+ if (data !is null) {
+ unmapElement(data, item);
+ }
+ item.setData(element);
+ mapElement(element, item);
+ }
+
+ // update icon and label
+ SafeRunnable.run(new UpdateItemSafeRunnable(item, element));
+ }
+ } finally {
+ busy = oldBusy;
+ }
+ }
+
+ /**
+ * Expands all nodes of the viewer's tree, starting with the root. This
+ * method is equivalent to expandToLevel(ALL_LEVELS)
.
+ */
+ public void expandAll() {
+ expandToLevel(ALL_LEVELS);
+ }
+
+ /**
+ * Expands the root of the viewer's tree to the given level.
+ *
+ * @param level
+ * non-negative level, or ALL_LEVELS
to expand all
+ * levels of the tree
+ */
+ public void expandToLevel(int level) {
+ expandToLevel(getRoot(), level);
+ }
+
+ /**
+ * Expands all ancestors of the given element or tree path so that the given
+ * element becomes visible in this viewer's tree control, and then expands
+ * the subtree rooted at the given element to the given level.
+ *
+ * @param elementOrTreePath
+ * the element
+ * @param level
+ * non-negative level, or ALL_LEVELS
to expand all
+ * levels of the tree
+ */
+ public void expandToLevel(Object elementOrTreePath, int level) {
+ if (isBusy())
+ return;
+ Widget w = internalExpand(elementOrTreePath, true);
+ if (w !is null) {
+ internalExpandToLevel(w, level);
+ }
+ }
+
+ /**
+ * Fires a tree collapsed event. Only listeners registered at the time this
+ * method is called are notified.
+ *
+ * @param event
+ * the tree expansion event
+ * @see ITreeViewerListener#treeCollapsed
+ */
+ protected void fireTreeCollapsed(TreeExpansionEvent event) {
+ Object[] listeners = treeListeners.getListeners();
+ for (int i = 0; i < listeners.length; ++i) {
+ SafeRunnable.run(new class SafeRunnable {
+ TreeExpansionEvent event_;
+ ITreeViewerListener l;
+ this(){
+ event_=event;
+ l = cast(ITreeViewerListener) listeners[i];
+ }
+ public void run() {
+ l.treeCollapsed(event_);
+ }
+ });
+ }
+ }
+
+ /**
+ * Fires a tree expanded event. Only listeners registered at the time this
+ * method is called are notified.
+ *
+ * @param event
+ * the tree expansion event
+ * @see ITreeViewerListener#treeExpanded
+ */
+ protected void fireTreeExpanded(TreeExpansionEvent event) {
+ Object[] listeners = treeListeners.getListeners();
+ for (int i = 0; i < listeners.length; ++i) {
+ SafeRunnable.run(new class SafeRunnable {
+ TreeExpansionEvent event_;
+ ITreeViewerListener l;
+ this(){
+ event_=event;
+ l = cast(ITreeViewerListener) listeners[i];
+ }
+ public void run() {
+ l.treeExpanded(event_);
+ }
+ });
+ }
+
+ }
+
+ /**
+ * Returns the auto-expand level.
+ *
+ * @return non-negative level, or ALL_LEVELS
if all levels of
+ * the tree are expanded automatically
+ * @see #setAutoExpandLevel
+ */
+ public int getAutoExpandLevel() {
+ return expandToLevel_;
+ }
+
+ /**
+ * Returns the DWT child items for the given DWT widget.
+ *
+ * @param widget
+ * the widget
+ * @return the child items
+ */
+ protected abstract Item[] getChildren(Widget widget);
+
+ /**
+ * Get the child for the widget at index. Note that the default
+ * implementation is not very efficient and should be overridden if this
+ * class is implemented.
+ *
+ * @param widget
+ * the widget to check
+ * @param index
+ * the index of the widget
+ * @return Item or null
if widget is not a type that can
+ * contain items.
+ *
+ * @throws ArrayIndexOutOfBoundsException
+ * if the index is not valid.
+ * @since 3.1
+ */
+ protected Item getChild(Widget widget, int index) {
+ return getChildren(widget)[index];
+ }
+
+ /**
+ * Returns whether the given DWT item is expanded or collapsed.
+ *
+ * @param item
+ * the item
+ * @return true
if the item is considered expanded and
+ * false
if collapsed
+ */
+ protected abstract bool getExpanded(Item item);
+
+ /**
+ * Returns a list of elements corresponding to expanded nodes in this
+ * viewer's tree, including currently hidden ones that are marked as
+ * expanded but are under a collapsed ancestor.
+ * setExpandedElements
is used during the restore.
+ * true
if the node is expanded, and
+ * false
if collapsed
+ */
+ public bool getExpandedState(Object elementOrTreePath) {
+ Assert.isNotNull(elementOrTreePath);
+ Widget item = internalGetWidgetToSelect(elementOrTreePath);
+ if ( auto i = cast(Item)item ) {
+ return getExpanded(i);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the number of child items of the given DWT control.
+ *
+ * @param control
+ * the control
+ * @return the number of children
+ */
+ protected abstract int getItemCount(Control control);
+
+ /**
+ * Returns the number of child items of the given DWT item.
+ *
+ * @param item
+ * the item
+ * @return the number of children
+ */
+ protected abstract int getItemCount(Item item);
+
+ /**
+ * Returns the child items of the given DWT item.
+ *
+ * @param item
+ * the item
+ * @return the child items
+ */
+ protected abstract Item[] getItems(Item item);
+
+ /**
+ * Returns the item after the given item in the tree, or null
+ * if there is no next item.
+ *
+ * @param item
+ * the item
+ * @param includeChildren
+ * true
if the children are considered in
+ * determining which item is next, and false
if
+ * subtrees are ignored
+ * @return the next item, or null
if none
+ */
+ protected Item getNextItem(Item item, bool includeChildren) {
+ if (item is null) {
+ return null;
+ }
+ if (includeChildren && getExpanded(item)) {
+ Item[] children = getItems(item);
+ if (children !is null && children.length > 0) {
+ return children[0];
+ }
+ }
+
+ // next item is either next sibling or next sibling of first
+ // parent that has a next sibling.
+ Item parent = getParentItem(item);
+ if (parent is null) {
+ return null;
+ }
+ Item[] siblings = getItems(parent);
+ if (siblings !is null) {
+ if (siblings.length <= 1) {
+ return getNextItem(parent, false);
+ }
+
+ for (int i = 0; i < siblings.length; i++) {
+ if (siblings[i] is item && i < (siblings.length - 1)) {
+ return siblings[i + 1];
+ }
+ }
+ }
+ return getNextItem(parent, false);
+ }
+
+ /**
+ * Returns the parent item of the given item in the tree, or
+ * null
if there is no parent item.
+ *
+ * @param item
+ * the item
+ * @return the parent item, or null
if none
+ */
+ protected abstract Item getParentItem(Item item);
+
+ /**
+ * Returns the item before the given item in the tree, or null
+ * if there is no previous item.
+ *
+ * @param item
+ * the item
+ * @return the previous item, or null
if none
+ */
+ protected Item getPreviousItem(Item item) {
+ // previous item is either right-most visible descendent of previous
+ // sibling or parent
+ Item parent = getParentItem(item);
+ if (parent is null) {
+ return null;
+ }
+ Item[] siblings = getItems(parent);
+ if (siblings.length is 0 || siblings[0] is item) {
+ return parent;
+ }
+ Item previous = siblings[0];
+ for (int i = 1; i < siblings.length; i++) {
+ if (siblings[i] is item) {
+ return rightMostVisibleDescendent(previous);
+ }
+ previous = siblings[i];
+ }
+ return null;
+ }
+
+ /* (non-Javadoc) Method declared on StructuredViewer. */
+ protected Object[] getRawChildren(Object parentElementOrTreePath) {
+ bool oldBusy = busy;
+ busy = true;
+ try {
+ Object parent;
+ TreePath path;
+ if ( auto p = cast(TreePath)parentElementOrTreePath ) {
+ path = p;
+ parent = path.getLastSegment();
+ } else {
+ parent = parentElementOrTreePath;
+ path = null;
+ }
+ if (parent !is null) {
+ if (opEquals(parent, getRoot())) {
+ return super.getRawChildren(parent);
+ }
+ IContentProvider cp = getContentProvider();
+ if ( auto tpcp = cast(ITreePathContentProvider)cp ) {
+ if (path is null) {
+ // A path was not provided so try and find one
+ Widget w = findItem(parent);
+ if ( auto item = cast(Item)w ) {
+ path = getTreePathFromItem(item);
+ }
+ if (path is null) {
+ path = new TreePath([parent ]);
+ }
+ }
+ Object[] result = tpcp.getChildren(path);
+ if (result !is null) {
+ return result;
+ }
+ } else if ( auto tcp = cast(ITreeContentProvider)cp ) {
+ Object[] result = tcp.getChildren(parent);
+ if (result !is null) {
+ return result;
+ }
+ }
+ }
+ return null;
+ } finally {
+ busy = oldBusy;
+ }
+ }
+
+ /**
+ * Returns all selected items for the given DWT control.
+ *
+ * @param control
+ * the control
+ * @return the list of selected items
+ */
+ protected abstract Item[] getSelection(Control control);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.StructuredViewer#getSelectionFromWidget()
+ */
+ protected SeqView!(Object) getSelectionFromWidget() {
+ Widget[] items = getSelection(getControl());
+ ArraySeq!(Object) list = new ArraySeq!(Object);
+ list.capacity(items.length);
+ for (int i = 0; i < items.length; i++) {
+ Widget item = items[i];
+ Object e = item.getData();
+ if (e !is null) {
+ list.append(e);
+ }
+ }
+ return list;
+ }
+
+ /*
+ * Overridden in AbstractTreeViewer to fix bug 108102 (code copied from
+ * StructuredViewer to avoid introducing new API) (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.StructuredViewer#handleDoubleSelect(dwt.events.SelectionEvent)
+ */
+ protected void handleDoubleSelect(SelectionEvent event) {
+ // handle case where an earlier selection listener disposed the control.
+ Control control = getControl();
+ if (control !is null && !control.isDisposed()) {
+ // If the double-clicked element can be obtained from the event, use
+ // it
+ // otherwise get it from the control. Some controls like List do
+ // not have the notion of item.
+ // For details, see bug 90161 [Navigator] DefaultSelecting folders
+ // shouldn't always expand first one
+ ISelection selection;
+ if (event.item !is null && event.item.getData() !is null) {
+
+ // changes to fix bug 108102 follow
+ TreePath treePath = getTreePathFromItem(cast(Item) event.item);
+ selection = new TreeSelection(treePath);
+ // end of changes
+
+ } else {
+ selection = getSelection();
+ updateSelection(selection);
+ }
+ fireDoubleClick(new DoubleClickEvent(this, selection));
+ }
+ }
+
+ /**
+ * Handles a tree collapse event from the DWT widget.
+ *
+ * @param event
+ * the DWT tree event
+ */
+ protected void handleTreeCollapse(TreeEvent event) {
+ if (event.item.getData() !is null) {
+ fireTreeCollapsed(new TreeExpansionEvent(this, event.item.getData()));
+ }
+ }
+
+ /**
+ * Handles a tree expand event from the DWT widget.
+ *
+ * @param event
+ * the DWT tree event
+ */
+ protected void handleTreeExpand(TreeEvent event) {
+ createChildren(event.item);
+ if (event.item.getData() !is null) {
+ fireTreeExpanded(new TreeExpansionEvent(this, event.item.getData()));
+ }
+ }
+
+ /* (non-Javadoc) Method declared on Viewer. */
+ protected void hookControl(Control control) {
+ super.hookControl(control);
+ addTreeListener(control, new class TreeListener {
+ public void treeExpanded(TreeEvent event) {
+ handleTreeExpand(event);
+ }
+
+ public void treeCollapsed(TreeEvent event) {
+ handleTreeCollapse(event);
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc) Method declared on StructuredViewer. Builds the initial
+ * tree and handles the automatic expand feature.
+ */
+ protected void inputChanged(Object input, Object oldInput) {
+ preservingSelection(new class Runnable {
+ public void run() {
+ Control tree = getControl();
+ bool useRedraw = true;
+ // (size > REDRAW_THRESHOLD) || (table.getItemCount() >
+ // REDRAW_THRESHOLD);
+ if (useRedraw) {
+ tree.setRedraw(false);
+ }
+ removeAll(tree);
+ tree.setData(getRoot());
+ internalInitializeTree(tree);
+ if (useRedraw) {
+ tree.setRedraw(true);
+ }
+ }
+
+ });
+ }
+
+ /**
+ * Initializes the tree with root items, expanding to the appropriate
+ * level if necessary.
+ *
+ * @param tree the tree control
+ * @since 3.3
+ */
+ protected void internalInitializeTree(Control tree) {
+ createChildren(tree);
+ internalExpandToLevel(tree, expandToLevel_);
+ }
+
+ /**
+ * Recursively collapses the subtree rooted at the given widget to the given
+ * level.
+ * setRedraw
.
+ *
+ * @param widget
+ * the widget
+ * @param level
+ * non-negative level, or ALL_LEVELS
to collapse
+ * all levels of the tree
+ */
+ protected void internalCollapseToLevel(Widget widget, int level) {
+ if (level is ALL_LEVELS || level > 0) {
+
+ if ( auto i = cast(Item)widget ) {
+ setExpanded(i, false);
+ }
+
+ if (level is ALL_LEVELS || level > 1) {
+ Item[] children = getChildren(widget);
+ if (children !is null) {
+ int nextLevel = (level is ALL_LEVELS ? ALL_LEVELS
+ : level - 1);
+ for (int i = 0; i < children.length; i++) {
+ internalCollapseToLevel(children[i], nextLevel);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Recursively collects all expanded items from the given widget.
+ *
+ * @param result
+ * a list (element type: Item
) into which to
+ * collect the elements
+ * @param widget
+ * the widget
+ */
+ private void internalCollectExpandedItems(Seq!(Item) result, Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ if (getExpanded(item)) {
+ result.append(item);
+ }
+ internalCollectExpandedItems(result, item);
+ }
+ }
+
+ /**
+ * Tries to create a path of tree items for the given element or tree path.
+ * This method recursively walks up towards the root of the tree and in the
+ * case of an element (rather than a tree path) assumes that
+ * getParent
returns the correct parent of an element.
+ *
+ * @param elementOrPath
+ * the element
+ * @param expand
+ * true
if all nodes on the path should be
+ * expanded, and false
otherwise
+ * @return Widget
+ */
+ protected Widget internalExpand(Object elementOrPath, bool expand) {
+
+ if (elementOrPath is null) {
+ return null;
+ }
+
+ Widget w = internalGetWidgetToSelect(elementOrPath);
+ if (w is null) {
+ if (opEquals(elementOrPath, getRoot())) { // stop at root
+ return null;
+ }
+ // my parent has to create me
+ Object parent = getParentElement(elementOrPath);
+ if (parent !is null) {
+ Widget pw = internalExpand(parent, false);
+ if (pw !is null) {
+ // let my parent create me
+ createChildren(pw);
+ Object element = internalToElement(elementOrPath);
+ w = internalFindChild(pw, element);
+ if (expand && null !is cast(Item)pw ) {
+ // expand parent items top-down
+ Item item = cast(Item) pw;
+ auto toExpandList = new LinkSeq!(Item);
+ while (item !is null && !getExpanded(item)) {
+ toExpandList.prepend(item);
+ item = getParentItem(item);
+ }
+ foreach( toExpand; toExpandList ){
+ setExpanded(toExpand, true);
+ }
+ }
+ }
+ }
+ }
+ return w;
+ }
+
+ /**
+ * If the argument is a tree path, returns its last segment, otherwise
+ * return the argument
+ *
+ * @param elementOrPath
+ * an element or a tree path
+ * @return the element, or the last segment of the tree path
+ */
+ private Object internalToElement(Object elementOrPath) {
+ if (auto tp = cast(TreePath)elementOrPath ) {
+ return tp.getLastSegment();
+ }
+ return elementOrPath;
+ }
+
+ /**
+ * This method takes a tree path or an element. If the argument is not a
+ * tree path, returns the parent of the given element or null
+ * if the parent is not known. If the argument is a tree path with more than
+ * one segment, returns its parent tree path, otherwise returns
+ * null
.
+ *
+ * @param elementOrTreePath
+ * @return the parent element, or parent path, or null
+ *
+ * @since 3.2
+ */
+ protected Object getParentElement(Object elementOrTreePath) {
+ if (auto tp = cast(TreePath)elementOrTreePath) {
+ return tp.getParentPath();
+ }
+ IContentProvider cp = getContentProvider();
+ if ( auto tpcp = cast(ITreePathContentProvider)cp ) {
+ TreePath[] paths = tpcp.getParents(elementOrTreePath);
+ if (paths.length > 0) {
+ if (paths[0].getSegmentCount() is 0) {
+ return getInput();
+ }
+ return paths[0].getLastSegment();
+ }
+ }
+ if ( auto tcp = cast(ITreeContentProvider) cp ) {
+ return tcp.getParent(elementOrTreePath);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the widget to be selected for the given element or tree path.
+ *
+ * @param elementOrTreePath
+ * the element or tree path to select
+ * @return the widget to be selected, or null
if not found
+ *
+ * @since 3.1
+ */
+ protected Widget internalGetWidgetToSelect(Object elementOrTreePath) {
+ if ( auto treePath = cast(TreePath) elementOrTreePath ) {
+ if (treePath.getSegmentCount() is 0) {
+ return getControl();
+ }
+ Widget[] candidates = findItems(treePath.getLastSegment());
+ for (int i = 0; i < candidates.length; i++) {
+ Widget candidate = candidates[i];
+ if (!(cast(Item)candidate )) {
+ continue;
+ }
+ if (treePath.opEquals(getTreePathFromItem(cast(Item) candidate),
+ getComparer())) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+ return findItem(elementOrTreePath);
+ }
+
+ /**
+ * Recursively expands the subtree rooted at the given widget to the given
+ * level.
+ * setRedraw
.
+ *
+ * @param widget
+ * the widget
+ * @param level
+ * non-negative level, or ALL_LEVELS
to collapse
+ * all levels of the tree
+ */
+ protected void internalExpandToLevel(Widget widget, int level) {
+ if (level is ALL_LEVELS || level > 0) {
+ if ( cast(Item)widget && widget.getData() !is null
+ && !isExpandable(cast(Item) widget, null, widget.getData())) {
+ return;
+ }
+ createChildren(widget);
+ if ( auto i = cast(Item)widget ) {
+ setExpanded(i, true);
+ }
+ if (level is ALL_LEVELS || level > 1) {
+ Item[] children = getChildren(widget);
+ if (children !is null) {
+ int newLevel = (level is ALL_LEVELS ? ALL_LEVELS
+ : level - 1);
+ for (int i = 0; i < children.length; i++) {
+ internalExpandToLevel(children[i], newLevel);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Non-recursively tries to find the given element as a child of the given
+ * parent (item or tree).
+ *
+ * @param parent
+ * the parent item
+ * @param element
+ * the element
+ * @return Widget
+ */
+ private Widget internalFindChild(Widget parent, Object element) {
+ Item[] items = getChildren(parent);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ Object data = item.getData();
+ if (data !is null && opEquals(data, element)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Recursively tries to find the given element.
+ *
+ * @param parent
+ * the parent item
+ * @param element
+ * the element
+ * @return Widget
+ */
+ private Widget internalFindItem(Item parent, Object element) {
+
+ // compare with node
+ Object data = parent.getData();
+ if (data !is null) {
+ if (opEquals(data, element)) {
+ return parent;
+ }
+ }
+ // recurse over children
+ Item[] items = getChildren(parent);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ Widget o = internalFindItem(item, element);
+ if (o !is null) {
+ return o;
+ }
+ }
+ return null;
+ }
+
+ /* (non-Javadoc) Method declared on StructuredViewer. */
+ protected void internalRefresh(Object element) {
+ internalRefresh(element, true);
+ }
+
+ /* (non-Javadoc) Method declared on StructuredViewer. */
+ protected void internalRefresh(Object element, bool updateLabels) {
+ // If element is null, do a full refresh.
+ if (element is null) {
+ internalRefresh(getControl(), getRoot(), true, updateLabels);
+ return;
+ }
+ Widget[] items = findItems(element);
+ if (items.length !is 0) {
+ for (int i = 0; i < items.length; i++) {
+ // pick up structure changes too
+ internalRefresh(items[i], element, true, updateLabels);
+ }
+ }
+ }
+
+ /**
+ * Refreshes the tree starting at the given widget.
+ * true
if structural changes are to be picked up,
+ * and false
if only label provider changes are of
+ * interest
+ * @param updateLabels
+ * true
to update labels for existing elements,
+ * false
to only update labels as needed, assuming
+ * that labels for existing elements are unchanged.
+ * @since 3.1
+ */
+ protected void internalRefresh(Widget widget, Object element,
+ bool doStruct, bool updateLabels) {
+
+ if ( auto i = cast(Item)widget ) {
+ if (doStruct) {
+ updatePlus(i, element);
+ }
+ if (updateLabels || !opEquals(element, widget.getData())) {
+ doUpdateItem(widget, element, true);
+ } else {
+ associate(element, cast(Item) widget);
+ }
+ }
+
+ if (doStruct) {
+ internalRefreshStruct(widget, element, updateLabels);
+ } else {
+ Item[] children = getChildren(widget);
+ if (children !is null) {
+ for (int i = 0; i < children.length; i++) {
+ Widget item = children[i];
+ Object data = item.getData();
+ if (data !is null) {
+ internalRefresh(item, data, doStruct, updateLabels);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Update the structure and recurse. Items are updated in updateChildren, as
+ * needed.
+ *
+ * @param widget
+ * @param element
+ * @param updateLabels
+ */
+ /* package */void internalRefreshStruct(Widget widget, Object element,
+ bool updateLabels) {
+ updateChildren(widget, element, null, updateLabels);
+ Item[] children = getChildren(widget);
+ if (children !is null) {
+ for (int i = 0; i < children.length; i++) {
+ Widget item = children[i];
+ Object data = item.getData();
+ if (data !is null) {
+ internalRefreshStruct(item, data, updateLabels);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes the given elements from this viewer.
+ * Object
) of elements
+ * which are expanded
+ * @param widget
+ * the widget
+ */
+ private void internalSetExpanded(CustomHashtable expandedElements,
+ Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ Object data = item.getData();
+ if (data !is null) {
+ // remove the element to avoid an infinite loop
+ // if the same element appears on a child item
+ bool expanded = expandedElements.remove(data) !is null;
+ if (expanded !is getExpanded(item)) {
+ if (expanded) {
+ createChildren(item);
+ }
+ setExpanded(item, expanded);
+ }
+ }
+ if (expandedElements.size() > 0) {
+ internalSetExpanded(expandedElements, item);
+ }
+ }
+ }
+
+ /**
+ * Sets the expanded state of all items to correspond to the given set of
+ * expanded tree paths.
+ *
+ * @param expandedTreePaths
+ * the set (element type: TreePath
) of elements
+ * which are expanded
+ * @param widget
+ * the widget
+ */
+ private void internalSetExpandedTreePaths(
+ CustomHashtable expandedTreePaths, Widget widget,
+ TreePath currentPath) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ Object data = item.getData();
+ TreePath childPath = data is null ? null : currentPath
+ .createChildPath(data);
+ if (data !is null && childPath !is null) {
+ // remove the element to avoid an infinite loop
+ // if the same element appears on a child item
+ bool expanded = expandedTreePaths.remove(childPath) !is null;
+ if (expanded !is getExpanded(item)) {
+ if (expanded) {
+ createChildren(item);
+ }
+ setExpanded(item, expanded);
+ }
+ }
+ internalSetExpandedTreePaths(expandedTreePaths, item, childPath);
+ }
+ }
+
+ /**
+ * Return whether the tree node representing the given element or path can
+ * be expanded. Clients should query expandability by path if the viewer's
+ * content provider is an {@link ITreePathContentProvider}.
+ * hasChildren
on this viewer's content provider. It may be
+ * overridden if necessary.
+ * true
if the tree node representing the given
+ * element can be expanded, or false
if not
+ */
+ public bool isExpandable(Object elementOrTreePath) {
+ Object element;
+ TreePath path;
+ if (auto p = cast(TreePath)elementOrTreePath) {
+ path = p;
+ element = path.getLastSegment();
+ } else {
+ element = elementOrTreePath;
+ path = null;
+ }
+ IContentProvider cp = getContentProvider();
+ if ( auto tpcp = cast(ITreePathContentProvider) cp ) {
+ if (path is null) {
+ // A path was not provided so try and find one
+ Widget w = findItem(element);
+ if ( auto item = cast(Item)w ) {
+ path = getTreePathFromItem(item);
+ }
+ if (path is null) {
+ path = new TreePath([ element ]);
+ }
+ }
+ return tpcp.hasChildren(path);
+ }
+ if (auto tcp = cast(ITreeContentProvider)cp ) {
+ return tcp.hasChildren(element);
+ }
+ return false;
+ }
+
+ /**
+ * Return whether the given element is expandable.
+ *
+ * @param item
+ * the tree item for the element
+ * @param parentPath
+ * the parent path if it is known or null
if it
+ * needs to be determines
+ * @param element
+ * the element
+ * @return whether the given element is expandable
+ */
+ private bool isExpandable(Item item, TreePath parentPath, Object element) {
+ Object elementOrTreePath = element;
+ if (isTreePathContentProvider()) {
+ if (parentPath !is null) {
+ elementOrTreePath = parentPath.createChildPath(element);
+ } else {
+ elementOrTreePath = getTreePathFromItem(item);
+ }
+ }
+ return isExpandable(elementOrTreePath);
+ }
+
+ /* (non-Javadoc) Method declared on Viewer. */
+ protected void labelProviderChanged() {
+ // we have to walk the (visible) tree and update every item
+ Control tree = getControl();
+ tree.setRedraw(false);
+ // don't pick up structure changes, but do force label updates
+ internalRefresh(tree, getRoot(), false, true);
+ tree.setRedraw(true);
+ }
+
+ /**
+ * Creates a new item.
+ *
+ * @param parent
+ * the parent widget
+ * @param style
+ * DWT style bits
+ * @param index
+ * if non-negative, indicates the position to insert the item
+ * into its parent
+ * @return the newly-created item
+ */
+ protected abstract Item newItem(Widget parent, int style, int index);
+
+ /**
+ * Removes the given elements from this viewer. The selection is updated if
+ * required.
+ * ALL_LEVELS
means that all subtrees should be
+ * expanded.
+ * ALL_LEVELS
to expand all
+ * levels of the tree
+ */
+ public void setAutoExpandLevel(int level) {
+ expandToLevel_ = level;
+ }
+
+ /**
+ * The AbstractTreeViewer
implementation of this method
+ * checks to ensure that the content provider is an
+ * ITreeContentProvider
.
+ */
+ public void setContentProvider(IContentProvider provider) {
+ // the actual check is in assertContentProviderType
+ super.setContentProvider(provider);
+ }
+
+ protected void assertContentProviderType(IContentProvider provider) {
+ Assert.isTrue(cast(ITreeContentProvider)provider
+ || cast(ITreePathContentProvider)provider );
+ }
+
+ /**
+ * Sets the expand state of the given item.
+ *
+ * @param item
+ * the item
+ * @param expand
+ * the expand state of the item
+ */
+ protected abstract void setExpanded(Item item, bool expand);
+
+ /**
+ * Sets which nodes are expanded in this viewer's tree. The given list
+ * contains the elements that are to be expanded; all other nodes are to be
+ * collapsed.
+ * getExpandedElements
.
+ * getExpandedTreePaths
.
+ * true
if the node is expanded, and
+ * false
if collapsed
+ */
+ public void setExpandedState(Object elementOrTreePath, bool expanded) {
+ Assert.isNotNull(elementOrTreePath);
+ if (isBusy())
+ return;
+ Widget item = internalExpand(elementOrTreePath, false);
+ if ( cast(Item)item ) {
+ if (expanded) {
+ createChildren(item);
+ }
+ setExpanded(cast(Item) item, expanded);
+ }
+ }
+
+ /**
+ * Sets the selection to the given list of items.
+ *
+ * @param items
+ * list of items (element type:
+ * dwt.widgets.Item
)
+ */
+ protected abstract void setSelection(SeqView!(Item) items);
+
+ /**
+ * This implementation of setSelectionToWidget accepts a list of elements or
+ * a list of tree paths.
+ */
+ protected void setSelectionToWidget(SeqView!(Object) v, bool reveal) {
+ if (v is null) {
+ setSelection(new ArraySeq!(Item));
+ return;
+ }
+ int size = v.size();
+ auto newSelection = new ArraySeq!(Item);
+ newSelection.capacity(size);
+ for (int i = 0; i < size; ++i) {
+ Object elementOrTreePath = v.get(i);
+ // Use internalExpand since item may not yet be created. See
+ // 1G6B1AR.
+ Widget w = internalExpand(elementOrTreePath, false);
+ if ( auto it = cast(Item)w ) {
+ newSelection.append(it);
+ } else if (w is null && null !is cast(TreePath)elementOrTreePath ) {
+ TreePath treePath = cast(TreePath) elementOrTreePath;
+ Object element = treePath.getLastSegment();
+ if (element !is null) {
+ w = internalExpand(element, false);
+ if ( auto it = cast(Item)w ) {
+ newSelection.append(it);
+ }
+ }
+ }
+ }
+ setSelection(newSelection);
+
+ // Although setting the selection in the control should reveal it,
+ // setSelection may be a no-op if the selection is unchanged,
+ // so explicitly reveal the first item in the selection here.
+ // See bug 100565 for more details.
+ if (reveal && newSelection.size() > 0) {
+ showItem(cast(Item) newSelection.get(0));
+ }
+ }
+
+ /**
+ * Shows the given item.
+ *
+ * @param item
+ * the item
+ */
+ protected abstract void showItem(Item item);
+
+ /**
+ * Updates the tree items to correspond to the child elements of the given
+ * parent element. If null is passed for the children, this method obtains
+ * them (only if needed).
+ *
+ * @param widget
+ * the widget
+ * @param parent
+ * the parent element
+ * @param elementChildren
+ * the child elements, or null
+ * @deprecated this is no longer called by the framework
+ */
+ protected void updateChildren(Widget widget, Object parent,
+ Object[] elementChildren) {
+ updateChildren(widget, parent, elementChildren, true);
+ }
+
+ /**
+ * Updates the tree items to correspond to the child elements of the given
+ * parent element. If null is passed for the children, this method obtains
+ * them (only if needed).
+ *
+ * @param widget
+ * the widget
+ * @param parent
+ * the parent element
+ * @param elementChildren
+ * the child elements, or null
+ * @param updateLabels
+ * true
to update labels for existing elements,
+ * false
to only update labels as needed, assuming
+ * that labels for existing elements are unchanged.
+ * @since 2.1
+ */
+ private void updateChildren(Widget widget, Object parent,
+ Object[] elementChildren, bool updateLabels) {
+ // optimization! prune collapsed subtrees
+ if (auto ti = cast(Item)widget ) {
+ if (!getExpanded(ti)) {
+ // need a dummy node if element is expandable;
+ // but try to avoid recreating the dummy node
+ bool needDummy = isExpandable(ti, null, parent);
+ bool haveDummy = false;
+ // remove all children
+ Item[] items = getItems(ti);
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].getData() !is null) {
+ disassociate(items[i]);
+ items[i].dispose();
+ } else {
+ if (needDummy && !haveDummy) {
+ haveDummy = true;
+ } else {
+ items[i].dispose();
+ }
+ }
+ }
+ if (needDummy && !haveDummy) {
+ newItem(ti, DWT.NULL, -1);
+ }
+
+ return;
+ }
+ }
+
+ // If the children weren't passed in, get them now since they're needed
+ // below.
+ if (elementChildren is null) {
+ if (isTreePathContentProvider() && null !is cast(Item) widget ) {
+ TreePath path = getTreePathFromItem(cast(Item) widget);
+ elementChildren = getSortedChildren(path);
+ } else {
+ elementChildren = getSortedChildren(parent);
+ }
+ }
+
+ Control tree = getControl();
+
+ // WORKAROUND
+ int oldCnt = -1;
+ if (widget is tree) {
+ oldCnt = getItemCount(tree);
+ }
+
+ Item[] items = getChildren(widget);
+
+ // save the expanded elements
+ CustomHashtable expanded = newHashtable(CustomHashtable.DEFAULT_CAPACITY); // assume
+ // num
+ // expanded
+ // is
+ // small
+ for (int i = 0; i < items.length; ++i) {
+ if (getExpanded(items[i])) {
+ Object element = items[i].getData();
+ if (element !is null) {
+ expanded.put(element, element);
+ }
+ }
+ }
+
+ int min = Math.min(elementChildren.length, items.length);
+
+ // dispose of surplus items, optimizing for the case where elements have
+ // been deleted but not reordered, or all elements have been removed.
+ int numItemsToDispose = items.length - min;
+ if (numItemsToDispose > 0) {
+ CustomHashtable children = newHashtable(elementChildren.length * 2);
+ for (int i = 0; i < elementChildren.length; i++) {
+ Object elementChild = elementChildren[i];
+ children.put(elementChild, elementChild);
+ }
+ int i = 0;
+ while (numItemsToDispose > 0 && i < items.length) {
+ Object data = items[i].getData();
+ if (data is null || items.length - i <= numItemsToDispose || !children.containsKey(data)) {
+ if (data !is null) {
+ disassociate(items[i]);
+ }
+ items[i].dispose();
+ if (i + 1 < items.length) {
+ // The components at positions i+1 through
+ // items.length-1 in the source array are copied into
+ // positions i through items.length-2
+ System.arraycopy(items, i + 1, items, i, items.length - (i+1));
+ }
+ numItemsToDispose--;
+ } else {
+ i++;
+ }
+ }
+ }
+
+ // compare first min items, and update item if necessary
+ // need to do it in two passes:
+ // 1: disassociate old items
+ // 2: associate new items
+ // because otherwise a later disassociate can remove a mapping made for
+ // a previous associate,
+ // making the map inconsistent
+ for (int i = 0; i < min; ++i) {
+ Item item = items[i];
+ Object oldElement = item.getData();
+ if (oldElement !is null) {
+ Object newElement = elementChildren[i];
+ if (newElement !is oldElement) {
+ if (opEquals(newElement, oldElement)) {
+ // update the data to be the new element, since
+ // although the elements
+ // may be equal, they may still have different labels
+ // or children
+ Object data = item.getData();
+ if (data !is null) {
+ unmapElement(data, item);
+ }
+ item.setData(newElement);
+ mapElement(newElement, item);
+ } else {
+ disassociate(item);
+ // Clear the text and image to force a label update
+ item.setImage(null);
+ item.setText("");//$NON-NLS-1$
+
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < min; ++i) {
+ Item item = items[i];
+ Object newElement = elementChildren[i];
+ if (item.getData() is null) {
+ // old and new elements are not equal
+ associate(newElement, item);
+ updatePlus(item, newElement);
+ updateItem(item, newElement);
+ } else {
+ // old and new elements are equal
+ updatePlus(item, newElement);
+ if (updateLabels) {
+ updateItem(item, newElement);
+ }
+ }
+ }
+
+ // Restore expanded state for items that changed position.
+ // Make sure setExpanded is called after updatePlus, since
+ // setExpanded(false) fails if item has no children.
+ // Need to call setExpanded for both expanded and unexpanded
+ // cases since the expanded state can change either way.
+ // This needs to be done in a second loop, see bug 148025.
+ for (int i = 0; i < min; ++i) {
+ Item item = items[i];
+ Object newElement = elementChildren[i];
+ setExpanded(item, expanded.containsKey(newElement));
+ }
+
+ // add any remaining elements
+ if (min < elementChildren.length) {
+ for (int i = min; i < elementChildren.length; ++i) {
+ createTreeItem(widget, elementChildren[i], i);
+ }
+
+ // Need to restore expanded state in a separate pass
+ // because createTreeItem does not return the new item.
+ // Avoid doing this unless needed.
+ if (expanded.size() > 0) {
+ // get the items again, to include the new items
+ items = getChildren(widget);
+ for (int i = min; i < elementChildren.length; ++i) {
+ // Restore expanded state for items that changed position.
+ // Make sure setExpanded is called after updatePlus (called
+ // in createTreeItem), since
+ // setExpanded(false) fails if item has no children.
+ // Only need to call setExpanded if element was expanded
+ // since new items are initially unexpanded.
+ if (expanded.containsKey(elementChildren[i])) {
+ setExpanded(items[i], true);
+ }
+ }
+ }
+ }
+
+ // WORKAROUND
+ if (widget is tree && oldCnt is 0 && getItemCount(tree) !is 0) {
+ // System.out.println("WORKAROUND setRedraw");
+ tree.setRedraw(false);
+ tree.setRedraw(true);
+ }
+ }
+
+ /**
+ * Updates the "+"/"-" icon of the tree node from the given element. It
+ * calls isExpandable
to determine whether an element is
+ * expandable.
+ *
+ * @param item
+ * the item
+ * @param element
+ * the element
+ */
+ protected void updatePlus(Item item, Object element) {
+ bool hasPlus = getItemCount(item) > 0;
+ bool needsPlus = isExpandable(item, null, element);
+ bool removeAll = false;
+ bool addDummy = false;
+ Object data = item.getData();
+ if (data !is null && opEquals(element, data)) {
+ // item shows same element
+ if (hasPlus !is needsPlus) {
+ if (needsPlus) {
+ addDummy = true;
+ } else {
+ removeAll = true;
+ }
+ }
+ } else {
+ // item shows different element
+ removeAll = true;
+ addDummy = needsPlus;
+
+ // we cannot maintain expand state so collapse it
+ setExpanded(item, false);
+ }
+ if (removeAll) {
+ // remove all children
+ Item[] items = getItems(item);
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].getData() !is null) {
+ disassociate(items[i]);
+ }
+ items[i].dispose();
+ }
+ }
+ if (addDummy) {
+ newItem(item, DWT.NULL, -1); // append a dummy
+ }
+ }
+
+ /**
+ * Gets the expanded elements that are visible to the user. An expanded
+ * element is only visible if the parent is expanded.
+ *
+ * @return the visible expanded elements
+ * @since 2.0
+ */
+ public Object[] getVisibleExpandedElements() {
+ auto v = new ArraySeq!(Object);
+ internalCollectVisibleExpanded(v, getControl());
+ return v.toArray();
+ }
+
+ private void internalCollectVisibleExpanded(ArraySeq!(Object) result, Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ if (getExpanded(item)) {
+ Object data = item.getData();
+ if (data !is null) {
+ result.append(data);
+ }
+ // Only recurse if it is expanded - if
+ // not then the children aren't visible
+ internalCollectVisibleExpanded(result, item);
+ }
+ }
+ }
+
+ /**
+ * Returns the tree path for the given item.
+ * @param item
+ * @return {@link TreePath}
+ *
+ * @since 3.2
+ */
+ protected TreePath getTreePathFromItem(Item item) {
+ auto segments = new LinkSeq!(Object);
+ while (item !is null) {
+ Object segment = item.getData();
+ Assert.isNotNull(segment);
+ segments.prepend(segment);
+ item = getParentItem(item);
+ }
+ return new TreePath(segments.toArray());
+ }
+ package TreePath getTreePathFromItem_package(Item item) {
+ return getTreePathFromItem_package(item);
+ }
+
+ /**
+ * This implementation of getSelection() returns an instance of
+ * ITreeSelection.
+ *
+ * @since 3.2
+ */
+ public ISelection getSelection() {
+ Control control = getControl();
+ if (control is null || control.isDisposed()) {
+ return TreeSelection.EMPTY;
+ }
+ Widget[] items = getSelection(getControl());
+ auto list = new ArraySeq!(TreePath);
+ list.capacity(items.length);
+ for (int i = 0; i < items.length; i++) {
+ Widget item = items[i];
+ if (item.getData() !is null) {
+ list.append(getTreePathFromItem(cast(Item) item));
+ }
+ }
+ return new TreeSelection( list.toArray(), getComparer());
+ }
+
+ protected void setSelectionToWidget(ISelection selection, bool reveal) {
+ if ( auto treeSelection = cast(ITreeSelection)selection ) {
+ auto list = new ArraySeq!(Object);
+ auto paths = treeSelection.getPaths();
+ list.capacity(paths.length);
+ foreach( path; paths ){
+ list.append(path);
+ }
+ setSelectionToWidget(list, reveal);
+ } else {
+ super.setSelectionToWidget(selection, reveal);
+ }
+ }
+
+ /**
+ * Returns a list of tree paths corresponding to expanded nodes in this
+ * viewer's tree, including currently hidden ones that are marked as
+ * expanded but are under a collapsed ancestor.
+ * setExpandedElements
is used during the restore.
+ * true
if the given object is either the input or an empty tree path,
+ * false
otherwise.
+ * @since 3.3
+ */
+ final protected bool internalIsInputOrEmptyPath(Object elementOrTreePath) {
+ if (elementOrTreePath.opEquals(getInput()))
+ return true;
+ if (!(cast(TreePath)elementOrTreePath ))
+ return false;
+ return (cast(TreePath) elementOrTreePath).getSegmentCount() is 0;
+ }
+
+ /*
+ * Subclasses should implement
+ */
+ protected ViewerRow getViewerRowFromItem(Widget item) {
+ return null;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/AcceptAllFilter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/AcceptAllFilter.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit IStructuredContentProvider
handles
+ * the case where the viewer input is an unchanging array or collection of elements.
+ * Collection
.
+ */
+ public Object[] getElements(Object inputElement) {
+ if ( auto aw = cast(ArrayWrapperObject) inputElement ) {
+ return aw.array;
+ }
+ if ( auto col = cast(View!(Object)) inputElement ) {
+ return col.toArray();
+ }
+ return null;
+ }
+
+ /**
+ * This implementation does nothing.
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // do nothing.
+ }
+
+ /**
+ * This implementation does nothing.
+ */
+ public void dispose() {
+ // do nothing.
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/BaseLabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/BaseLabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit BaseLabelProvider
implementation of this
+ * IBaseLabelProvider
method clears its internal listener list.
+ * Subclasses may extend but should call the super implementation.
+ */
+ public void dispose() {
+ clearListeners();
+ }
+
+ /**
+ * The BaseLabelProvider
implementation of this
+ * IBaseLabelProvider
method returns true
. Subclasses may
+ * override.
+ */
+ public bool isLabelProperty(Object element, String property) {
+ return true;
+ }
+
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.IBaseLabelProvider#removeListener(dwtx.jface.viewers.ILabelProviderListener)
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ removeListenerObject(cast(Object)listener);
+ }
+
+ /**
+ * Fires a label provider changed event to all registered listeners Only
+ * listeners registered at the time this method is called are notified.
+ *
+ * @param event
+ * a label provider changed event
+ *
+ * @see ILabelProviderListener#labelProviderChanged
+ */
+ protected void fireLabelProviderChanged(LabelProviderChangedEvent event) {
+ Object[] listeners = getListeners();
+ for (int i = 0; i < listeners.length; ++i) {
+ SafeRunnable.run(new class SafeRunnable {
+ LabelProviderChangedEvent event_;
+ ILabelProviderListener l;
+ this(){
+ event_=event;
+ l = cast(ILabelProviderListener) listeners[i];
+ }
+ public void run() {
+ l.labelProviderChanged(event_);
+ }
+ });
+
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/CellEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/CellEditor.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,907 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ * TextCellEditor
- for simple text stringsColorCellEditor
- for colorsComboBoxCellEditor
- value selected from drop-down combo boxCheckboxCellEditor
- bool valued checkboxDialogCellEditor
- value from arbitrary dialog
ICellEditorListener
).
+ */
+ private ListenerList listeners;
+
+ /**
+ * List of cell editor property change listeners
+ * (element type: IPropertyChangeListener
).
+ */
+ private ListenerList propertyChangeListeners;
+
+ /**
+ * Indicates whether this cell editor's current value is valid.
+ */
+ private bool valid = false;
+
+ /**
+ * Optional cell editor validator; null
if none.
+ */
+ private ICellEditorValidator validator = null;
+
+ /**
+ * The error message string to display for invalid values;
+ * null
if none (that is, the value is valid).
+ */
+ private String errorMessage = null;
+
+ /**
+ * Indicates whether this cell editor has been changed recently.
+ */
+ private bool dirty = false;
+
+ /**
+ * This cell editor's control, or null
+ * if not created yet.
+ */
+ private Control control = null;
+
+ /**
+ * Default cell editor style
+ */
+ private static const int defaultStyle = DWT.NONE;
+
+ /**
+ * This cell editor's style
+ */
+ private int style = defaultStyle;
+
+ /**
+ * Struct-like layout data for cell editors, with reasonable defaults
+ * for all fields.
+ */
+ public static class LayoutData {
+ /**
+ * Horizontal alignment; DWT.LEFT
by default.
+ */
+ public int horizontalAlignment = DWT.LEFT;
+
+ /**
+ * Indicates control grabs additional space; true
by default.
+ */
+ public bool grabHorizontal = true;
+
+ /**
+ * Minimum width in pixels; 50
pixels by default.
+ */
+ public int minimumWidth = 50;
+ }
+
+ /**
+ * Property name for the copy action
+ */
+ public static const String COPY = "copy"; //$NON-NLS-1$
+
+ /**
+ * Property name for the cut action
+ */
+ public static const String CUT = "cut"; //$NON-NLS-1$
+
+ /**
+ * Property name for the delete action
+ */
+ public static const String DELETE = "delete"; //$NON-NLS-1$
+
+ /**
+ * Property name for the find action
+ */
+ public static const String FIND = "find"; //$NON-NLS-1$
+
+ /**
+ * Property name for the paste action
+ */
+ public static const String PASTE = "paste"; //$NON-NLS-1$
+
+ /**
+ * Property name for the redo action
+ */
+ public static const String REDO = "redo"; //$NON-NLS-1$
+
+ /**
+ * Property name for the select all action
+ */
+ public static const String SELECT_ALL = "selectall"; //$NON-NLS-1$
+
+ /**
+ * Property name for the undo action
+ */
+ public static const String UNDO = "undo"; //$NON-NLS-1$
+
+ /**
+ * Creates a new cell editor with no control
+ * The cell editor has no cell validator.
+ * @since 2.1
+ */
+ protected this() {
+ propertyChangeListeners = new ListenerList();
+ listeners = new ListenerList();
+ }
+
+ /**
+ * Creates a new cell editor under the given parent control.
+ * The cell editor has no cell validator.
+ *
+ * @param parent the parent control
+ */
+ protected this(Composite parent) {
+ this(parent, defaultStyle);
+ }
+
+ /**
+ * Creates a new cell editor under the given parent control.
+ * The cell editor has no cell validator.
+ *
+ * @param parent the parent control
+ * @param style the style bits
+ * @since 2.1
+ */
+ protected this(Composite parent, int style) {
+ propertyChangeListeners = new ListenerList();
+ listeners = new ListenerList();
+ this.style = style;
+ create(parent);
+ }
+
+ /**
+ * Activates this cell editor.
+ * + * The default implementation of this framework method + * does nothing. Subclasses may reimplement. + *
+ */ + public void activate() { + } + + /** + * Adds a listener to this cell editor. + * Has no effect if an identical listener is already registered. + * + * @param listener a cell editor listener + */ + public void addListener(ICellEditorListener listener) { + listeners.add(cast(Object)listener); + } + + /** + * Adds a property change listener to this cell editor. + * Has no effect if an identical property change listener + * is already registered. + * + * @param listener a property change listener + */ + public void addPropertyChangeListener(IPropertyChangeListener listener) { + propertyChangeListeners.add(cast(Object)listener); + } + + /** + * Creates the control for this cell editor under the given parent control. + *+ * This framework method must be implemented by concrete + * subclasses. + *
+ * + * @param parent the parent control + * @return the new control, ornull
if this cell editor has no control
+ */
+ protected abstract Control createControl(Composite parent);
+
+ /**
+ * Creates the control for this cell editor under the given parent control.
+ *
+ * @param parent the parent control
+ * @since 2.1
+ */
+ public void create(Composite parent) {
+ Assert.isTrue(control is null);
+ control = createControl(parent);
+ // See 1GD5CA6: ITPUI:ALL - TaskView.setSelection does not work
+ // Control is created with getVisible()istrue by default.
+ // This causes composite.setFocus() to work incorrectly.
+ // The cell editor's control grabs focus instead, even if it is not active.
+ // Make the control invisible here by default.
+ deactivate();
+ }
+
+ /**
+ * Hides this cell editor's control. Does nothing if this
+ * cell editor is not visible.
+ */
+ public void deactivate() {
+ if (control !is null && !control.isDisposed()) {
+ control.setVisible(false);
+ }
+ }
+
+ /**
+ * Disposes of this cell editor and frees any associated DWT resources.
+ */
+ public void dispose() {
+ if (control !is null && !control.isDisposed()) {
+ control.dispose();
+ }
+ control = null;
+ }
+
+ /**
+ * Returns this cell editor's value.
+ * + * This framework method must be implemented by concrete subclasses. + *
+ * + * @return the value of this cell editor + * @see #getValue + */ + protected abstract Object doGetValue(); + + /** + * Sets the focus to the cell editor's control. + *+ * This framework method must be implemented by concrete subclasses. + *
+ * + * @see #setFocus + */ + protected abstract void doSetFocus(); + + /** + * Sets this cell editor's value. + *+ * This framework method must be implemented by concrete subclasses. + *
+ * + * @param value the value of this cell editor + * @see #setValue + */ + protected abstract void doSetValue(Object value); + + /** + * Notifies all registered cell editor listeners of an apply event. + * Only listeners registered at the time this method is called are notified. + * + * @see ICellEditorListener#applyEditorValue + */ + protected void fireApplyEditorValue() { + Object[] array = listeners.getListeners(); + for (int i = 0; i < array.length; i++) { + SafeRunnable.run(new class SafeRunnable { + ICellEditorListener l; + this(){ + l = cast(ICellEditorListener) array[i]; + } + public void run() { + l.applyEditorValue(); + } + }); + } + } + + /** + * Notifies all registered cell editor listeners that editing has been + * canceled. + * + * @see ICellEditorListener#cancelEditor + */ + protected void fireCancelEditor() { + Object[] array = listeners.getListeners(); + for (int i = 0; i < array.length; i++) { + SafeRunnable.run(new class SafeRunnable { + ICellEditorListener l; + this(){ + l = cast(ICellEditorListener) array[i]; + } + public void run() { + l.cancelEditor(); + } + }); + } + } + + /** + * Notifies all registered cell editor listeners of a value change. + * + * @param oldValidState the valid state before the end user changed the value + * @param newValidState the current valid state + * @see ICellEditorListener#editorValueChanged + */ + protected void fireEditorValueChanged(bool oldValidState, + bool newValidState) { + Object[] array = listeners.getListeners(); + for (int i = 0; i < array.length; i++) { + SafeRunnable.run(new class SafeRunnable { + bool newValidState_; + bool oldValidState_; + ICellEditorListener l; + this(){ + newValidState_=newValidState; + oldValidState_=oldValidState; + l = cast(ICellEditorListener) array[i]; + } + public void run() { + l.editorValueChanged(oldValidState_, newValidState_); + } + }); + } + } + + /** + * Notifies all registered property listeners + * of an enablement change. + * + * @param actionId the id indicating what action's enablement has changed. + */ + protected void fireEnablementChanged(String actionId) { + Object[] array = propertyChangeListeners.getListeners(); + for (int i = 0; i < array.length; i++) { + SafeRunnable.run(new class SafeRunnable { + String actionId_; + IPropertyChangeListener l; + this(){ + actionId_=actionId; + l = cast(IPropertyChangeListener) array[i]; + } + public void run() { + l.propertyChange(new PropertyChangeEvent(this, actionId_, + null, null)); + } + }); + } + } + + /** + * Sets the style bits for this cell editor. + * + * @param style the DWT style bits for this cell editor + * @since 2.1 + */ + public void setStyle(int style) { + this.style = style; + } + + /** + * Returns the style bits for this cell editor. + * + * @return the style for this cell editor + * @since 2.1 + */ + public int getStyle() { + return style; + } + + /** + * Returns the control used to implement this cell editor. + * + * @return the control, ornull
if this cell editor has no control
+ */
+ public Control getControl() {
+ return control;
+ }
+
+ /**
+ * Returns the current error message for this cell editor.
+ *
+ * @return the error message if the cell editor is in an invalid state,
+ * and null
if the cell editor is valid
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Returns a layout data object for this cell editor.
+ * This is called each time the cell editor is activated
+ * and controls the layout of the DWT table editor.
+ * + * The default implementation of this method sets the + * minimum width to the control's preferred width. + * Subclasses may extend or reimplement. + *
+ * + * @return the layout data object + */ + public LayoutData getLayoutData() { + LayoutData result = new LayoutData(); + Control control = getControl(); + if (control !is null) { + result.minimumWidth = control.computeSize(DWT.DEFAULT, DWT.DEFAULT, + true).x; + } + return result; + } + + /** + * Returns the input validator for this cell editor. + * + * @return the input validator, ornull
if none
+ */
+ public ICellEditorValidator getValidator() {
+ return validator;
+ }
+
+ /**
+ * Returns this cell editor's value provided that it has a valid one.
+ *
+ * @return the value of this cell editor, or null
+ * if the cell editor does not contain a valid value
+ */
+ public final Object getValue() {
+ if (!valid) {
+ return null;
+ }
+
+ return doGetValue();
+ }
+
+ /**
+ * Returns whether this cell editor is activated.
+ *
+ * @return true
if this cell editor's control is
+ * currently activated, and false
if not activated
+ */
+ public bool isActivated() {
+ // Use the state of the visible style bit (getVisible()) rather than the
+ // window's actual visibility (isVisible()) to get correct handling when
+ // an ancestor control goes invisible, see bug 85331.
+ return control !is null && control.getVisible();
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the copy action.
+ *
+ * This default implementation always returns
+ * false
.
+ *
+ * Subclasses may override + *
+ * @returntrue
if copy is possible,
+ * false
otherwise
+ */
+ public bool isCopyEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns whether the given value is valid for this cell editor.
+ * This cell editor's validator (if any) makes the actual determination.
+ * @param value the value to check for
+ *
+ * @return true
if the value is valid, and false
+ * if invalid
+ */
+ protected bool isCorrect(Object value) {
+ errorMessage = null;
+ if (validator is null) {
+ return true;
+ }
+
+ errorMessage = validator.isValid(value);
+ return (errorMessage is null || errorMessage.equals(""));//$NON-NLS-1$
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the cut action.
+ *
+ * This default implementation always returns
+ * false
.
+ *
+ * Subclasses may override + *
+ * @returntrue
if cut is possible,
+ * false
otherwise
+ */
+ public bool isCutEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the delete action.
+ *
+ * This default implementation always returns
+ * false
.
+ *
+ * Subclasses may override + *
+ * @returntrue
if delete is possible,
+ * false
otherwise
+ */
+ public bool isDeleteEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns whether the value of this cell editor has changed since the
+ * last call to setValue
.
+ *
+ * @return true
if the value has changed, and false
+ * if unchanged
+ */
+ public bool isDirty() {
+ return dirty;
+ }
+
+ /**
+ * Marks this cell editor as dirty.
+ * @since 2.1
+ */
+ protected void markDirty() {
+ dirty = true;
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the find action.
+ *
+ * This default implementation always returns
+ * false
.
+ *
+ * Subclasses may override + *
+ * @returntrue
if find is possible,
+ * false
otherwise
+ */
+ public bool isFindEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the paste action.
+ *
+ * This default implementation always returns
+ * false
.
+ *
+ * Subclasses may override + *
+ * @returntrue
if paste is possible,
+ * false
otherwise
+ */
+ public bool isPasteEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the redo action.
+ *
+ * This default implementation always returns
+ * false
.
+ *
+ * Subclasses may override + *
+ * @returntrue
if redo is possible,
+ * false
otherwise
+ */
+ public bool isRedoEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the select all action.
+ *
+ * This default implementation always returns
+ * false
.
+ *
+ * Subclasses may override + *
+ * @returntrue
if select all is possible,
+ * false
otherwise
+ */
+ public bool isSelectAllEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the undo action.
+ *
+ * This default implementation always returns
+ * false
.
+ *
+ * Subclasses may override + *
+ * @returntrue
if undo is possible,
+ * false
otherwise
+ */
+ public bool isUndoEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns whether this cell editor has a valid value.
+ * The default value is false.
+ *
+ * @return true
if the value is valid, and false
+ * if invalid
+ *
+ * @see #setValueValid(bool)
+ */
+ public bool isValueValid() {
+ return valid;
+ }
+
+ /**
+ * Processes a key release event that occurred in this cell editor.
+ * + * The default implementation of this framework method cancels editing + * when the ESC key is pressed. When the RETURN key is pressed the current + * value is applied and the cell editor deactivates. + * Subclasses should call this method at appropriate times. + * Subclasses may also extend or reimplement. + *
+ * + * @param keyEvent the key event + */ + protected void keyReleaseOccured(KeyEvent keyEvent) { + if (keyEvent.character is '\u001b') { // Escape character + fireCancelEditor(); + } else if (keyEvent.character is '\r') { // Return key + fireApplyEditorValue(); + deactivate(); + } + } + + /** + * Processes a focus lost event that occurred in this cell editor. + *+ * The default implementation of this framework method applies the current + * value and deactivates the cell editor. + * Subclasses should call this method at appropriate times. + * Subclasses may also extend or reimplement. + *
+ */ + protected void focusLost() { + if (isActivated()) { + fireApplyEditorValue(); + deactivate(); + } + } + + /** + * Performs the copy action. + * This default implementation does nothing. + *+ * Subclasses may override + *
+ */ + public void performCopy() { + } + + /** + * Performs the cut action. + * This default implementation does nothing. + *+ * Subclasses may override + *
+ */ + public void performCut() { + } + + /** + * Performs the delete action. + * This default implementation does nothing. + *+ * Subclasses may override + *
+ */ + public void performDelete() { + } + + /** + * Performs the find action. + * This default implementation does nothing. + *+ * Subclasses may override + *
+ */ + public void performFind() { + } + + /** + * Performs the paste action. + * This default implementation does nothing. + *+ * Subclasses may override + *
+ */ + public void performPaste() { + } + + /** + * Performs the redo action. + * This default implementation does nothing. + *+ * Subclasses may override + *
+ */ + public void performRedo() { + } + + /** + * Performs the select all action. + * This default implementation does nothing. + *+ * Subclasses may override + *
+ */ + public void performSelectAll() { + } + + /** + * Performs the undo action. + * This default implementation does nothing. + *+ * Subclasses may override + *
+ */ + public void performUndo() { + } + + /** + * Removes the given listener from this cell editor. + * Has no affect if an identical listener is not registered. + * + * @param listener a cell editor listener + */ + public void removeListener(ICellEditorListener listener) { + listeners.remove(cast(Object)listener); + } + + /** + * Removes the given property change listener from this cell editor. + * Has no affect if an identical property change listener is not + * registered. + * + * @param listener a property change listener + */ + public void removePropertyChangeListener(IPropertyChangeListener listener) { + propertyChangeListeners.remove(cast(Object)listener); + } + + /** + * Sets or clears the current error message for this cell editor. + *+ * No formatting is done here, the message to be set is expected to be fully formatted + * before being passed in. + *
+ * @param message the error message, ornull
to clear
+ */
+ protected void setErrorMessage(String message) {
+ errorMessage = message;
+ }
+
+ /**
+ * Sets the focus to the cell editor's control.
+ */
+ public void setFocus() {
+ doSetFocus();
+ }
+
+ /**
+ * Sets the input validator for this cell editor.
+ *
+ * @param validator the input validator, or null
if none
+ */
+ public void setValidator(ICellEditorValidator validator) {
+ this.validator = validator;
+ }
+
+ /**
+ * Sets this cell editor's value.
+ *
+ * @param value the value of this cell editor
+ */
+ public final void setValue(Object value) {
+ valid = isCorrect(value);
+ dirty = false;
+ doSetValue(value);
+ }
+
+ /**
+ * Sets the valid state of this cell editor.
+ * The default value is false.
+ * Subclasses should call this method on construction.
+ *
+ * @param valid true
if the current value is valid,
+ * and false
if invalid
+ *
+ * @see #isValueValid
+ */
+ protected void setValueValid(bool valid) {
+ this.valid = valid;
+ }
+
+ /**
+ * The value has changed.
+ * Updates the valid state flag, marks this cell editor as dirty,
+ * and notifies all registered cell editor listeners of a value change.
+ *
+ * @param oldValidState the valid state before the end user changed the value
+ * @param newValidState the current valid state
+ * @see ICellEditorListener#editorValueChanged
+ */
+ protected void valueChanged(bool oldValidState, bool newValidState) {
+ valid = newValidState;
+ dirty = true;
+ fireEditorValueChanged(oldValidState, newValidState);
+ }
+
+ /**
+ * Activate the editor but also inform the editor which event triggered its activation.
+ * The default implementation simply calls {@link #activate()}
+ *
+ * @param activationEvent the editor activation event
+ * @since 3.3
+ */
+ public void activate(ColumnViewerEditorActivationEvent activationEvent) {
+ activate();
+ }
+
+ /**
+ * This method is for interal use in {@link ColumnViewerEditor} to not break clients
+ * who don't implement the {@link ICellEditorListener} appropiately
+ *
+ * @return true
to indicate that a focus listener has to be attached
+ */
+ bool dependsOnExternalFocusListener() {
+ return true;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/CellLabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/CellLabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Shindl This class is intended to be subclassed
+ * + * @since 3.3 + * @see ColumnLabelProvider as a concrete implementation + */ +public abstract class CellLabelProvider : BaseLabelProvider { + + /** + * Create a new instance of the receiver. + */ + public this() { + } + + /** + * Create a ViewerLabelProvider for the column at index + * + * @param labelProvider + * The labelProvider to convert + * @return ViewerLabelProvider + */ + /* package */static CellLabelProvider createViewerLabelProvider( + ColumnViewer viewer, IBaseLabelProvider labelProvider) { + + bool noColumnTreeViewer = ( null !is cast(AbstractTreeViewer)viewer ) && viewer + .doGetColumnCount_package() is 0; + + if (!noColumnTreeViewer + && (null !is cast(ITableLabelProvider) labelProvider + || null !is cast(ITableColorProvider) labelProvider || null !is cast(ITableFontProvider)labelProvider )) + return new TableColumnViewerLabelProvider(labelProvider); + if ( cast(CellLabelProvider)labelProvider ) + return cast(CellLabelProvider) labelProvider; + return new WrappedViewerLabelProvider(labelProvider); + + } + + /** + * Get the image displayed in the tool tip for object. + * + *
+ * If {@link #getToolTipText(Object)} and
+ * {@link #getToolTipImage(Object)} both return null
the
+ * control is set back to standard behavior
+ *
null
if there is not image.
+ */
+
+ public Image getToolTipImage(Object object) {
+ return null;
+ }
+
+ /**
+ * Get the text displayed in the tool tip for object.
+ *
+ *
+ * If {@link #getToolTipText(Object)} and
+ * {@link #getToolTipImage(Object)} both return null
the
+ * control is set back to standard behavior
+ *
null
if there is not text to
+ * display
+ */
+ public String getToolTipText(Object element) {
+ return null;
+ }
+
+ /**
+ * Return the background color used for the tool tip
+ *
+ * @param object
+ * the {@link Object} for which the tool tip is shown
+ *
+ * @return the {@link Color} used or null
if you want to use
+ * the default color {@link DWT#COLOR_INFO_BACKGROUND}
+ * @see DWT#COLOR_INFO_BACKGROUND
+ */
+ public Color getToolTipBackgroundColor(Object object) {
+ return null;
+ }
+
+ /**
+ * The foreground color used to display the the text in the tool tip
+ *
+ * @param object
+ * the {@link Object} for which the tool tip is shown
+ * @return the {@link Color} used or null
if you want to use
+ * the default color {@link DWT#COLOR_INFO_FOREGROUND}
+ * @see DWT#COLOR_INFO_FOREGROUND
+ */
+ public Color getToolTipForegroundColor(Object object) {
+ return null;
+ }
+
+ /**
+ * Get the {@link Font} used to display the tool tip
+ *
+ * @param object
+ * the element for which the tool tip is shown
+ * @return {@link Font} or null
if the default font is to be
+ * used.
+ */
+ public Font getToolTipFont(Object object) {
+ return null;
+ }
+
+ /**
+ * Return the amount of pixels in x and y direction you want the tool tip to
+ * pop up from the mouse pointer. The default shift is 10px right and 0px
+ * below your mouse cursor. Be aware of the fact that you should at least
+ * position the tool tip 1px right to your mouse cursor else click events
+ * may not get propagated properly.
+ *
+ * @param object
+ * the element for which the tool tip is shown
+ * @return {@link Point} to shift of the tool tip or null
if the
+ * default shift should be used.
+ */
+ public Point getToolTipShift(Object object) {
+ return null;
+ }
+
+ /**
+ * Return whether or not to use the native tool tip. If you switch to native
+ * tool tips only the value from {@link #getToolTipText(Object)} is used all
+ * other features from custom tool tips are not supported.
+ *
+ *
+ * To reset the control to native behavior you should return
+ * true
from this method and null
from
+ * {@link #getToolTipText(Object)} or null
from
+ * {@link #getToolTipText(Object)} and {@link #getToolTipImage(Object)} at
+ * the same time
+ *
true
if native tool tips should be used
+ */
+ public bool useNativeToolTip(Object object) {
+ return false;
+ }
+
+ /**
+ * The time in milliseconds the tool tip is shown for.
+ *
+ * @param object
+ * the {@link Object} for which the tool tip is shown
+ * @return time in milliseconds the tool tip is shown for
+ */
+ public int getToolTipTimeDisplayed(Object object) {
+ return 0;
+ }
+
+ /**
+ * The time in milliseconds until the tool tip is displayed.
+ *
+ * @param object
+ * the {@link Object} for which the tool tip is shown
+ * @return time in milliseconds until the tool tip is displayed
+ */
+ public int getToolTipDisplayDelayTime(Object object) {
+ return 0;
+ }
+
+ /**
+ * The {@link DWT} style used to create the {@link CLabel} (see there for
+ * supported styles). By default {@link DWT#SHADOW_NONE} is used.
+ *
+ * @param object
+ * the element for which the tool tip is shown
+ * @return the style used to create the label
+ * @see CLabel
+ */
+ public int getToolTipStyle(Object object) {
+ return DWT.SHADOW_NONE;
+ }
+
+ /**
+ * Update the label for cell.
+ *
+ * @param cell
+ * {@link ViewerCell}
+ */
+ public abstract void update(ViewerCell cell);
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/CellNavigationStrategy.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/CellNavigationStrategy.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * Subclasses can implement their custom navigation algorithms + *
+ * + * @since 3.3 + * + */ +public class CellNavigationStrategy { + /** + * is the given event an event which moves the selection to another cell + * + * @param viewer + * the viewer we are working for + * @param event + * the key event + * @returntrue
if a new cell is searched
+ */
+ public bool isNavigationEvent(ColumnViewer viewer, Event event) {
+ switch (event.keyCode) {
+ case DWT.ARROW_UP:
+ case DWT.ARROW_DOWN:
+ case DWT.ARROW_LEFT:
+ case DWT.ARROW_RIGHT:
+ case DWT.HOME:
+ case DWT.PAGE_DOWN:
+ case DWT.PAGE_UP:
+ case DWT.END:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * @param viewer
+ * the viewer we are working for
+ * @param cellToCollapse
+ * the cell to collapse
+ * @param event
+ * the key event
+ * @return true
if this event triggers collapsing of a node
+ */
+ public bool isCollapseEvent(ColumnViewer viewer,
+ ViewerCell cellToCollapse, Event event) {
+ return false;
+ }
+
+ /**
+ * @param viewer
+ * the viewer we are working for
+ * @param cellToExpand
+ * the cell to expand
+ * @param event
+ * the key event
+ * @return true
if this event triggers expanding of a node
+ */
+ public bool isExpandEvent(ColumnViewer viewer, ViewerCell cellToExpand,
+ Event event) {
+ return false;
+ }
+
+ /**
+ * @param viewer
+ * the viewer working for
+ * @param cellToExpand
+ * the cell the user wants to expand
+ * @param event
+ * the event triggering the expansion
+ */
+ public void expand(ColumnViewer viewer, ViewerCell cellToExpand, Event event) {
+
+ }
+
+ /**
+ * @param viewer
+ * the viewer working for
+ * @param cellToCollapse
+ * the cell the user wants to collapse
+ * @param event
+ * the event triggering the expansion
+ */
+ public void collapse(ColumnViewer viewer, ViewerCell cellToCollapse,
+ Event event) {
+
+ }
+
+ /**
+ * @param viewer
+ * the viewer we are working for
+ * @param currentSelectedCell
+ * the cell currently selected
+ * @param event
+ * the key event
+ * @return the cell which is highlighted next or null
if the
+ * default implementation is taken. E.g. it's fairly impossible to
+ * react on PAGE_DOWN requests
+ */
+ public ViewerCell findSelectedCell(ColumnViewer viewer,
+ ViewerCell currentSelectedCell, Event event) {
+
+ switch (event.keyCode) {
+ case DWT.ARROW_UP:
+ if (currentSelectedCell !is null) {
+ return currentSelectedCell.getNeighbor(ViewerCell.ABOVE, false);
+ }
+ break;
+ case DWT.ARROW_DOWN:
+ if (currentSelectedCell !is null) {
+ return currentSelectedCell.getNeighbor(ViewerCell.BELOW, false);
+ }
+ break;
+ case DWT.ARROW_LEFT:
+ if (currentSelectedCell !is null) {
+ return currentSelectedCell.getNeighbor(ViewerCell.LEFT, true);
+ }
+ break;
+ case DWT.ARROW_RIGHT:
+ if (currentSelectedCell !is null) {
+ return currentSelectedCell.getNeighbor(ViewerCell.RIGHT, true);
+ }
+ break;
+ }
+
+ return null;
+ }
+
+ /**
+ * This method is consulted to decide whether an event has to be canceled or
+ * not. By default events who collapse/expand tree-nodes are canceled
+ *
+ * @param viewer
+ * the viewer working for
+ * @param event
+ * the event
+ * @return true
if the event has to be canceled
+ */
+ public bool shouldCancelEvent(ColumnViewer viewer, Event event) {
+ return event.keyCode is DWT.ARROW_LEFT
+ || event.keyCode is DWT.ARROW_RIGHT;
+ }
+
+ /**
+ * This method is called by the framework to initialize this navigation
+ * strategy object. Subclasses may extend.
+ */
+ protected void init() {
+ }
+ package void init_package() {
+ init();
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/CheckStateChangedEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/CheckStateChangedEvent.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * This class may be instantiated; it is not intended to be subclassed. + *
+ *
+ * Note that this implementation simply fakes it and does does not create
+ * any new controls. The mere activation of this editor means that the value
+ * of the check box is being toggled by the end users; the listener method
+ * applyEditorValue
is immediately called to signal the change.
+ *
false
.
+ * Initially, the cell editor has no cell validator.
+ *
+ * @param parent the parent control
+ */
+ public this(Composite parent) {
+ this(parent, defaultStyle);
+ }
+
+ /**
+ * Creates a new checkbox cell editor parented under the given control.
+ * The cell editor value is a bool value, which is initially false
.
+ * Initially, the cell editor has no cell validator.
+ *
+ * @param parent the parent control
+ * @param style the style bits
+ * @since 2.1
+ */
+ public this(Composite parent, int style) {
+ super(parent, style);
+ }
+
+ /**
+ * The CheckboxCellEditor
implementation of
+ * this CellEditor
framework method simulates
+ * the toggling of the checkbox control and notifies
+ * listeners with ICellEditorListener.applyEditorValue
.
+ */
+ public void activate() {
+ value = !value;
+ fireApplyEditorValue();
+ }
+
+ /**
+ * The CheckboxCellEditor
implementation of
+ * this CellEditor
framework method does
+ * nothing and returns null
.
+ */
+ protected Control createControl(Composite parent) {
+ return null;
+ }
+
+ /**
+ * The CheckboxCellEditor
implementation of
+ * this CellEditor
framework method returns
+ * the checkbox setting wrapped as a bool
.
+ *
+ * @return the bool checkbox value
+ */
+ protected Object doGetValue() {
+ return new ValueWrapperBool( value );
+ }
+
+ /* (non-Javadoc)
+ * Method declared on CellEditor.
+ */
+ protected void doSetFocus() {
+ // Ignore
+ }
+
+ /**
+ * The CheckboxCellEditor
implementation of
+ * this CellEditor
framework method accepts
+ * a value wrapped as a bool
.
+ *
+ * @param value a bool value
+ */
+ protected void doSetValue(Object value) {
+ Assert.isTrue( null !is cast(ValueWrapperBool)value );
+ this.value = (cast(ValueWrapperBool) value).value;
+ }
+
+ public void activate(ColumnViewerEditorActivationEvent activationEvent) {
+ if (activationEvent.eventType !is ColumnViewerEditorActivationEvent.TRAVERSAL) {
+ super.activate(activationEvent);
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/CheckboxTableViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/CheckboxTableViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,462 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit Table
+ * control with checkboxes on each node.
+ * + * This class is not intended to be subclassed outside the viewer framework. + * It is designed to be instantiated with a pre-existing DWT table control and configured + * with a domain-specific content provider, label provider, element filter (optional), + * and element sorter (optional). + *
+ */ +public class CheckboxTableViewer : TableViewer, ICheckable { + + /** + * List of check state listeners (element type:ICheckStateListener
).
+ */
+ private ListenerList checkStateListeners;
+
+ /**
+ * Creates a table viewer on a newly-created table control under the given parent.
+ * The table control is created using the DWT style bits:
+ * DWT.CHECK
and DWT.BORDER
.
+ * The table has one column.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * This is equivalent to calling new CheckboxTableViewer(parent, DWT.BORDER)
.
+ * See that constructor for more details.
+ *
DWT.CHECK
style bit.
+ * The table has one column.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * This also adds a TableColumn
for the single column,
+ * and sets a TableLayout
on the table which sizes the column to fill
+ * the table for its initial sizing, but does nothing on subsequent resizes.
+ *
+ * If the caller just needs to show a single column with no header,
+ * it is preferable to use the newCheckList
factory method instead,
+ * since DWT properly handles the initial sizing and subsequent resizes in this case.
+ *
+ * If the caller adds its own columns, uses Table.setHeadersVisible(true)
,
+ * or needs to handle dynamic resizing of the table, it is recommended to
+ * create the Table
itself, specifying the DWT.CHECK
style bit
+ * (along with any other style bits needed), and use new CheckboxTableViewer(Table)
+ * rather than this constructor.
+ *
DWT.CHECK
style bit.
+ * The table shows its contents in a single column, with no header.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * No TableColumn
is added. DWT does not require a
+ * TableColumn
if showing only a single column with no header.
+ * DWT correctly handles the initial sizing and subsequent resizes in this case.
+ *
+ * @param parent the parent control
+ * @param style DWT style bits
+ *
+ * @since 2.0
+ * @return CheckboxTableViewer
+ */
+ public static CheckboxTableViewer newCheckList(Composite parent, int style) {
+ Table table = new Table(parent, DWT.CHECK | style);
+ return new CheckboxTableViewer(table);
+ }
+
+ /**
+ * Creates a table viewer on the given table control.
+ * The DWT.CHECK
style bit must be set on the given table control.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param table the table control
+ */
+ public this(Table table) {
+ super(table);
+ checkStateListeners = new ListenerList();
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ICheckable.
+ */
+ public void addCheckStateListener(ICheckStateListener listener) {
+ checkStateListeners.add(cast(Object)listener);
+ }
+
+ /**
+ * Creates a new table control with one column.
+ *
+ * @param parent the parent control
+ * @param style style bits
+ * @return a new table control
+ */
+ protected static Table createTable(Composite parent, int style) {
+ Table table = new Table(parent, DWT.CHECK | style);
+
+ // Although this table column is not needed, and can cause resize problems,
+ // it can't be removed since this would be a breaking change against R1.0.
+ // See bug 6643 for more details.
+ new TableColumn(table, DWT.NONE);
+ TableLayout layout = new TableLayout();
+ layout.addColumnData(new ColumnWeightData(100));
+ table.setLayout(layout);
+
+ return table;
+ }
+
+ /**
+ * Notifies any check state listeners that a check state changed has been received.
+ * Only listeners registered at the time this method is called are notified.
+ *
+ * @param event a check state changed event
+ *
+ * @see ICheckStateListener#checkStateChanged
+ */
+ private void fireCheckStateChanged(CheckStateChangedEvent event) {
+ Object[] array = checkStateListeners.getListeners();
+ for (int i = 0; i < array.length; i++) {
+ SafeRunnable.run(new class SafeRunnable {
+ ICheckStateListener l;
+ CheckStateChangedEvent event_;
+ this(){
+ event_=event;
+ l = cast(ICheckStateListener) array[i];
+ }
+ public void run() {
+ l.checkStateChanged(event_);
+ }
+ });
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ICheckable.
+ */
+ public bool getChecked(Object element) {
+ Widget widget = findItem(element);
+ if ( auto ti = cast(TableItem) widget ) {
+ return ti.getChecked();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a list of elements corresponding to checked table items in this
+ * viewer.
+ *
+ * This method is typically used when preserving the interesting
+ * state of a viewer; setCheckedElements
is used during the restore.
+ *
true
if the element is grayed,
+ * and false
if not grayed
+ */
+ public bool getGrayed(Object element) {
+ Widget widget = findItem(element);
+ if ( auto ti = cast(TableItem) widget ) {
+ return ti.getGrayed();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a list of elements corresponding to grayed nodes in this
+ * viewer.
+ *
+ * This method is typically used when preserving the interesting
+ * state of a viewer; setGrayedElements
is used during the restore.
+ *
true
if the element should be checked,
+ * and false
if it should be unchecked
+ */
+ public void setAllChecked(bool state) {
+ TableItem[] children = getTable().getItems();
+ for (int i = 0; i < children.length; i++) {
+ TableItem item = children[i];
+ item.setChecked(state);
+ }
+ }
+
+ /**
+ * Sets to the given value the grayed state for all elements in this viewer.
+ *
+ * @param state true
if the element should be grayed,
+ * and false
if it should be ungrayed
+ */
+ public void setAllGrayed(bool state) {
+ TableItem[] children = getTable().getItems();
+ for (int i = 0; i < children.length; i++) {
+ TableItem item = children[i];
+ item.setGrayed(state);
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ICheckable.
+ */
+ public bool setChecked(Object element, bool state) {
+ Assert.isNotNull(element);
+ Widget widget = findItem(element);
+ if ( auto ti = cast(TableItem) widget ) {
+ ti.setChecked(state);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets which nodes are checked in this viewer.
+ * The given list contains the elements that are to be checked;
+ * all other nodes are to be unchecked.
+ * Does not fire events to check state listeners.
+ *
+ * This method is typically used when restoring the interesting
+ * state of a viewer captured by an earlier call to getCheckedElements
.
+ *
Object
)
+ * @see #getCheckedElements
+ */
+ public void setCheckedElements(Object[] elements) {
+ assertElementsNotNull(elements);
+ CustomHashtable set = newHashtable(elements.length * 2 + 1);
+ for (int i = 0; i < elements.length; ++i) {
+ set.put(elements[i], elements[i]);
+ }
+ TableItem[] items = getTable().getItems();
+ for (int i = 0; i < items.length; ++i) {
+ TableItem item = items[i];
+ Object element = item.getData();
+ if (element !is null) {
+ bool check = set.containsKey(element);
+ // only set if different, to avoid flicker
+ if (item.getChecked() !is check) {
+ item.setChecked(check);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the grayed state for the given element in this viewer.
+ *
+ * @param element the element
+ * @param state true
if the item should be grayed,
+ * and false
if it should be ungrayed
+ * @return true
if the element is visible and the gray
+ * state could be set, and false
otherwise
+ */
+ public bool setGrayed(Object element, bool state) {
+ Assert.isNotNull(element);
+ Widget widget = findItem(element);
+ if ( auto ti = cast(TableItem) widget ) {
+ ti.setGrayed(state);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets which nodes are grayed in this viewer.
+ * The given list contains the elements that are to be grayed;
+ * all other nodes are to be ungrayed.
+ *
+ * This method is typically used when restoring the interesting
+ * state of a viewer captured by an earlier call to getGrayedElements
.
+ *
Tree
+ * control with checkboxes on each node.
+ * + * This class is not intended to be subclassed outside the viewer framework. + * It is designed to be instantiated with a pre-existing DWT tree control and configured + * with a domain-specific content provider, label provider, element filter (optional), + * and element sorter (optional). + *
+ */ +public class CheckboxTreeViewer : TreeViewer, ICheckable { + + /** + * List of check state listeners (element type:ICheckStateListener
).
+ */
+ private ListenerList checkStateListeners;
+
+ /**
+ * Last item clicked on, or null
if none.
+ */
+ private TreeItem lastClickedItem = null;
+
+ /**
+ * Creates a tree viewer on a newly-created tree control under the given parent.
+ * The tree control is created using the DWT style bits: CHECK
and BORDER
.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param parent the parent control
+ */
+ public this(Composite parent) {
+ this(parent, DWT.BORDER);
+ }
+
+ /**
+ * Creates a tree viewer on a newly-created tree control under the given parent.
+ * The tree control is created using the given DWT style bits, plus the CHECK
style bit.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param parent the parent control
+ * @param style the DWT style bits
+ */
+ public this(Composite parent, int style) {
+ this(new Tree(parent, DWT.CHECK | style));
+ }
+
+ /**
+ * Creates a tree viewer on the given tree control.
+ * The DWT.CHECK
style bit must be set on the given tree control.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param tree the tree control
+ */
+ public this(Tree tree) {
+ checkStateListeners = new ListenerList();
+ super(tree);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ICheckable.
+ */
+ public void addCheckStateListener(ICheckStateListener listener) {
+ checkStateListeners.add(cast(Object)listener);
+ }
+
+ /**
+ * Applies the checked and grayed states of the given widget and its
+ * descendents.
+ *
+ * @param checked a set of elements (element type: Object
)
+ * @param grayed a set of elements (element type: Object
)
+ * @param widget the widget
+ */
+ private void applyState(CustomHashtable checked, CustomHashtable grayed,
+ Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ if ( auto ti = cast(TreeItem) item ) {
+ Object data = item.getData();
+ if (data !is null) {
+ ti.setChecked(checked.containsKey(data));
+ ti.setGrayed(grayed.containsKey(data));
+ }
+ }
+ applyState(checked, grayed, item);
+ }
+ }
+
+ /**
+ * Notifies any check state listeners that the check state of an element has changed.
+ * Only listeners registered at the time this method is called are notified.
+ *
+ * @param event a check state changed event
+ *
+ * @see ICheckStateListener#checkStateChanged
+ */
+ protected void fireCheckStateChanged(CheckStateChangedEvent event) {
+ Object[] array = checkStateListeners.getListeners();
+ for (int i = 0; i < array.length; i++) {
+ SafeRunnable.run(new class SafeRunnable {
+ ICheckStateListener l;
+ this(){
+ l = cast(ICheckStateListener) array[i];
+ }
+ public void run() {
+ l.checkStateChanged(event);
+ }
+ });
+ }
+
+ }
+
+ /**
+ * Gathers the checked and grayed states of the given widget and its
+ * descendents.
+ *
+ * @param checked a writable set of elements (element type: Object
)
+ * @param grayed a writable set of elements (element type: Object
)
+ * @param widget the widget
+ */
+ private void gatherState(CustomHashtable checked, CustomHashtable grayed,
+ Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ if ( auto ti = cast(TreeItem) item ) {
+ Object data = item.getData();
+ if (data !is null) {
+ if (ti.getChecked()) {
+ checked.put(data, data);
+ }
+ if (ti.getGrayed()) {
+ grayed.put(data, data);
+ }
+ }
+ }
+ gatherState(checked, grayed, item);
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ICheckable.
+ */
+ public bool getChecked(Object element) {
+ Widget widget = findItem(element);
+ if ( auto ti = cast(TreeItem) widget ) {
+ return ti.getChecked();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a list of checked elements in this viewer's tree,
+ * including currently hidden ones that are marked as
+ * checked but are under a collapsed ancestor.
+ *
+ * This method is typically used when preserving the interesting
+ * state of a viewer; setCheckedElements
is used during the restore.
+ *
true
if the element is grayed,
+ * and false
if not grayed
+ */
+ public bool getGrayed(Object element) {
+ Widget widget = findItem(element);
+ if ( auto ti = cast(TreeItem) widget ) {
+ return ti.getGrayed();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a list of grayed elements in this viewer's tree,
+ * including currently hidden ones that are marked as
+ * grayed but are under a collapsed ancestor.
+ *
+ * This method is typically used when preserving the interesting
+ * state of a viewer; setGrayedElements
is used during the restore.
+ *
Object
)
+ * @param widget the widget
+ */
+ private void internalCollectChecked(Seq!(Object) result, Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ if ( null !is cast(TreeItem)item && (cast(TreeItem) item).getChecked()) {
+ Object data = item.getData();
+ if (data !is null) {
+ result.append(data);
+ }
+ }
+ internalCollectChecked(result, item);
+ }
+ }
+
+ /**
+ * Gathers the grayed states of the given widget and its
+ * descendents, following a pre-order traversal of the tree.
+ *
+ * @param result a writable list of elements (element type: Object
)
+ * @param widget the widget
+ */
+ private void internalCollectGrayed(Seq!(Object) result, Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ if (null !is cast(TreeItem)item && (cast(TreeItem) item).getGrayed()) {
+ Object data = item.getData();
+ if (data !is null) {
+ result.append(data);
+ }
+ }
+ internalCollectGrayed(result, item);
+ }
+ }
+
+ /**
+ * Sets the checked state of all items to correspond to the given set of checked elements.
+ *
+ * @param checkedElements the set (element type: Object
) of elements which are checked
+ * @param widget the widget
+ */
+ private void internalSetChecked(CustomHashtable checkedElements,
+ Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ TreeItem item = cast(TreeItem) items[i];
+ Object data = item.getData();
+ if (data !is null) {
+ bool checked = checkedElements.containsKey(data);
+ if (checked !is item.getChecked()) {
+ item.setChecked(checked);
+ }
+ }
+ internalSetChecked(checkedElements, item);
+ }
+ }
+
+ /**
+ * Sets the grayed state of all items to correspond to the given set of grayed elements.
+ *
+ * @param grayedElements the set (element type: Object
) of elements which are grayed
+ * @param widget the widget
+ */
+ private void internalSetGrayed(CustomHashtable grayedElements, Widget widget) {
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ TreeItem item = cast(TreeItem) items[i];
+ Object data = item.getData();
+ if (data !is null) {
+ bool grayed = grayedElements.containsKey(data);
+ if (grayed !is item.getGrayed()) {
+ item.setGrayed(grayed);
+ }
+ }
+ internalSetGrayed(grayedElements, item);
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Viewer.
+ */
+ protected void preservingSelection(Runnable updateCode) {
+
+ int n = getItemCount(getControl());
+ CustomHashtable checkedNodes = newHashtable(n * 2 + 1);
+ CustomHashtable grayedNodes = newHashtable(n * 2 + 1);
+
+ gatherState(checkedNodes, grayedNodes, getControl());
+
+ super.preservingSelection(updateCode);
+
+ applyState(checkedNodes, grayedNodes, getControl());
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ICheckable.
+ */
+ public void removeCheckStateListener(ICheckStateListener listener) {
+ checkStateListeners.remove(cast(Object)listener);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ICheckable.
+ */
+ public bool setChecked(Object element, bool state) {
+ Assert.isNotNull(element);
+ Widget widget = internalExpand(element, false);
+ if ( auto ti = cast(TreeItem) widget ) {
+ ti.setChecked(state);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the checked state for the children of the given item.
+ *
+ * @param item the item
+ * @param state true
if the item should be checked,
+ * and false
if it should be unchecked
+ */
+ private void setCheckedChildren(Item item, bool state) {
+ createChildren(item);
+ Item[] items = getChildren(item);
+ if (items !is null) {
+ for (int i = 0; i < items.length; i++) {
+ Item it = items[i];
+ if (it.getData() !is null && (null !is cast(TreeItem)it )) {
+ TreeItem treeItem = cast(TreeItem) it;
+ treeItem.setChecked(state);
+ setCheckedChildren(treeItem, state);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets which elements are checked in this viewer's tree.
+ * The given list contains the elements that are to be checked;
+ * all other elements are to be unchecked.
+ * Does not fire events to check state listeners.
+ *
+ * This method is typically used when restoring the interesting
+ * state of a viewer captured by an earlier call to getCheckedElements
.
+ *
true
if the item should be grayed,
+ * and false
if it should be ungrayed
+ * @return true
if the gray state could be set,
+ * and false
otherwise
+ */
+ public bool setGrayed(Object element, bool state) {
+ Assert.isNotNull(element);
+ Widget widget = internalExpand(element, false);
+ if ( auto ti = cast(TreeItem) widget ) {
+ ti.setGrayed(state);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check and gray the selection rather than calling both
+ * setGrayed and setChecked as an optimization.
+ * Does not fire events to check state listeners.
+ * @param element the item being checked
+ * @param state a bool indicating selection or deselection
+ * @return bool indicating success or failure.
+ */
+ public bool setGrayChecked(Object element, bool state) {
+ Assert.isNotNull(element);
+ Widget widget = internalExpand(element, false);
+ if (auto item = cast(TreeItem)widget ) {
+ item.setChecked(state);
+ item.setGrayed(state);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets which elements are grayed in this viewer's tree.
+ * The given list contains the elements that are to be grayed;
+ * all other elements are to be ungrayed.
+ *
+ * This method is typically used when restoring the interesting
+ * state of a viewer captured by an earlier call to getGrayedElements
.
+ *
true
if the item should be grayed,
+ * and false
if it should be ungrayed
+ * @return true
if the element is visible and the gray
+ * state could be set, and false
otherwise
+ * @see #setGrayed
+ */
+ public bool setParentsGrayed(Object element, bool state) {
+ Assert.isNotNull(element);
+ Widget widget = internalExpand(element, false);
+ if (auto item = cast(TreeItem) widget ) {
+ item.setGrayed(state);
+ item = item.getParentItem();
+ while (item !is null) {
+ item.setGrayed(state);
+ item = item.getParentItem();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the checked state for the given element and its visible
+ * children in this viewer.
+ * Assumes that the element has been expanded before. To enforce
+ * that the item is expanded, call expandToLevel
+ * for the element.
+ * Does not fire events to check state listeners.
+ *
+ * @param element the element
+ * @param state true
if the item should be checked,
+ * and false
if it should be unchecked
+ * @return true
if the checked state could be set,
+ * and false
otherwise
+ */
+ public bool setSubtreeChecked(Object element, bool state) {
+ Widget widget = internalExpand(element, false);
+ if (auto item = cast(TreeItem) widget ) {
+ item.setChecked(state);
+ setCheckedChildren(item, state);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets to the given value the checked state for all elements in this viewer.
+ * Does not fire events to check state listeners.
+ *
+ * @param state true
if the element should be checked,
+ * and false
if it should be unchecked
+ *
+ * @since 3.2
+ */
+ public void setAllChecked(bool state) {
+ setAllChecked(state, getTree().getItems());
+
+ }
+
+ /**
+ * Set the checked state of items and their children to state.
+ * @param state
+ * @param items
+ */
+ private void setAllChecked(bool state, TreeItem[] items) {
+ for (int i = 0; i < items.length; i++) {
+ items[i].setChecked(state);
+ TreeItem[] children = items[i].getItems();
+ setAllChecked(state, children);
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColorCellEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ColorCellEditor.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit RBG
).
+ * + * This class may be instantiated; it is not intended to be subclassed. + *
+ */ +public class ColorCellEditor : DialogCellEditor { + + /** + * The default extent in pixels. + */ + private static const int DEFAULT_EXTENT = 16; + + /** + * Gap between between image and text in pixels. + */ + private static const int GAP = 6; + + /** + * The composite widget containing the color and RGB label widgets + */ + private Composite composite; + + /** + * The label widget showing the current color. + */ + private Label colorLabel; + + /** + * The label widget showing the RGB values. + */ + private Label rgbLabel; + + /** + * The image. + */ + private Image image; + + /** + * Internal class for laying out this cell editor. + */ + private class ColorCellLayout : Layout { + public Point computeSize(Composite editor, int wHint, int hHint, + bool force) { + if (wHint !is DWT.DEFAULT && hHint !is DWT.DEFAULT) { + return new Point(wHint, hHint); + } + Point colorSize = colorLabel.computeSize(DWT.DEFAULT, DWT.DEFAULT, + force); + Point rgbSize = rgbLabel.computeSize(DWT.DEFAULT, DWT.DEFAULT, + force); + return new Point(colorSize.x + GAP + rgbSize.x, Math.max( + colorSize.y, rgbSize.y)); + } + + public void layout(Composite editor, bool force) { + Rectangle bounds = editor.getClientArea(); + Point colorSize = colorLabel.computeSize(DWT.DEFAULT, DWT.DEFAULT, + force); + Point rgbSize = rgbLabel.computeSize(DWT.DEFAULT, DWT.DEFAULT, + force); + int ty = (bounds.height - rgbSize.y) / 2; + if (ty < 0) { + ty = 0; + } + colorLabel.setBounds(-1, 0, colorSize.x, colorSize.y); + rgbLabel.setBounds(colorSize.x + GAP - 1, ty, bounds.width + - colorSize.x - GAP, bounds.height); + } + } + + /** + * Creates a new color cell editor parented under the given control. + * The cell editor value is black (RGB(0,0,0)
) initially, and has no
+ * validator.
+ *
+ * @param parent the parent control
+ */
+ public this(Composite parent) {
+ this(parent, DWT.NONE);
+ }
+
+ /**
+ * Creates a new color cell editor parented under the given control.
+ * The cell editor value is black (RGB(0,0,0)
) initially, and has no
+ * validator.
+ *
+ * @param parent the parent control
+ * @param style the style bits
+ * @since 2.1
+ */
+ public this(Composite parent, int style) {
+ super(parent, style);
+ doSetValue(new RGB(0, 0, 0));
+ }
+
+ /**
+ * Creates and returns the color image data for the given control
+ * and RGB value. The image's size is either the control's item extent
+ * or the cell editor's default extent, which is 16 pixels square.
+ *
+ * @param w the control
+ * @param color the color
+ */
+ private ImageData createColorImage(Control w, RGB color) {
+
+ GC gc = new GC(w);
+ FontMetrics fm = gc.getFontMetrics();
+ int size = fm.getAscent();
+ gc.dispose();
+
+ int indent = 6;
+ int extent = DEFAULT_EXTENT;
+ if ( auto i = cast(Table)w ) {
+ extent = i.getItemHeight() - 1;
+ } else if ( auto i = cast(Tree)w ) {
+ extent = i.getItemHeight() - 1;
+ } else if ( auto i = cast(TableTree)w ) {
+ extent = i.getItemHeight() - 1;
+ }
+
+ if (size > extent) {
+ size = extent;
+ }
+
+ int width = indent + size;
+ int height = extent;
+
+ int xoffset = indent;
+ int yoffset = (height - size) / 2;
+
+ RGB black = new RGB(0, 0, 0);
+ PaletteData dataPalette = new PaletteData([ black, black,
+ color ]);
+ ImageData data = new ImageData(width, height, 4, dataPalette);
+ data.transparentPixel = 0;
+
+ int end = size - 1;
+ for (int y = 0; y < size; y++) {
+ for (int x = 0; x < size; x++) {
+ if (x is 0 || y is 0 || x is end || y is end) {
+ data.setPixel(x + xoffset, y + yoffset, 1);
+ } else {
+ data.setPixel(x + xoffset, y + yoffset, 2);
+ }
+ }
+ }
+
+ return data;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DialogCellEditor.
+ */
+ protected Control createContents(Composite cell) {
+ Color bg = cell.getBackground();
+ composite = new Composite(cell, getStyle());
+ composite.setBackground(bg);
+ composite.setLayout(new ColorCellLayout());
+ colorLabel = new Label(composite, DWT.LEFT);
+ colorLabel.setBackground(bg);
+ rgbLabel = new Label(composite, DWT.LEFT);
+ rgbLabel.setBackground(bg);
+ rgbLabel.setFont(cell.getFont());
+ return composite;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on CellEditor.
+ */
+ public void dispose() {
+ if (image !is null) {
+ image.dispose();
+ image = null;
+ }
+ super.dispose();
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DialogCellEditor.
+ */
+ protected Object openDialogBox(Control cellEditorWindow) {
+ ColorDialog dialog = new ColorDialog(cellEditorWindow.getShell());
+ Object value = getValue();
+ if (value !is null) {
+ dialog.setRGB(cast(RGB) value);
+ }
+ value = dialog.open();
+ return dialog.getRGB();
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DialogCellEditor.
+ */
+ protected void updateContents(Object value) {
+ RGB rgb = cast(RGB) value;
+ // XXX: We don't have a value the first time this method is called".
+ if (rgb is null) {
+ rgb = new RGB(0, 0, 0);
+ }
+ // XXX: Workaround for 1FMQ0P3: DWT:ALL - TableItem.setImage doesn't work if using the identical image."
+ if (image !is null) {
+ image.dispose();
+ }
+
+ ImageData id = createColorImage(colorLabel.getParent().getParent(), rgb);
+ ImageData mask = id.getTransparencyMask();
+ image = new Image(colorLabel.getDisplay(), id, mask);
+ colorLabel.setImage(image);
+
+ rgbLabel
+ .setText( Format( "({},{},{})", rgb.red, rgb.green, rgb.blue));//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColumnLabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ColumnLabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit This classes is intended to be subclassed
+ * + * @since 3.3 + * + */ +public class ColumnLabelProvider : CellLabelProvider, + IFontProvider, IColorProvider, ILabelProvider { + + /* (non-Javadoc) + * @see dwtx.jface.viewers.CellLabelProvider#update(dwtx.jface.viewers.ViewerCell) + */ + public void update(ViewerCell cell) { + Object element = cell.getElement(); + cell.setText(getText(element)); + Image image = getImage(element); + cell.setImage(image); + cell.setBackground(getBackground(element)); + cell.setForeground(getForeground(element)); + cell.setFont(getFont(element)); + + } + + /* (non-Javadoc) + * @see dwtx.jface.viewers.IFontProvider#getFont(java.lang.Object) + */ + public Font getFont(Object element) { + return null; + } + + /* (non-Javadoc) + * @see dwtx.jface.viewers.IColorProvider#getBackground(java.lang.Object) + */ + public Color getBackground(Object element) { + return null; + } + + /* (non-Javadoc) + * @see dwtx.jface.viewers.IColorProvider#getForeground(java.lang.Object) + */ + public Color getForeground(Object element) { + return null; + } + + + /* (non-Javadoc) + * @see dwtx.jface.viewers.ILabelProvider#getImage(java.lang.Object) + */ + public Image getImage(Object element) { + return null; + } + + /* (non-Javadoc) + * @see dwtx.jface.viewers.ILabelProvider#getText(java.lang.Object) + */ + public String getText(Object element) { + return element is null ? "" : element.toString();//$NON-NLS-1$ + } + +} diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColumnLayoutData.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/viewers/ColumnLayoutData.d Mon Mar 31 00:47:19 2008 +0200 @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank BenoitTableLayout
) to properly lay out a table.
+ * + * This class is not intended to be subclassed outside the framework. + *
+ */ +public abstract class ColumnLayoutData { + + /** + * Indicates whether the column is resizable. + */ + public bool resizable; + + /** + * Creates a new column layout data object. + * + * @param resizabletrue
if the column is resizable, and false
if not
+ */
+ protected this(bool resizable) {
+ this.resizable = resizable;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColumnPixelData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ColumnPixelData.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * This class may be instantiated; it is not intended to be subclassed. + *
+ */ +public class ColumnPixelData : ColumnLayoutData { + + /** + * The column's width in pixels. + */ + public int width; + + /** + * Whether to allocate extra width to the column to account for + * trim taken by the column itself. + * The default isfalse
for backwards compatibility, but
+ * the recommended practice is to specify true
, and
+ * specify the desired width for the content of the column, rather
+ * than adding a fudge factor to the specified width.
+ *
+ * @since 3.1
+ */
+ public bool addTrim = false;
+
+ /**
+ * Creates a resizable column width of the given number of pixels.
+ *
+ * @param widthInPixels the width of column in pixels
+ */
+ public this(int widthInPixels) {
+ this(widthInPixels, true, false);
+ }
+
+ /**
+ * Creates a column width of the given number of pixels.
+ *
+ * @param widthInPixels the width of column in pixels
+ * @param resizable true
if the column is resizable,
+ * and false
if size of the column is fixed
+ */
+ public this(int widthInPixels, bool resizable) {
+ this(widthInPixels, resizable, false);
+ }
+
+ /**
+ * Creates a column width of the given number of pixels.
+ *
+ * @param widthInPixels
+ * the width of column in pixels
+ * @param resizable
+ * true
if the column is resizable, and
+ * false
if size of the column is fixed
+ * @param addTrim
+ * true
to allocate extra width to the column to
+ * account for trim taken by the column itself,
+ * false
to use the given width exactly
+ * @since 3.1
+ */
+ public this(int widthInPixels, bool resizable, bool addTrim) {
+ super(resizable);
+ Assert.isTrue(widthInPixels >= 0);
+ this.width = widthInPixels;
+ this.addTrim = addTrim;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColumnViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ColumnViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,769 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl null
if this viewer does not
+ * support editing cell contents.
+ */
+ protected abstract ColumnViewerEditor createViewerEditor();
+
+ /**
+ * Returns the viewer cell at the given widget-relative coordinates, or
+ * null
if there is no cell at that location
+ *
+ * @param point
+ * the widget-relative coordinates
+ * @return the cell or null
if no cell is found at the given
+ * point
+ */
+ ViewerCell getCell(Point point) {
+ ViewerRow row = getViewerRow(point);
+ if (row !is null) {
+ return row.getCell(point);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the viewer row at the given widget-relative coordinates.
+ *
+ * @param point
+ * the widget-relative coordinates of the viewer row
+ * @return ViewerRow the row or null
if no row is found at
+ * the given coordinates
+ */
+ protected ViewerRow getViewerRow(Point point) {
+ Item item = getItemAt(point);
+
+ if (item !is null) {
+ return getViewerRowFromItem(item);
+ }
+
+ return null;
+ }
+ package ViewerRow getViewerRow_package(Point point) {
+ return getViewerRow(point);
+ }
+
+
+
+ /**
+ * Returns a {@link ViewerRow} associated with the given row widget. Implementations
+ * may re-use the same instance for different row widgets; callers can only use the viewer
+ * row locally and until the next call to this method.
+ *
+ * @param item the row widget
+ * @return ViewerRow a viewer row object
+ */
+ protected abstract ViewerRow getViewerRowFromItem(Widget item);
+ package ViewerRow getViewerRowFromItem_package(Widget item){
+ return getViewerRowFromItem(item);
+ }
+
+ /**
+ * Returns the column widget at the given column index.
+ *
+ * @param columnIndex
+ * the column index
+ * @return Widget the column widget
+ */
+ protected abstract Widget getColumnViewerOwner(int columnIndex);
+
+ /**
+ * Returns the viewer column for the given column index.
+ *
+ * @param columnIndex
+ * the column index
+ * @return the viewer column at the given index, or null
if
+ * there is none for the given index
+ */
+ /* package */ViewerColumn getViewerColumn(int columnIndex) {
+
+ ViewerColumn viewer;
+ Widget columnOwner = getColumnViewerOwner(columnIndex);
+
+ if (columnOwner is null) {
+ return null;
+ }
+
+ viewer = cast(ViewerColumn) columnOwner
+ .getData(ViewerColumn.COLUMN_VIEWER_KEY);
+
+ if (viewer is null) {
+ viewer = createViewerColumn(columnOwner, CellLabelProvider
+ .createViewerLabelProvider(this, getLabelProvider()));
+ setupEditingSupport(columnIndex, viewer);
+ }
+
+ if (viewer.getEditingSupport() is null && getCellModifier() !is null) {
+ setupEditingSupport(columnIndex, viewer);
+ }
+
+ return viewer;
+ }
+
+ /**
+ * Sets up editing support for the given column based on the "old" cell
+ * editor API.
+ *
+ * @param columnIndex
+ * @param viewer
+ */
+ private void setupEditingSupport(int columnIndex, ViewerColumn viewer) {
+ if (getCellModifier() !is null) {
+ viewer.setEditingSupport(new class(this) EditingSupport {
+ int columnIndex_;
+ this(ColumnViewer cv){
+ super(cv);
+ columnIndex_=columnIndex;
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.EditingSupport#canEdit(java.lang.Object)
+ */
+ public bool canEdit(Object element) {
+ Object[] properties = getColumnProperties();
+
+ if( columnIndex_ < properties.length ) {
+ return getCellModifier().canModify(element,
+ (cast(ArrayWrapperString) getColumnProperties()[columnIndex_]).array);
+ }
+
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.EditingSupport#getCellEditor(java.lang.Object)
+ */
+ public CellEditor getCellEditor(Object element) {
+ CellEditor[] editors = getCellEditors();
+ if( columnIndex_ < editors.length ) {
+ return getCellEditors()[columnIndex_];
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.EditingSupport#getValue(java.lang.Object)
+ */
+ public Object getValue(Object element) {
+ Object[] properties = getColumnProperties();
+
+ if( columnIndex_ < properties.length ) {
+ return getCellModifier().getValue(element,
+ (cast(ArrayWrapperString) getColumnProperties()[columnIndex_]).array);
+ }
+
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.EditingSupport#setValue(java.lang.Object,
+ * java.lang.Object)
+ */
+ public void setValue(Object element, Object value) {
+ Object[] properties = getColumnProperties();
+
+ if( columnIndex_ < properties.length ) {
+ getCellModifier().modify(findItem(element),
+ (cast(ArrayWrapperString) getColumnProperties()[columnIndex_]).array, value);
+ }
+ }
+
+ bool isLegacySupport() {
+ return true;
+ }
+ });
+ }
+ }
+
+ /**
+ * Creates a generic viewer column for the given column widget, based on the
+ * given label provider.
+ *
+ * @param columnOwner
+ * the column widget
+ * @param labelProvider
+ * the label provider to use for the column
+ * @return ViewerColumn the viewer column
+ */
+ private ViewerColumn createViewerColumn(Widget columnOwner,
+ CellLabelProvider labelProvider) {
+ ViewerColumn column = new class(this, columnOwner) ViewerColumn {
+ this( ColumnViewer cv, Widget co ){
+ super(cv,co);
+ }
+ };
+ column.setLabelProvider(labelProvider, false);
+ return column;
+ }
+
+ /**
+ * Update the cached cell object with the given row and column. Be careful not
+ * to hold on to element objects longer than required. It is good practice to
+ * call updateCell(null, 0, null) to clear references immediately after using
+ * the cached cell object. (See bug 201280 for an example case where this happened.)
+ *
+ * @param rowItem
+ * @param column
+ * @return ViewerCell
+ */
+ /* package */ViewerCell updateCell(ViewerRow rowItem, int column, Object element) {
+ cell.update(rowItem, column, element);
+ return cell;
+ }
+
+ /**
+ * Returns the {@link Item} at the given widget-relative coordinates, or
+ * null
if there is no item at the given coordinates.
+ *
+ * @param point
+ * the widget-relative coordinates
+ * @return the {@link Item} at the coordinates or null
if
+ * there is no item at the given coordinates
+ */
+ protected abstract Item getItemAt(Point point);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.StructuredViewer#getItem(int, int)
+ */
+ protected Item getItem(int x, int y) {
+ return getItemAt(getControl().toControl(x, y));
+ }
+
+ /**
+ * The column viewer implementation of this Viewer
framework
+ * method ensures that the given label provider is an instance of
+ * ITableLabelProvider
, ILabelProvider
, or
+ * CellLabelProvider
.
+ *
+ * If the label provider is an {@link ITableLabelProvider}, then it
+ * provides a separate label text and image for each column. Implementers of
+ * ITableLabelProvider
may also implement
+ * {@link ITableColorProvider} and/or {@link ITableFontProvider} to provide
+ * colors and/or fonts.
+ *
+ * If the label provider is an ILabelProvider
, then it
+ * provides only the label text and image for the first column, and any
+ * remaining columns are blank. Implementers of ILabelProvider
+ * may also implement {@link IColorProvider} and/or {@link IFontProvider} to
+ * provide colors and/or fonts.
+ *
null
if no
+ * cell editors are set.
+ * + * Since 3.3, an alternative API is available, see + * {@link ViewerColumn#setEditingSupport(EditingSupport)} for a more + * flexible way of editing values in a column viewer. + *
+ * + * @return CellEditor[] + * @since 3.1 (in subclasses, added in 3.3 to abstract class) + * @see ViewerColumn#setEditingSupport(EditingSupport) + * @see EditingSupport + */ + public CellEditor[] getCellEditors() { + return cellEditors; + } + + /** + * Returns the cell modifier of this viewer, ornull
if none
+ * has been set.
+ *
+ * + * Since 3.3, an alternative API is available, see + * {@link ViewerColumn#setEditingSupport(EditingSupport)} for a more + * flexible way of editing values in a column viewer. + *
+ * + * @return the cell modifier, ornull
+ * @since 3.1 (in subclasses, added in 3.3 to abstract class)
+ * @see ViewerColumn#setEditingSupport(EditingSupport)
+ * @see EditingSupport
+ */
+ public ICellModifier getCellModifier() {
+ return cellModifier;
+ }
+
+ /**
+ * Returns the column properties of this table viewer. The properties must
+ * correspond with the columns of the table control. They are used to
+ * identify the column in a cell modifier.
+ *
+ * + * Since 3.3, an alternative API is available, see + * {@link ViewerColumn#setEditingSupport(EditingSupport)} for a more + * flexible way of editing values in a column viewer. + *
+ * + * @return the list of column properties + * @since 3.1 (in subclasses, added in 3.3 to abstract class) + * @see ViewerColumn#setEditingSupport(EditingSupport) + * @see EditingSupport + */ + public Object[] getColumnProperties() { + Object[] res; + foreach( prop; columnProperties ){ + res ~= new ArrayWrapperString( prop ); + } + return res; + } + + /** + * Returns whether there is an active cell editor. + * + *+ * Since 3.3, an alternative API is available, see + * {@link ViewerColumn#setEditingSupport(EditingSupport)} for a more + * flexible way of editing values in a column viewer. + *
+ * + * @returntrue
if there is an active cell editor, and
+ * false
otherwise
+ * @since 3.1 (in subclasses, added in 3.3 to abstract class)
+ * @see ViewerColumn#setEditingSupport(EditingSupport)
+ * @see EditingSupport
+ */
+ public bool isCellEditorActive() {
+ if (viewerEditor !is null) {
+ return viewerEditor.isCellEditorActive();
+ }
+ return false;
+ }
+
+ public void refresh(Object element) {
+ if (isBusy())
+ return;
+
+ if( isCellEditorActive() ) {
+ cancelEditing();
+ }
+
+ super.refresh(element);
+ }
+
+ public void refresh(Object element, bool updateLabels) {
+ if (isBusy())
+ return;
+
+ if( isCellEditorActive() ) {
+ cancelEditing();
+ }
+
+ super.refresh(element, updateLabels);
+ }
+
+ public void update(Object element, String[] properties) {
+ if (isBusy())
+ return;
+ super.update(element, properties);
+ }
+
+ /**
+ * Sets the cell editors of this column viewer. If editing is not supported
+ * by this viewer the call simply has no effect.
+ *
+ * + * Since 3.3, an alternative API is available, see + * {@link ViewerColumn#setEditingSupport(EditingSupport)} for a more + * flexible way of editing values in a column viewer. + *
+ * + * @param editors + * the list of cell editors + * @since 3.1 (in subclasses, added in 3.3 to abstract class) + * @see ViewerColumn#setEditingSupport(EditingSupport) + * @see EditingSupport + */ + public void setCellEditors(CellEditor[] editors) { + this.cellEditors = editors; + } + + /** + * Sets the cell modifier for this column viewer. This method does nothing + * if editing is not supported by this viewer. + * + *+ * Since 3.3, an alternative API is available, see + * {@link ViewerColumn#setEditingSupport(EditingSupport)} for a more + * flexible way of editing values in a column viewer. + *
+ * + * @param modifier + * the cell modifier + * @since 3.1 (in subclasses, added in 3.3 to abstract class) + * @see ViewerColumn#setEditingSupport(EditingSupport) + * @see EditingSupport + */ + public void setCellModifier(ICellModifier modifier) { + this.cellModifier = modifier; + } + + /** + * Sets the column properties of this column viewer. The properties must + * correspond with the columns of the control. They are used to identify the + * column in a cell modifier. If editing is not supported by this viewer the + * call simply has no effect. + * + *+ * Since 3.3, an alternative API is available, see + * {@link ViewerColumn#setEditingSupport(EditingSupport)} for a more + * flexible way of editing values in a column viewer. + *
+ * + * @param columnProperties + * the list of column properties + * @since 3.1 (in subclasses, added in 3.3 to abstract class) + * @see ViewerColumn#setEditingSupport(EditingSupport) + * @see EditingSupport + */ + public void setColumnProperties(String[] columnProperties) { + this.columnProperties = columnProperties; + } + + /** + * Returns the number of columns contained in the receiver. If no columns + * were created by the programmer, this value is zero, despite the fact that + * visually, one column of items may be visible. This occurs when the + * programmer uses the column viewer like a list, adding elements but never + * creating a column. + * + * @return the number of columns + * + * @since 3.3 + */ + protected abstract int doGetColumnCount(); + package int doGetColumnCount_package(){ + return doGetColumnCount(); + } + + /** + * Returns the label provider associated with the column at the given index + * ornull
if no column with this index is known.
+ *
+ * @param columnIndex
+ * the column index
+ * @return the label provider associated with the column or
+ * null
if no column with this index is known
+ *
+ * @since 3.3
+ */
+ public CellLabelProvider getLabelProvider(int columnIndex) {
+ ViewerColumn column = getViewerColumn(columnIndex);
+ if (column !is null) {
+ return column.getLabelProvider();
+ }
+ return null;
+ }
+
+ private void handleMouseDown(MouseEvent e) {
+ ViewerCell cell = getCell(new Point(e.x, e.y));
+
+ if (cell !is null) {
+ triggerEditorActivationEvent(new ColumnViewerEditorActivationEvent(
+ cell, e));
+ }
+ }
+
+ /**
+ * Invoking this method fires an editor activation event which tries to
+ * enable the editor but before this event is passed to
+ * {@link ColumnViewerEditorActivationStrategy} to see if this event should
+ * really trigger editor activation
+ *
+ * @param event
+ * the activation event
+ */
+ protected void triggerEditorActivationEvent(
+ ColumnViewerEditorActivationEvent event) {
+ viewerEditor.handleEditorActivationEvent(event);
+ }
+ package void triggerEditorActivationEvent_package(
+ ColumnViewerEditorActivationEvent event) {
+ triggerEditorActivationEvent(event);
+ }
+
+ /**
+ * @param columnViewerEditor
+ * the new column viewer editor
+ */
+ public void setColumnViewerEditor(ColumnViewerEditor columnViewerEditor) {
+ Assert.isNotNull(viewerEditor);
+ this.viewerEditor = columnViewerEditor;
+ }
+
+ /**
+ * @return the currently attached viewer editor
+ */
+ public ColumnViewerEditor getColumnViewerEditor() {
+ return viewerEditor;
+ }
+
+ protected Object[] getRawChildren(Object parent) {
+ bool oldBusy = busy;
+ busy = true;
+ try {
+ return super.getRawChildren(parent);
+ } finally {
+ busy = oldBusy;
+ }
+ }
+
+ /**
+ * Clear all cell-editors setup for backwards compatibility in
+ * {@link #setupEditingSupport(int, ViewerColumn)}. This has to be done
+ * whenever a column is disposed because the index cached when the anonymous
+ * class is created has to be readjusted
+ */
+ void clearLegacyEditingSetup() {
+ int count = doGetColumnCount();
+
+ for( int i = 0; i < count || i is 0; i++ ) {
+ Widget owner = getColumnViewerOwner(i);
+
+ if( owner !is null && ! owner.isDisposed() ) {
+ ViewerColumn column = cast(ViewerColumn) owner.getData(ViewerColumn.COLUMN_VIEWER_KEY);
+ if( column !is null ) {
+ EditingSupport e = column.getEditingSupport();
+ // Ensure that only EditingSupports are wiped that are setup
+ // for Legacy reasons
+ if (e !is null && e.isLegacySupport()) {
+ column.setEditingSupport(null);
+ }
+ }
+ }
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColumnViewerEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ColumnViewerEditor.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,658 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl true
if there is an active cell editor; otherwise
+ * false
is returned.
+ */
+ bool isCellEditorActive() {
+ return cellEditor !is null;
+ }
+
+ void handleDoubleClickEvent() {
+ viewer.fireDoubleClick_package(new DoubleClickEvent(viewer, viewer
+ .getSelection()));
+ viewer.fireOpen_package(new OpenEvent(viewer, viewer.getSelection()));
+ }
+
+ /**
+ * Adds the given listener, it is to be notified when the cell editor is
+ * activated or deactivated.
+ *
+ * @param listener
+ * the listener to add
+ */
+ public void addEditorActivationListener(
+ ColumnViewerEditorActivationListener listener) {
+ if (editorActivationListener is null) {
+ editorActivationListener = new ListenerList();
+ }
+ editorActivationListener.add(listener);
+ }
+
+ /**
+ * Removes the given listener.
+ *
+ * @param listener
+ * the listener to remove
+ */
+ public void removeEditorActivationListener(
+ ColumnViewerEditorActivationListener listener) {
+ if (editorActivationListener !is null) {
+ editorActivationListener.remove(listener);
+ }
+ }
+
+ /**
+ * Process the traverse event and opens the next available editor depending
+ * of the implemented strategy. The default implementation uses the style
+ * constants
+ * + * Subclasses may overwrite to implement their custom logic to edit the next + * cell + *
+ * + * @param columnIndex + * the index of the current column + * @param row + * the current row - may only be used for the duration of this + * method call + * @param event + * the traverse event + */ + protected void processTraverseEvent(int columnIndex, ViewerRow row, + TraverseEvent event) { + + ViewerCell cell2edit = null; + + if (event.detail is DWT.TRAVERSE_TAB_PREVIOUS) { + event.doit = false; + + if ((event.stateMask & DWT.CTRL) is DWT.CTRL + && (feature & TABBING_VERTICAL) is TABBING_VERTICAL) { + cell2edit = searchCellAboveBelow(row, viewer, columnIndex, true); + } else if ((feature & TABBING_HORIZONTAL) is TABBING_HORIZONTAL) { + cell2edit = searchPreviousCell(row, viewer, columnIndex, + columnIndex); + } + } else if (event.detail is DWT.TRAVERSE_TAB_NEXT) { + event.doit = false; + + if ((event.stateMask & DWT.CTRL) is DWT.CTRL + && (feature & TABBING_VERTICAL) is TABBING_VERTICAL) { + cell2edit = searchCellAboveBelow(row, viewer, columnIndex, + false); + } else if ((feature & TABBING_HORIZONTAL) is TABBING_HORIZONTAL) { + cell2edit = searchNextCell(row, viewer, columnIndex, + columnIndex); + } + } + + if (cell2edit !is null) { + + viewer.getControl().setRedraw(false); + ColumnViewerEditorActivationEvent acEvent = new ColumnViewerEditorActivationEvent( + cell2edit, event); + viewer.triggerEditorActivationEvent_package(acEvent); + viewer.getControl().setRedraw(true); + } + } + + private ViewerCell searchCellAboveBelow(ViewerRow row, ColumnViewer viewer, + int columnIndex, bool above) { + ViewerCell rv = null; + + ViewerRow newRow = null; + + if (above) { + newRow = row.getNeighbor(ViewerRow.ABOVE, false); + } else { + newRow = row.getNeighbor(ViewerRow.BELOW, false); + } + + if (newRow !is null) { + ViewerColumn column = viewer.getViewerColumn(columnIndex); + if (column !is null + && column.getEditingSupport() !is null + && column.getEditingSupport().canEdit_package( + newRow.getItem().getData())) { + rv = newRow.getCell(columnIndex); + } else { + rv = searchCellAboveBelow(newRow, viewer, columnIndex, above); + } + } + + return rv; + } + + private ViewerCell searchPreviousCell(ViewerRow row, ColumnViewer viewer, + int columnIndex, int startIndex) { + ViewerCell rv = null; + + if (columnIndex - 1 >= 0) { + ViewerColumn column = viewer.getViewerColumn(columnIndex - 1); + if (column !is null + && column.getEditingSupport() !is null + && column.getEditingSupport().canEdit_package( + row.getItem().getData())) { + rv = row.getCell(columnIndex - 1); + } else { + rv = searchPreviousCell(row, viewer, columnIndex - 1, + startIndex); + } + } else { + if ((feature & TABBING_CYCLE_IN_ROW) is TABBING_CYCLE_IN_ROW) { + // Check that we don't get into endless loop + if (columnIndex - 1 !is startIndex) { + // Don't subtract -1 from getColumnCount() we need to + // start in the virtual column + // next to it + rv = searchPreviousCell(row, viewer, row.getColumnCount(), + startIndex); + } + } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) is TABBING_MOVE_TO_ROW_NEIGHBOR) { + ViewerRow rowAbove = row.getNeighbor(ViewerRow.ABOVE, false); + if (rowAbove !is null) { + rv = searchPreviousCell(rowAbove, viewer, rowAbove + .getColumnCount(), startIndex); + } + } + } + + return rv; + } + + private ViewerCell searchNextCell(ViewerRow row, ColumnViewer viewer, + int columnIndex, int startIndex) { + ViewerCell rv = null; + + if (columnIndex + 1 < row.getColumnCount()) { + ViewerColumn column = viewer.getViewerColumn(columnIndex + 1); + if (column !is null + && column.getEditingSupport() !is null + && column.getEditingSupport().canEdit_package( + row.getItem().getData())) { + rv = row.getCell(columnIndex + 1); + } else { + rv = searchNextCell(row, viewer, columnIndex + 1, startIndex); + } + } else { + if ((feature & TABBING_CYCLE_IN_ROW) is TABBING_CYCLE_IN_ROW) { + // Check that we don't get into endless loop + if (columnIndex + 1 !is startIndex) { + // Start from -1 from the virtual column before the + // first one + rv = searchNextCell(row, viewer, -1, startIndex); + } + } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) is TABBING_MOVE_TO_ROW_NEIGHBOR) { + ViewerRow rowBelow = row.getNeighbor(ViewerRow.BELOW, false); + if (rowBelow !is null) { + rv = searchNextCell(rowBelow, viewer, -1, startIndex); + } + } + } + + return rv; + } + + /** + * Position the editor inside the control + * + * @param w + * the editor control + * @param item + * the item (row) in which the editor is drawn in + * @param fColumnNumber + * the column number in which the editor is shown + */ + protected abstract void setEditor(Control w, Item item, int fColumnNumber); + + /** + * set the layout data for the editor + * + * @param layoutData + * the layout data used when editor is displayed + */ + protected abstract void setLayoutData(CellEditor.LayoutData layoutData); + + /** + * @param focusCell + * updates the cell with the current input focus + * @param event + * the event requesting to update the focusCell + */ + protected abstract void updateFocusCell(ViewerCell focusCell, + ColumnViewerEditorActivationEvent event); + + /** + * @return the cell currently holding the focus if no cell has the focus or + * the viewer implementation doesn't supportnull
is
+ * returned
+ *
+ */
+ public ViewerCell getFocusCell() {
+ return null;
+ }
+
+ /**
+ * @return the viewer working for
+ */
+ protected ColumnViewer getViewer() {
+ return viewer;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColumnViewerEditorActivationEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ColumnViewerEditorActivationEvent.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if this event should open the editor
+ */
+ protected bool isEditorActivationEvent(
+ ColumnViewerEditorActivationEvent event) {
+ bool singleSelect = (cast(IStructuredSelection)viewer.getSelection()).size() is 1;
+ bool isLeftMouseSelect = event.eventType is ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION && (cast(MouseEvent)event.sourceEvent).button is 1;
+
+ return singleSelect && (isLeftMouseSelect
+ || event.eventType is ColumnViewerEditorActivationEvent.PROGRAMMATIC
+ || event.eventType is ColumnViewerEditorActivationEvent.TRAVERSAL);
+ }
+ package bool isEditorActivationEvent_package(ColumnViewerEditorActivationEvent event){
+ return isEditorActivationEvent(event);
+ }
+
+ /**
+ * @return the cell holding the current focus
+ */
+ private ViewerCell getFocusCell() {
+ return viewer.getColumnViewerEditor().getFocusCell();
+ }
+
+ /**
+ * @return the viewer
+ */
+ public ColumnViewer getViewer() {
+ return viewer;
+ }
+
+ /**
+ * Enable activation of cell editors by keyboard
+ *
+ * @param enable
+ * true
to enable
+ */
+ public void setEnableEditorActivationWithKeyboard(bool enable) {
+ if (enable) {
+ if (keyboardActivationListener is null) {
+ keyboardActivationListener = new class KeyListener {
+
+ public void keyPressed(KeyEvent e) {
+ ViewerCell cell = getFocusCell();
+
+ if (cell !is null) {
+ viewer
+ .triggerEditorActivationEvent_package(new ColumnViewerEditorActivationEvent(
+ cell, e));
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+
+ }
+
+ };
+ viewer.getControl().addKeyListener(keyboardActivationListener);
+ }
+ } else {
+ if (keyboardActivationListener !is null) {
+ viewer.getControl().removeKeyListener(
+ keyboardActivationListener);
+ keyboardActivationListener = null;
+ }
+ }
+ }
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColumnViewerEditorDeactivationEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ColumnViewerEditorDeactivationEvent.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if the activation is done manually using
+ * {@link #show(Point)}
+ */
+ protected this(ColumnViewer viewer, int style, bool manualActivation ) {
+ super(viewer.getControl(),style,manualActivation);
+ this.viewer = viewer;
+ }
+
+ /**
+ * Enable ToolTip support for the viewer by creating an instance from this
+ * class. To get all necessary informations this support class consults the
+ * {@link CellLabelProvider}.
+ *
+ * @param viewer
+ * the viewer the support is attached to
+ */
+ public static void enableFor(ColumnViewer viewer) {
+ new ColumnViewerToolTipSupport(viewer,ToolTip.NO_RECREATE,false);
+ }
+
+ /**
+ * Enable ToolTip support for the viewer by creating an instance from this
+ * class. To get all necessary informations this support class consults the
+ * {@link CellLabelProvider}.
+ *
+ * @param viewer
+ * the viewer the support is attached to
+ * @param style style passed to control tool tip behavior
+ *
+ * @see ToolTip#RECREATE
+ * @see ToolTip#NO_RECREATE
+ */
+ public static void enableFor(ColumnViewer viewer, int style) {
+ new ColumnViewerToolTipSupport(viewer,style,false);
+ }
+
+ protected Object getToolTipArea(Event event) {
+ return viewer.getCell(new Point(event.x,event.y));
+ }
+
+ protected final bool shouldCreateToolTip(Event event) {
+ if( ! super.shouldCreateToolTip(event) ) {
+ return false;
+ }
+
+ bool rv = false;
+
+ ViewerRow row = viewer.getViewerRow_package(new Point(event.x, event.y));
+
+ viewer.getControl().setToolTipText(""); //$NON-NLS-1$
+ Point point = new Point(event.x, event.y);
+
+ if (row !is null) {
+ Object element = row.getItem().getData();
+
+ ViewerColumn viewPart = viewer.getViewerColumn(row
+ .getColumnIndex(point));
+
+ if (viewPart is null) {
+ return false;
+ }
+
+ CellLabelProvider labelProvider = viewPart.getLabelProvider();
+ bool useNative = labelProvider.useNativeToolTip(element);
+
+ String text = labelProvider.getToolTipText(element);
+ Image img = null;
+
+ if( ! useNative ) {
+ img = labelProvider.getToolTipImage(element);
+ }
+
+ if( useNative || (text is null && img is null ) ) {
+ viewer.getControl().setToolTipText(text);
+ rv = false;
+ } else {
+ setPopupDelay(labelProvider.getToolTipDisplayDelayTime(element));
+ setHideDelay(labelProvider.getToolTipTimeDisplayed(element));
+
+ Point shift = labelProvider.getToolTipShift(element);
+
+ if (shift is null) {
+ setShift(new Point(DEFAULT_SHIFT_X, DEFAULT_SHIFT_Y));
+ } else {
+ setShift(new Point(shift.x, shift.y));
+ }
+
+ setData(LABEL_PROVIDER_KEY, labelProvider);
+ setData(ELEMENT_KEY, element);
+
+ setText(text);
+ setImage(img);
+ setStyle(labelProvider.getToolTipStyle(element));
+ setForegroundColor(labelProvider.getToolTipForegroundColor(element));
+ setBackgroundColor(labelProvider.getToolTipBackgroundColor(element));
+ setFont(labelProvider.getToolTipFont(element));
+
+ // Check if at least one of the values is set
+ rv = getText(event) !is null || getImage(event) !is null;
+ }
+ }
+
+ return rv;
+ }
+
+ protected void afterHideToolTip(Event event) {
+ if (event !is null && event.widget !is viewer.getControl()) {
+ if (event.type is DWT.MouseDown) {
+ viewer.setSelection(new StructuredSelection());
+ } else {
+ viewer.getControl().setFocus();
+ }
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ColumnWeightData.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ColumnWeightData.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * This class may be instantiated; it is not intended to be subclassed. + *
+ */ +public class ColumnWeightData : ColumnLayoutData { + + /** + * Default width of a column (in pixels). + */ + public static const int MINIMUM_WIDTH = 20; + + /** + * The column's minimum width in pixels. + */ + public int minimumWidth; + + /** + * The column's weight. + */ + public int weight; + + /** + * Creates a resizable column width with the given weight and a default + * minimum width. + * + * @param weight the weight of the column + */ + public this(int weight) { + this(weight, true); + } + + /** + * Creates a resizable column width with the given weight and minimum width. + * + * @param weight the weight of the column + * @param minimumWidth the minimum width of the column in pixels + */ + public this(int weight, int minimumWidth) { + this(weight, minimumWidth, true); + } + + /** + * Creates a column width with the given weight and minimum width. + * + * @param weight the weight of the column + * @param minimumWidth the minimum width of the column in pixels + * @param resizabletrue
if the column is resizable,
+ * and false
if size of the column is fixed
+ */
+ public this(int weight, int minimumWidth, bool resizable) {
+ super(resizable);
+ Assert.isTrue(weight >= 0);
+ Assert.isTrue(minimumWidth >= 0);
+ this.weight = weight;
+ this.minimumWidth = minimumWidth;
+ }
+
+ /**
+ * Creates a column width with the given weight and a default
+ * minimum width.
+ *
+ * @param weight the weight of the column
+ * @param resizable true
if the column is resizable,
+ * and false
if size of the column is fixed
+ */
+ public this(int weight, bool resizable) {
+ this(weight, MINIMUM_WIDTH, resizable);
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ComboBoxCellEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ComboBoxCellEditor.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl + * This class may be instantiated; it is not intended to be subclassed. + *
+ */ +public class ComboBoxCellEditor : CellEditor { + + /** + * The list of items to present in the combo box. + */ + private String[] items; + + /** + * The zero-based index of the selected item. + */ + int selection; + + /** + * The custom combo box control. + */ + CCombo comboBox; + + /** + * Default ComboBoxCellEditor style + */ + private static const int defaultStyle = DWT.NONE; + + /** + * Creates a new cell editor with no control and no st of choices. Initially, + * the cell editor has no cell validator. + * + * @since 2.1 + * @see CellEditor#setStyle + * @see CellEditor#create + * @see ComboBoxCellEditor#setItems + * @see CellEditor#dispose + */ + public this() { + setStyle(defaultStyle); + } + + /** + * Creates a new cell editor with a combo containing the given + * list of choices and parented under the given control. The cell + * editor value is the zero-based index of the selected item. + * Initially, the cell editor has no cell validator and + * the first item in the list is selected. + * + * @param parent the parent control + * @param items the list of strings for the combo box + */ + public this(Composite parent, String[] items) { + this(parent, items, defaultStyle); + } + + /** + * Creates a new cell editor with a combo containing the given + * list of choices and parented under the given control. The cell + * editor value is the zero-based index of the selected item. + * Initially, the cell editor has no cell validator and + * the first item in the list is selected. + * + * @param parent the parent control + * @param items the list of strings for the combo box + * @param style the style bits + * @since 2.1 + */ + public this(Composite parent, String[] items, int style) { + super(parent, style); + setItems(items); + } + + /** + * Returns the list of choices for the combo box + * + * @return the list of choices for the combo box + */ + public String[] getItems() { + return this.items; + } + + /** + * Sets the list of choices for the combo box + * + * @param items the list of choices for the combo box + */ + public void setItems(String[] items) { +// Assert.isNotNull(items); + this.items = items; + populateComboBoxItems(); + } + + /* (non-Javadoc) + * Method declared on CellEditor. + */ + protected Control createControl(Composite parent) { + + comboBox = new CCombo(parent, getStyle()); + comboBox.setFont(parent.getFont()); + + populateComboBoxItems(); + + comboBox.addKeyListener(new class KeyAdapter { + // hook key pressed - see PR 14201 + public void keyPressed(KeyEvent e) { + keyReleaseOccured(e); + } + }); + + comboBox.addSelectionListener(new class SelectionAdapter { + public void widgetDefaultSelected(SelectionEvent event) { + applyEditorValueAndDeactivate(); + } + + public void widgetSelected(SelectionEvent event) { + selection = comboBox.getSelectionIndex(); + } + }); + + comboBox.addTraverseListener(new class TraverseListener { + public void keyTraversed(TraverseEvent e) { + if (e.detail is DWT.TRAVERSE_ESCAPE + || e.detail is DWT.TRAVERSE_RETURN) { + e.doit = false; + } + } + }); + + comboBox.addFocusListener(new class FocusAdapter { + public void focusLost(FocusEvent e) { + this.outer.focusLost(); + } + }); + return comboBox; + } + + /** + * TheComboBoxCellEditor
implementation of
+ * this CellEditor
framework method returns
+ * the zero-based index of the current selection.
+ *
+ * @return the zero-based index of the current selection wrapped
+ * as an Integer
+ */
+ protected Object doGetValue() {
+ return new ValueWrapperInt(selection);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on CellEditor.
+ */
+ protected void doSetFocus() {
+ comboBox.setFocus();
+ }
+
+ /**
+ * The ComboBoxCellEditor
implementation of
+ * this CellEditor
framework method sets the
+ * minimum width of the cell. The minimum width is 10 characters
+ * if comboBox
is not null
or disposed
+ * else it is 60 pixels to make sure the arrow button and some text is visible.
+ * The list of CCombo will be wide enough to show its longest item.
+ */
+ public LayoutData getLayoutData() {
+ LayoutData layoutData = super.getLayoutData();
+ if ((comboBox is null) || comboBox.isDisposed()) {
+ layoutData.minimumWidth = 60;
+ } else {
+ // make the comboBox 10 characters wide
+ GC gc = new GC(comboBox);
+ layoutData.minimumWidth = (gc.getFontMetrics()
+ .getAverageCharWidth() * 10) + 10;
+ gc.dispose();
+ }
+ return layoutData;
+ }
+
+ /**
+ * The ComboBoxCellEditor
implementation of
+ * this CellEditor
framework method
+ * accepts a zero-based index of a selection.
+ *
+ * @param value the zero-based index of the selection wrapped
+ * as an Integer
+ */
+ protected void doSetValue(Object value) {
+ Assert.isTrue(comboBox !is null && (cast(ValueWrapperInt)value ));
+ selection = (cast(ValueWrapperInt) value).value;
+ comboBox.select(selection);
+ }
+
+ /**
+ * Updates the list of choices for the combo box for the current control.
+ */
+ private void populateComboBoxItems() {
+ if (comboBox !is null && items !is null) {
+ comboBox.removeAll();
+ for (int i = 0; i < items.length; i++) {
+ comboBox.add(items[i], i);
+ }
+
+ setValueValid(true);
+ selection = 0;
+ }
+ }
+
+ /**
+ * Applies the currently selected value and deactivates the cell editor
+ */
+ void applyEditorValueAndDeactivate() {
+ // must set the selection before getting value
+ selection = comboBox.getSelectionIndex();
+ Object newValue = doGetValue();
+ markDirty();
+ bool isValid = isCorrect(newValue);
+ setValueValid(isValid);
+
+ if (!isValid) {
+ // Only format if the 'index' is valid
+ if (items.length > 0 && selection >= 0 && selection < items.length) {
+ // try to insert the current value into the error message.
+ setErrorMessage(Format(getErrorMessage(),
+ [ items[selection] ]));
+ }
+ else {
+ // Since we don't have a valid index, assume we're using an 'edit'
+ // combo so format using its text value
+ setErrorMessage(Format(getErrorMessage(),
+ [ comboBox.getText() ]));
+ }
+ }
+
+ fireApplyEditorValue();
+ deactivate();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see dwtx.jface.viewers.CellEditor#focusLost()
+ */
+ protected void focusLost() {
+ if (isActivated()) {
+ applyEditorValueAndDeactivate();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see dwtx.jface.viewers.CellEditor#keyReleaseOccured(dwt.events.KeyEvent)
+ */
+ protected void keyReleaseOccured(KeyEvent keyEvent) {
+ if (keyEvent.character is '\u001b') { // Escape character
+ fireCancelEditor();
+ } else if (keyEvent.character is '\t') { // tab key
+ applyEditorValueAndDeactivate();
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ComboViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ComboViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2004-2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Sebastian Davids - bug 69254
+ * Port to the D programming language:
+ * Frank Benoit Combo
control or CCombo
+ * control. This class is intended as an alternative to the JFace ListViewer
, which displays
+ * its content in a combo box rather than a list. Wherever possible, this class attempts to behave
+ * like ListViewer. + * + * This class is designed to be instantiated with a pre-existing DWT combo control + * and configured with a domain-specific content provider, label provider, element + * filter (optional), and element sorter (optional). + *
+ * + * @see dwtx.jface.viewers.ListViewer + * @since 3.0 + */ +public final class ComboViewer : AbstractListViewer { + + /** + * This viewer's list control if this viewer is instantiated with a combo control; otherwise + *null
.
+ *
+ * @see #ComboViewer(Combo)
+ */
+ private Combo combo;
+
+ /**
+ * This viewer's list control if this viewer is instantiated with a CCombo control; otherwise
+ * null
.
+ *
+ * @see #ComboViewer(CCombo)
+ * @since 3.3
+ */
+ private CCombo ccombo;
+
+ /**
+ * Creates a combo viewer on a newly-created combo control under the given parent.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param parent the parent control
+ */
+ public this(Composite parent) {
+ this(parent, DWT.READ_ONLY | DWT.BORDER);
+ }
+
+ /**
+ * Creates a combo viewer on a newly-created combo control under the given parent.
+ * The combo control is created using the given DWT style bits.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param parent the parent control
+ * @param style the DWT style bits
+ */
+ public this(Composite parent, int style) {
+ this(new Combo(parent, style));
+ }
+
+ /**
+ * Creates a combo viewer on the given combo control.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param list the combo control
+ */
+ public this(Combo list) {
+ this.combo = list;
+ hookControl(list);
+ }
+
+ /**
+ * Creates a combo viewer on the given CCombo control.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param list the CCombo control
+ * @since 3.3
+ */
+ public this(CCombo list) {
+ this.ccombo = list;
+ hookControl(list);
+ }
+
+ protected void listAdd(String string, int index) {
+ if (combo is null) {
+ ccombo.add(string, index);
+ } else {
+ combo.add(string, index);
+ }
+ }
+
+ protected void listSetItem(int index, String string) {
+ if (combo is null) {
+ ccombo.setItem(index, string);
+ } else {
+ combo.setItem(index, string);
+ }
+ }
+
+ protected int[] listGetSelectionIndices() {
+ if (combo is null) {
+ return [ ccombo.getSelectionIndex() ];
+ } else {
+ return [ combo.getSelectionIndex() ];
+ }
+ }
+
+ protected int listGetItemCount() {
+ if (combo is null) {
+ return ccombo.getItemCount();
+ } else {
+ return combo.getItemCount();
+ }
+ }
+
+ protected void listSetItems(String[] labels) {
+ if (combo is null) {
+ ccombo.setItems(labels);
+ } else {
+ combo.setItems(labels);
+ }
+ }
+
+ protected void listRemoveAll() {
+ if (combo is null) {
+ ccombo.removeAll();
+ } else {
+ combo.removeAll();
+ }
+ }
+
+ protected void listRemove(int index) {
+ if (combo is null) {
+ ccombo.remove(index);
+ } else {
+ combo.remove(index);
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Viewer.
+ */
+ public Control getControl() {
+ if (combo is null) {
+ return ccombo;
+ } else {
+ return combo;
+ }
+ }
+
+ /**
+ * Returns this list viewer's list control. If the viewer was not created on
+ * a CCombo control, some kind of unchecked exception is thrown.
+ *
+ * @return the list control
+ * @since 3.3
+ */
+ public CCombo getCCombo() {
+ Assert.isNotNull(ccombo);
+ return ccombo;
+ }
+
+ /**
+ * Returns this list viewer's list control. If the viewer was not created on
+ * a Combo control, some kind of unchecked exception is thrown.
+ *
+ * @return the list control
+ */
+ public Combo getCombo() {
+ Assert.isNotNull(combo);
+ return combo;
+ }
+
+ /*
+ * Do nothing -- combos only display the selected element, so there is no way
+ * we can ensure that the given element is visible without changing the selection.
+ * Method defined on StructuredViewer.
+ */
+ public void reveal(Object element) {
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listSetSelection(int[])
+ */
+ protected void listSetSelection(int[] ixs) {
+ if (combo is null) {
+ for (int idx = 0; idx < ixs.length; idx++) {
+ ccombo.select(ixs[idx]);
+ }
+ } else {
+ for (int idx = 0; idx < ixs.length; idx++) {
+ combo.select(ixs[idx]);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listDeselectAll()
+ */
+ protected void listDeselectAll() {
+ if (combo is null) {
+ ccombo.deselectAll();
+ ccombo.clearSelection();
+ } else {
+ combo.deselectAll();
+ combo.clearSelection();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listShowSelection()
+ */
+ protected void listShowSelection() {
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ContentViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ContentViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit
+ * A viewer's model consists of elements, represented by objects.
+ * A viewer defines and implements generic infrastructure for handling model
+ * input, updates, and selections in terms of elements.
+ * Input is obtained by querying an IContentProvider
which returns
+ * elements. The elements themselves are not displayed directly. They are
+ * mapped to labels, containing text and/or an image, using the viewer's
+ * ILabelProvider
.
+ *
+ * Implementing a concrete content viewer typically involves the following steps: + *
setSelection
, getSelection
)
+ * null
if none.
+ */
+ private IContentProvider contentProvider = null;
+
+ /**
+ * This viewer's input, or null
if none.
+ * The viewer's input provides the "model" for the viewer's content.
+ */
+ private Object input = null;
+
+ /**
+ * This viewer's label provider. Initially null
, but
+ * lazily initialized (to a SimpleLabelProvider
).
+ */
+ private IBaseLabelProvider labelProvider = null;
+
+ /**
+ * This viewer's label provider listener.
+ * Note: Having a viewer register a label provider listener with
+ * a label provider avoids having to define public methods
+ * for internal events.
+ */
+ private const ILabelProviderListener labelProviderListener;
+
+ /**
+ * Creates a content viewer with no input, no content provider, and a
+ * default label provider.
+ */
+ protected this() {
+ labelProviderListener = new class ILabelProviderListener {
+ public void labelProviderChanged(LabelProviderChangedEvent event) {
+ this.outer.handleLabelProviderChanged(event);
+ }
+ };
+ }
+
+ /**
+ * Returns the content provider used by this viewer,
+ * or null
if this view does not yet have a content
+ * provider.
+ *
+ * The ContentViewer
implementation of this method returns the content
+ * provider recorded is an internal state variable.
+ * Overriding this method is generally not required;
+ * however, if overriding in a subclass,
+ * super.getContentProvider
must be invoked.
+ *
null
if none
+ */
+ public IContentProvider getContentProvider() {
+ return contentProvider;
+ }
+
+ /**
+ * The ContentViewer
implementation of this IInputProvider
+ * method returns the current input of this viewer, or null
+ * if none. The viewer's input provides the "model" for the viewer's
+ * content.
+ */
+ public Object getInput() {
+ return input;
+ }
+
+ /**
+ * Returns the label provider used by this viewer.
+ *
+ * The ContentViewer
implementation of this method returns the label
+ * provider recorded in an internal state variable; if none has been
+ * set (with setLabelProvider
) a SimpleLabelProvider
+ * will be created, remembered, and returned.
+ * Overriding this method is generally not required;
+ * however, if overriding in a subclass,
+ * super.getLabelProvider
must be invoked.
+ *
+ * The ContentViewer
implementation of this method disposes of this
+ * viewer's label provider and content provider (if it has one).
+ * Subclasses should override this method to perform any additional
+ * cleanup of resources; however, overriding methods must invoke
+ * super.handleDispose
.
+ *
+ * The ContentViewer
implementation of this method calls labelProviderChanged()
+ * to cause a complete refresh of the viewer.
+ * Subclasses may reimplement or extend.
+ *
+ * All subclasses must call this method when their control is + * first established. + *
+ *
+ * The ContentViewer
implementation of this method hooks
+ * dispose events for the given control.
+ * Subclasses may override if they need to add other control hooks;
+ * however, super.hookControl
must be invoked.
+ *
+ * The ContentViewer
implementation of this method calls refresh()
.
+ * Subclasses may reimplement or extend.
+ *
+ * The ContentViewer
implementation of this method records the
+ * content provider in an internal state variable.
+ * Overriding this method is generally not required;
+ * however, if overriding in a subclass,
+ * super.setContentProvider
must be invoked.
+ *
ContentViewer
implementation of this Viewer
+ * method invokes inputChanged
on the content provider and then the
+ * inputChanged
hook method. This method fails if this viewer does
+ * not have a content provider. Subclassers are advised to override
+ * inputChanged
rather than this method, but may extend this method
+ * if required.
+ */
+ public void setInput(Object input) {
+ Assert
+ .isTrue(getContentProvider() !is null,
+ "ContentViewer must have a content provider when input is set."); //$NON-NLS-1$
+
+ Object oldInput = getInput();
+ contentProvider.inputChanged(this, oldInput, input);
+ this.input = input;
+
+ // call input hook
+ inputChanged(this.input, oldInput);
+ }
+
+ /**
+ * Sets the label provider for this viewer.
+ *
+ * The ContentViewer
implementation of this method ensures that the
+ * given label provider is connected to this viewer and the
+ * former label provider is disconnected from this viewer.
+ * Overriding this method is generally not required;
+ * however, if overriding in a subclass,
+ * super.setLabelProvider
must be invoked.
+ *
null
if none
+ */
+ public void setLabelProvider(IBaseLabelProvider labelProvider) {
+ IBaseLabelProvider oldProvider = this.labelProvider;
+ // If it hasn't changed, do nothing.
+ // This also ensures that the provider is not disposed
+ // if set a second time.
+ if (labelProvider is oldProvider) {
+ return;
+ }
+ if (oldProvider !is null) {
+ oldProvider.removeListener(this.labelProviderListener);
+ }
+ this.labelProvider = labelProvider;
+ if (labelProvider !is null) {
+ labelProvider.addListener(this.labelProviderListener);
+ }
+ refresh();
+
+ // Dispose old provider after refresh, so that items never refer to stale images.
+ if (oldProvider !is null) {
+ oldProvider.dispose();
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/CustomHashtable.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/CustomHashtable.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,443 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * Peter Shipton - original hashtable implementation
+ * Nick Edgar - added element comparer support
+ * Port to the D programming language:
+ * Frank Benoit
+ * CustomHashtable allows a custom comparator and hash code provider.
+ */
+/* package */final class CustomHashtable {
+
+ /**
+ * HashMapEntry is an internal class which is used to hold the entries of a Hashtable.
+ */
+ private static class HashMapEntry {
+ Object key, value;
+
+ HashMapEntry next;
+
+ this(Object theKey, Object theValue) {
+ key = theKey;
+ value = theValue;
+ }
+ }
+
+ private static final class EmptyEnumerator : Enumeration {
+ public bool hasMoreElements() {
+ return false;
+ }
+
+ public Object nextElement() {
+ throw new NoSuchElementException(null);
+ }
+ }
+
+ private class HashEnumerator : Enumeration {
+ bool key;
+
+ int start;
+
+ HashMapEntry entry;
+
+ this(bool isKey) {
+ key = isKey;
+ start = firstSlot;
+ }
+
+ public bool hasMoreElements() {
+ if (entry !is null) {
+ return true;
+ }
+ while (start <= lastSlot) {
+ if (elementData[start++] !is null) {
+ entry = elementData[start - 1];
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Object nextElement() {
+ if (hasMoreElements()) {
+ Object result = key ? entry.key : entry.value;
+ entry = entry.next;
+ return result;
+ } else {
+ throw new NoSuchElementException(null);
+ }
+ }
+ }
+
+ /+transient+/ int elementCount;
+
+ /+transient+/ HashMapEntry[] elementData;
+
+ private float loadFactor;
+
+ private int threshold;
+
+ /+transient+/ int firstSlot = 0;
+
+ /+transient+/ int lastSlot = -1;
+
+ /+transient+/ private IElementComparer comparer;
+
+ private static const EmptyEnumerator emptyEnumerator;
+ static this(){
+ emptyEnumerator = new EmptyEnumerator();
+ }
+
+ /**
+ * The default capacity used when not specified in the constructor.
+ */
+ public static const int DEFAULT_CAPACITY = 13;
+
+ /**
+ * Constructs a new Hashtable using the default capacity
+ * and load factor.
+ */
+ public this() {
+ this(13);
+ }
+
+ /**
+ * Constructs a new Hashtable using the specified capacity
+ * and the default load factor.
+ *
+ * @param capacity the initial capacity
+ */
+ public this(int capacity) {
+ this(capacity, null);
+ }
+
+ /**
+ * Constructs a new hash table with the default capacity and the given
+ * element comparer.
+ *
+ * @param comparer the element comparer to use to compare keys and obtain
+ * hash codes for keys, or
+ * This class is not intended to be subclassed.
+ *
+ * Subclasses may override the following methods:
+ * null
to use the normal
+ * equals
and hashCode
methods
+ */
+ public this(IElementComparer comparer) {
+ this(DEFAULT_CAPACITY, comparer);
+ }
+
+ /**
+ * Constructs a new hash table with the given capacity and the given
+ * element comparer.
+ *
+ * @param capacity the maximum number of elements that can be added without
+ * rehashing
+ * @param comparer the element comparer to use to compare keys and obtain
+ * hash codes for keys, or null
to use the normal
+ * equals
and hashCode
methods
+ */
+ public this(int capacity, IElementComparer comparer) {
+ if (capacity >= 0) {
+ elementCount = 0;
+ elementData = new HashMapEntry[capacity is 0 ? 1 : capacity];
+ firstSlot = elementData.length;
+ loadFactor = 0.75f;
+ computeMaxSize();
+ } else {
+ throw new IllegalArgumentException(null);
+ }
+ this.comparer = comparer;
+ }
+
+ /**
+ * Constructs a new hash table with enough capacity to hold all keys in the
+ * given hash table, then adds all key/value pairs in the given hash table
+ * to the new one, using the given element comparer.
+ * @param table the original hash table to copy from
+ *
+ * @param comparer the element comparer to use to compare keys and obtain
+ * hash codes for keys, or null
to use the normal
+ * equals
and hashCode
methods
+ */
+ public this(CustomHashtable table, IElementComparer comparer) {
+ this(table.size() * 2, comparer);
+ for (int i = table.elementData.length; --i >= 0;) {
+ HashMapEntry entry = table.elementData[i];
+ while (entry !is null) {
+ put(entry.key, entry.value);
+ entry = entry.next;
+ }
+ }
+ }
+
+ /**
+ * Returns the element comparer used to compare keys and to obtain
+ * hash codes for keys, or null
if no comparer has been
+ * provided.
+ *
+ * @return the element comparer or null
+ *
+ * @since 3.2
+ */
+ public IElementComparer getComparer() {
+ return comparer;
+ }
+
+ private void computeMaxSize() {
+ threshold = cast(int) (elementData.length * loadFactor);
+ }
+
+ /**
+ * Answers if this Hashtable contains the specified object as a key
+ * of one of the key/value pairs.
+ *
+ * @param key the object to look for as a key in this Hashtable
+ * @return true if object is a key in this Hashtable, false otherwise
+ */
+ public bool containsKey(Object key) {
+ return getEntry(key) !is null;
+ }
+
+ /**
+ * Answers an Enumeration on the values of this Hashtable. The
+ * results of the Enumeration may be affected if the contents
+ * of this Hashtable are modified.
+ *
+ * @return an Enumeration of the values of this Hashtable
+ */
+ public Enumeration elements() {
+ if (elementCount is 0) {
+ return emptyEnumerator;
+ }
+ return new HashEnumerator(false);
+ }
+
+ /**
+ * Answers the value associated with the specified key in
+ * this Hashtable.
+ *
+ * @param key the key of the value returned
+ * @return the value associated with the specified key, null if the specified key
+ * does not exist
+ */
+ public Object get(Object key) {
+ int index = (toHash(key) & 0x7FFFFFFF) % elementData.length;
+ HashMapEntry entry = elementData[index];
+ while (entry !is null) {
+ if (keyEquals(key, entry.key)) {
+ return entry.value;
+ }
+ entry = entry.next;
+ }
+ return null;
+ }
+
+ private HashMapEntry getEntry(Object key) {
+ int index = (toHash(key) & 0x7FFFFFFF) % elementData.length;
+ HashMapEntry entry = elementData[index];
+ while (entry !is null) {
+ if (keyEquals(key, entry.key)) {
+ return entry;
+ }
+ entry = entry.next;
+ }
+ return null;
+ }
+
+ /**
+ * Answers the hash code for the given key.
+ */
+ private hash_t toHash(Object key) {
+ if (comparer is null) {
+ return key.toHash();
+ } else {
+ return comparer.toHash(key);
+ }
+ }
+
+ /**
+ * Compares two keys for equality.
+ */
+ private bool keyEquals(Object a, Object b) {
+ if (comparer is null) {
+ return a.opEquals(b) !is 0;
+ } else {
+ return comparer.opEquals(a, b) !is 0;
+ }
+ }
+
+ /**
+ * Answers an Enumeration on the keys of this Hashtable. The
+ * results of the Enumeration may be affected if the contents
+ * of this Hashtable are modified.
+ *
+ * @return an Enumeration of the keys of this Hashtable
+ */
+ public Enumeration keys() {
+ if (elementCount is 0) {
+ return emptyEnumerator;
+ }
+ return new HashEnumerator(true);
+ }
+
+ /**
+ * Associate the specified value with the specified key in this Hashtable.
+ * If the key already exists, the old value is replaced. The key and value
+ * cannot be null.
+ *
+ * @param key the key to add
+ * @param value the value to add
+ * @return the old value associated with the specified key, null if the key did
+ * not exist
+ */
+ public Object put(Object key, Object value) {
+ if (key !is null && value !is null) {
+ int index = (toHash(key) & 0x7FFFFFFF) % elementData.length;
+ HashMapEntry entry = elementData[index];
+ while (entry !is null && !keyEquals(key, entry.key)) {
+ entry = entry.next;
+ }
+ if (entry is null) {
+ if (++elementCount > threshold) {
+ rehash();
+ index = (toHash(key) & 0x7FFFFFFF) % elementData.length;
+ }
+ if (index < firstSlot) {
+ firstSlot = index;
+ }
+ if (index > lastSlot) {
+ lastSlot = index;
+ }
+ entry = new HashMapEntry(key, value);
+ entry.next = elementData[index];
+ elementData[index] = entry;
+ return null;
+ }
+ Object result = entry.value;
+ entry.key = key; // important to avoid hanging onto keys that are equal but "old" -- see bug 30607
+ entry.value = value;
+ return result;
+ } else {
+ throw new NullPointerException();
+ }
+ }
+
+ /**
+ * Increases the capacity of this Hashtable. This method is sent when
+ * the size of this Hashtable exceeds the load factor.
+ */
+ private void rehash() {
+ int length = elementData.length << 1;
+ if (length is 0) {
+ length = 1;
+ }
+ firstSlot = length;
+ lastSlot = -1;
+ HashMapEntry[] newData = new HashMapEntry[length];
+ for (int i = elementData.length; --i >= 0;) {
+ HashMapEntry entry = elementData[i];
+ while (entry !is null) {
+ int index = (toHash(entry.key) & 0x7FFFFFFF) % length;
+ if (index < firstSlot) {
+ firstSlot = index;
+ }
+ if (index > lastSlot) {
+ lastSlot = index;
+ }
+ HashMapEntry next = entry.next;
+ entry.next = newData[index];
+ newData[index] = entry;
+ entry = next;
+ }
+ }
+ elementData = newData;
+ computeMaxSize();
+ }
+
+ /**
+ * Remove the key/value pair with the specified key from this Hashtable.
+ *
+ * @param key the key to remove
+ * @return the value associated with the specified key, null if the specified key
+ * did not exist
+ */
+ public Object remove(Object key) {
+ HashMapEntry last = null;
+ int index = (toHash(key) & 0x7FFFFFFF) % elementData.length;
+ HashMapEntry entry = elementData[index];
+ while (entry !is null && !keyEquals(key, entry.key)) {
+ last = entry;
+ entry = entry.next;
+ }
+ if (entry !is null) {
+ if (last is null) {
+ elementData[index] = entry.next;
+ } else {
+ last.next = entry.next;
+ }
+ elementCount--;
+ return entry.value;
+ }
+ return null;
+ }
+
+ /**
+ * Answers the number of key/value pairs in this Hashtable.
+ *
+ * @return the number of key/value pairs in this Hashtable
+ */
+ public int size() {
+ return elementCount;
+ }
+
+ /**
+ * Answers the string representation of this Hashtable.
+ *
+ * @return the string representation of this Hashtable
+ */
+ public override String toString() {
+ if (size() is 0) {
+ return "{}"; //$NON-NLS-1$
+ }
+
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('{');
+ for (int i = elementData.length; --i >= 0;) {
+ HashMapEntry entry = elementData[i];
+ while (entry !is null) {
+ if( buffer.length > 1 ){
+ buffer.append(", "); //$NON-NLS-1$
+ }
+ buffer.append(entry.key.toString);
+ buffer.append('=');
+ buffer.append(entry.value.toString);
+ entry = entry.next;
+ }
+ }
+ buffer.append('}');
+ return buffer.toString();
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/DecoratingLabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/DecoratingLabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,423 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
if no decorator is to be used initially
+ */
+ public this(ILabelProvider provider,
+ ILabelDecorator decorator) {
+ decorationContext = DecorationContext.DEFAULT_CONTEXT;
+ listeners = new ListenerList();
+ Assert.isNotNull(cast(Object)provider);
+ this.provider = provider;
+ this.decorator = decorator;
+ }
+
+ /**
+ * The DecoratingLabelProvider
implementation of this IBaseLabelProvider
method
+ * adds the listener to both the nested label provider and the label decorator.
+ *
+ * @param listener a label provider listener
+ */
+ public void addListener(ILabelProviderListener listener) {
+ super.addListener(listener);
+ provider.addListener(listener);
+ if (decorator !is null) {
+ decorator.addListener(listener);
+ }
+ listeners.add(cast(Object)listener);
+ }
+
+ /**
+ * The DecoratingLabelProvider
implementation of this IBaseLabelProvider
method
+ * disposes both the nested label provider and the label decorator.
+ */
+ public void dispose() {
+ provider.dispose();
+ if (decorator !is null) {
+ decorator.dispose();
+ }
+ }
+
+ /**
+ * The DecoratingLabelProvider
implementation of this
+ * ILabelProvider
method returns the image provided
+ * by the nested label provider's getImage
method,
+ * decorated with the decoration provided by the label decorator's
+ * decorateImage
method.
+ */
+ public Image getImage(Object element) {
+ Image image = provider.getImage(element);
+ if (decorator !is null) {
+ if ( auto ld2 = cast(LabelDecorator)decorator ) {
+ Image decorated = ld2.decorateImage(image, element, getDecorationContext());
+ if (decorated !is null) {
+ return decorated;
+ }
+ } else {
+ Image decorated = decorator.decorateImage(image, element);
+ if (decorated !is null) {
+ return decorated;
+ }
+ }
+ }
+ return image;
+ }
+
+ /**
+ * Returns the label decorator, or null
if none has been set.
+ *
+ * @return the label decorator, or null
if none has been set.
+ */
+ public ILabelDecorator getLabelDecorator() {
+ return decorator;
+ }
+
+ /**
+ * Returns the nested label provider.
+ *
+ * @return the nested label provider
+ */
+ public ILabelProvider getLabelProvider() {
+ return provider;
+ }
+
+ /**
+ * The DecoratingLabelProvider
implementation of this
+ * ILabelProvider
method returns the text label provided
+ * by the nested label provider's getText
method,
+ * decorated with the decoration provided by the label decorator's
+ * decorateText
method.
+ */
+ public String getText(Object element) {
+ String text = provider.getText(element);
+ if (decorator !is null) {
+ if ( auto ld2 = cast(LabelDecorator)decorator ) {
+ String decorated = ld2.decorateText(text, element, getDecorationContext());
+ if (decorated !is null) {
+ return decorated;
+ }
+ } else {
+ String decorated = decorator.decorateText(text, element);
+ if (decorated !is null) {
+ return decorated;
+ }
+ }
+ }
+ return text;
+ }
+
+ /**
+ * The DecoratingLabelProvider
implementation of this
+ * IBaseLabelProvider
method returns true
if the corresponding method
+ * on the nested label provider returns true
or if the corresponding method on the
+ * decorator returns true
.
+ */
+ public bool isLabelProperty(Object element, String property) {
+ if (provider.isLabelProperty(element, property)) {
+ return true;
+ }
+ if (decorator !is null && decorator.isLabelProperty(element, property)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * The DecoratingLabelProvider
implementation of this IBaseLabelProvider
method
+ * removes the listener from both the nested label provider and the label decorator.
+ *
+ * @param listener a label provider listener
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ super.removeListener(listener);
+ provider.removeListener(listener);
+ if (decorator !is null) {
+ decorator.removeListener(listener);
+ }
+ listeners.remove(cast(Object)listener);
+ }
+
+ /**
+ * Sets the label decorator.
+ * Removes all known listeners from the old decorator, and adds all known listeners to the new decorator.
+ * The old decorator is not disposed.
+ * Fires a label provider changed event indicating that all labels should be updated.
+ * Has no effect if the given decorator is identical to the current one.
+ *
+ * @param decorator the label decorator, or null
if no decorations are to be applied
+ */
+ public void setLabelDecorator(ILabelDecorator decorator) {
+ ILabelDecorator oldDecorator = this.decorator;
+ if (oldDecorator !is decorator) {
+ Object[] listenerList = this.listeners.getListeners();
+ if (oldDecorator !is null) {
+ for (int i = 0; i < listenerList.length; ++i) {
+ oldDecorator
+ .removeListener(cast(ILabelProviderListener) listenerList[i]);
+ }
+ }
+ this.decorator = decorator;
+ if (decorator !is null) {
+ for (int i = 0; i < listenerList.length; ++i) {
+ decorator
+ .addListener(cast(ILabelProviderListener) listenerList[i]);
+ }
+ }
+ fireLabelProviderChanged(new LabelProviderChangedEvent(this));
+ }
+ }
+
+
+ /*
+ * (non-Javadoc)
+ * @see dwtx.jface.viewers.IViewerLabelProvider#updateLabel(dwtx.jface.viewers.ViewerLabel, java.lang.Object)
+ */
+ public void updateLabel(ViewerLabel settings, Object element) {
+
+ ILabelDecorator currentDecorator = getLabelDecorator();
+ String oldText = settings.getText();
+ bool decorationReady = true;
+ if ( auto delayedDecorator = cast(IDelayedLabelDecorator)currentDecorator ) {
+ if (!delayedDecorator.prepareDecoration(element, oldText)) {
+ // The decoration is not ready but has been queued for processing
+ decorationReady = false;
+ }
+ }
+ // update icon and label
+
+ if (decorationReady || oldText is null
+ || settings.getText().length is 0) {
+ settings.setText(getText(element));
+ }
+
+ Image oldImage = settings.getImage();
+ if (decorationReady || oldImage is null) {
+ settings.setImage(getImage(element));
+ }
+
+ if(decorationReady) {
+ updateForDecorationReady(settings,element);
+ }
+
+ }
+
+ /**
+ * Decoration is ready. Update anything else for the settings.
+ * @param settings The object collecting the settings.
+ * @param element The Object being decorated.
+ * @since 3.1
+ */
+ protected void updateForDecorationReady(ViewerLabel settings, Object element) {
+
+ if( auto colorDecorator = cast(IColorDecorator) decorator ){
+ settings.setBackground(colorDecorator.decorateBackground(element));
+ settings.setForeground(colorDecorator.decorateForeground(element));
+ }
+
+ if( auto d = cast(IFontDecorator) decorator ) {
+ settings.setFont(d.decorateFont(element));
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.IColorProvider#getBackground(java.lang.Object)
+ */
+ public Color getBackground(Object element) {
+ if( auto p = cast(IColorProvider) provider ) {
+ return p.getBackground(element);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.IFontProvider#getFont(java.lang.Object)
+ */
+ public Font getFont(Object element) {
+ if(auto p = cast(IFontProvider)provider ) {
+ return p.getFont(element);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.IColorProvider#getForeground(java.lang.Object)
+ */
+ public Color getForeground(Object element) {
+ if(auto p = cast(IColorProvider)provider ) {
+ return p.getForeground(element);
+ }
+ return null;
+ }
+
+ /**
+ * Return the decoration context associated with this label provider.
+ * It will be passed to the decorator if the decorator is an
+ * instance of {@link LabelDecorator}.
+ * @return the decoration context associated with this label provider
+ *
+ * @since 3.2
+ */
+ public IDecorationContext getDecorationContext() {
+ return decorationContext;
+ }
+
+ /**
+ * Set the decoration context that will be based to the decorator
+ * for this label provider if that decorator implements {@link LabelDecorator}.
+ * @param decorationContext the decoration context.
+ *
+ * @since 3.2
+ */
+ public void setDecorationContext(IDecorationContext decorationContext) {
+ Assert.isNotNull(cast(Object)decorationContext);
+ this.decorationContext = decorationContext;
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.ITreePathLabelProvider#updateLabel(dwtx.jface.viewers.ViewerLabel, dwtx.jface.viewers.TreePath)
+ */
+ public void updateLabel(ViewerLabel settings, TreePath elementPath) {
+ ILabelDecorator currentDecorator = getLabelDecorator();
+ String oldText = settings.getText();
+ Object element = elementPath.getLastSegment();
+ bool decorationReady = true;
+ if ( auto labelDecorator = cast(LabelDecorator) currentDecorator ) {
+ if (!labelDecorator.prepareDecoration(element, oldText, getDecorationContext())) {
+ // The decoration is not ready but has been queued for processing
+ decorationReady = false;
+ }
+ } else if ( auto delayedDecorator = cast(IDelayedLabelDecorator) currentDecorator ) {
+ if (!delayedDecorator.prepareDecoration(element, oldText)) {
+ // The decoration is not ready but has been queued for processing
+ decorationReady = false;
+ }
+ }
+ settings.setHasPendingDecorations(!decorationReady);
+ // update icon and label
+
+ if ( auto pprov = cast(ITreePathLabelProvider) provider ) {
+ if (decorationReady || oldText is null
+ || settings.getText().length is 0) {
+ pprov.updateLabel(settings, elementPath);
+ decorateSettings(settings, elementPath);
+ }
+ } else {
+ if (decorationReady || oldText is null
+ || settings.getText().length is 0) {
+ settings.setText(getText(element));
+ }
+
+ Image oldImage = settings.getImage();
+ if (decorationReady || oldImage is null) {
+ settings.setImage(getImage(element));
+ }
+
+ if(decorationReady) {
+ updateForDecorationReady(settings,element);
+ }
+ }
+
+ }
+
+ /**
+ * Decorate the settings
+ * @param settings the settings obtained from the label provider
+ * @param elementPath the element path being decorated
+ */
+ private void decorateSettings(ViewerLabel settings, TreePath elementPath) {
+ Object element = elementPath.getLastSegment();
+ if (decorator !is null) {
+ if ( auto labelDecorator = cast(LabelDecorator) decorator ) {
+ String text = labelDecorator.decorateText(settings.getText(), element, getDecorationContext());
+ if (text !is null && text.length > 0)
+ settings.setText(text);
+ Image image = labelDecorator.decorateImage(settings.getImage(), element, getDecorationContext());
+ if (image !is null)
+ settings.setImage(image);
+
+ } else {
+ String text = decorator.decorateText(settings.getText(), element);
+ if (text !is null && text.length > 0)
+ settings.setText(text);
+ Image image = decorator.decorateImage(settings.getImage(), element);
+ if (image !is null)
+ settings.setImage(image);
+ }
+ if( auto colorDecorator = cast(IColorDecorator) decorator ){
+ Color background = colorDecorator.decorateBackground(element);
+ if (background !is null)
+ settings.setBackground(background);
+ Color foreground = colorDecorator.decorateForeground(element);
+ if (foreground !is null)
+ settings.setForeground(foreground);
+ }
+
+ if( auto fd = cast(IFontDecorator) decorator ) {
+ Font font = fd.decorateFont(element);
+ if (font !is null)
+ settings.setFont(font);
+ }
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/DecorationContext.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/DecorationContext.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
removes the property from
+ * the context.
+ * @param property the property
+ * @param value the value of the property or null
+ * if the property is to be removed.
+ */
+ public void putProperty(String property, Object value) {
+ if (value is null) {
+ properties.removeKey(property);
+ } else {
+ properties.add(property, value);
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/DecorationOverlayIcon.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/DecorationOverlayIcon.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit DecorationOverlayIcon
is an image descriptor that can be used
+ * to overlay decoration images on to the 4 corner quadrants of a base image.
+ * The four quadrants are {@link IDecoration#TOP_LEFT}, {@link IDecoration#TOP_RIGHT},
+ * {@link IDecoration#BOTTOM_LEFT} and {@link IDecoration#BOTTOM_RIGHT}. Additionally,
+ * the overlay can be used to provide an underlay corresponding to {@link IDecoration#UNDERLAY}.
+ *
+ * @since 3.3
+ * @see IDecoration
+ */
+public class DecorationOverlayIcon : CompositeImageDescriptor {
+
+ // the base image
+ private Image base;
+
+ // the overlay images
+ private ImageDescriptor[] overlays;
+
+ // the size
+ private Point size;
+
+ /**
+ * Create the decoration overlay for the base image using the array of
+ * provided overlays. The indices of the array correspond to the values
+ * of the 5 overlay constants defined on {@link IDecoration}
+ * ({@link IDecoration#TOP_LEFT}, {@link IDecoration#TOP_RIGHT},
+ * {@link IDecoration#BOTTOM_LEFT}, {@link IDecoration#BOTTOM_RIGHT}
+ * and{@link IDecoration#UNDERLAY}).
+ *
+ * @param baseImage the base image
+ * @param overlaysArray the overlay images
+ * @param sizeValue the size of the resulting image
+ */
+ public this(Image baseImage,
+ ImageDescriptor[] overlaysArray, Point sizeValue) {
+ this.base = baseImage;
+ this.overlays = overlaysArray;
+ this.size = sizeValue;
+ }
+
+ /**
+ * Create the decoration overlay for the base image using the array of
+ * provided overlays. The indices of the array correspond to the values
+ * of the 5 overlay constants defined on {@link IDecoration}
+ * ({@link IDecoration#TOP_LEFT}, {@link IDecoration#TOP_RIGHT},
+ * {@link IDecoration#BOTTOM_LEFT}, {@link IDecoration#BOTTOM_RIGHT}
+ * and {@link IDecoration#UNDERLAY}).
+ *
+ * @param baseImage the base image
+ * @param overlaysArray the overlay images
+ */
+ public this(Image baseImage, ImageDescriptor[] overlaysArray) {
+ this(baseImage, overlaysArray, new Point(baseImage.getBounds().width, baseImage.getBounds().height));
+ }
+
+ /**
+ * Create a decoration overlay icon that will place the given overlay icon in
+ * the given quadrant of the base image.
+ * @param baseImage the base image
+ * @param overlayImage the overlay image
+ * @param quadrant the quadrant (one of {@link IDecoration}
+ * ({@link IDecoration#TOP_LEFT}, {@link IDecoration#TOP_RIGHT},
+ * {@link IDecoration#BOTTOM_LEFT}, {@link IDecoration#BOTTOM_RIGHT}
+ * or {@link IDecoration#UNDERLAY})
+ */
+ public this(Image baseImage, ImageDescriptor overlayImage, int quadrant) {
+ this(baseImage, createArrayFrom(overlayImage, quadrant));
+ }
+
+ /**
+ * Convert the given image and quadrant into the proper input array.
+ * @param overlayImage the overlay image
+ * @param quadrant the quadrant
+ * @return an array with the given image in the proper quadrant
+ */
+ private static ImageDescriptor[] createArrayFrom(
+ ImageDescriptor overlayImage, int quadrant) {
+ ImageDescriptor[] descs = [ cast(ImageDescriptor) null, null, null, null, null ];
+ descs[quadrant] = overlayImage;
+ return descs;
+ }
+
+ /**
+ * Draw the overlays for the receiver.
+ * @param overlaysArray
+ */
+ private void drawOverlays(ImageDescriptor[] overlaysArray) {
+
+ for (int i = 0; i < overlays.length; i++) {
+ ImageDescriptor overlay = overlaysArray[i];
+ if (overlay is null) {
+ continue;
+ }
+ ImageData overlayData = overlay.getImageData();
+ //Use the missing descriptor if it is not there.
+ if (overlayData is null) {
+ overlayData = ImageDescriptor.getMissingImageDescriptor()
+ .getImageData();
+ }
+ switch (i) {
+ case IDecoration.TOP_LEFT:
+ drawImage(overlayData, 0, 0);
+ break;
+ case IDecoration.TOP_RIGHT:
+ drawImage(overlayData, size.x - overlayData.width, 0);
+ break;
+ case IDecoration.BOTTOM_LEFT:
+ drawImage(overlayData, 0, size.y - overlayData.height);
+ break;
+ case IDecoration.BOTTOM_RIGHT:
+ drawImage(overlayData, size.x - overlayData.width, size.y
+ - overlayData.height);
+ break;
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public override int opEquals(Object o) {
+ if (!( cast(DecorationOverlayIcon)o )) {
+ return false;
+ }
+ DecorationOverlayIcon other = cast(DecorationOverlayIcon) o;
+ return base.opEquals(other.base)
+ && Util.opEquals(overlays, other.overlays);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public override hash_t toHash() {
+ int code = base.toHash();
+ for (int i = 0; i < overlays.length; i++) {
+ if (overlays[i] !is null) {
+ code ^= overlays[i].toHash();
+ }
+ }
+ return code;
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.resource.CompositeImageDescriptor#drawCompositeImage(int, int)
+ */
+ protected void drawCompositeImage(int width, int height) {
+ if (overlays.length > IDecoration.UNDERLAY) {
+ ImageDescriptor underlay = overlays[IDecoration.UNDERLAY];
+ if (underlay !is null) {
+ drawImage(underlay.getImageData(), 0, 0);
+ }
+ }
+ drawImage(base.getImageData(), 0, 0);
+ drawOverlays(overlays);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.resource.CompositeImageDescriptor#getSize()
+ */
+ protected Point getSize() {
+ return size;
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.resource.CompositeImageDescriptor#getTransparentPixel()
+ */
+ protected int getTransparentPixel() {
+ return base.getImageData().transparentPixel;
+ }
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/DialogCellEditor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/DialogCellEditor.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ * createButton
: creates the cell editor's button controlcreateContents
: creates the cell editor's 'display value' controlupdateContents
: updates the cell editor's 'display value' control
+ * after its value has changedopenDialogBox
: opens the dialog box when the end user presses
+ * the button
"cell_editor_dots_button_image"
).
+ */
+ public static const String CELL_EDITOR_IMG_DOTS_BUTTON = "cell_editor_dots_button_image";//$NON-NLS-1$
+
+ /**
+ * The editor control.
+ */
+ private Composite editor;
+
+ /**
+ * The current contents.
+ */
+ private Control contents;
+
+ /**
+ * The label that gets reused by updateLabel
.
+ */
+ private Label defaultLabel;
+
+ /**
+ * The button.
+ */
+ private Button button;
+
+ /**
+ * Listens for 'focusLost' events and fires the 'apply' event as long
+ * as the focus wasn't lost because the dialog was opened.
+ */
+ private FocusListener buttonFocusListener;
+
+ /**
+ * The value of this cell editor; initially null
.
+ */
+ private Object value = null;
+
+ static this() {
+ ImageRegistry reg = JFaceResources.getImageRegistry();
+ reg.put(CELL_EDITOR_IMG_DOTS_BUTTON, ImageDescriptor.createFromFile(
+ DialogCellEditor.classinfo, "images/dots_button.gif"));//$NON-NLS-1$
+ }
+
+ /**
+ * Internal class for laying out the dialog.
+ */
+ private class DialogCellLayout : Layout {
+ public void layout(Composite editor, bool force) {
+ Rectangle bounds = editor.getClientArea();
+ Point size = button.computeSize(DWT.DEFAULT, DWT.DEFAULT, force);
+ if (contents !is null) {
+ contents.setBounds(0, 0, bounds.width - size.x, bounds.height);
+ }
+ button.setBounds(bounds.width - size.x, 0, size.x, bounds.height);
+ }
+
+ public Point computeSize(Composite editor, int wHint, int hHint,
+ bool force) {
+ if (wHint !is DWT.DEFAULT && hHint !is DWT.DEFAULT) {
+ return new Point(wHint, hHint);
+ }
+ Point contentsSize = contents.computeSize(DWT.DEFAULT, DWT.DEFAULT,
+ force);
+ Point buttonSize = button.computeSize(DWT.DEFAULT, DWT.DEFAULT,
+ force);
+ // Just return the button width to ensure the button is not clipped
+ // if the label is long.
+ // The label will just use whatever extra width there is
+ Point result = new Point(buttonSize.x, Math.max(contentsSize.y,
+ buttonSize.y));
+ return result;
+ }
+ }
+
+ /**
+ * Default DialogCellEditor style
+ */
+ private static const int defaultStyle = DWT.NONE;
+
+ /**
+ * Creates a new dialog cell editor with no control
+ * @since 2.1
+ */
+ public this() {
+ setStyle(defaultStyle);
+ }
+
+ /**
+ * Creates a new dialog cell editor parented under the given control.
+ * The cell editor value is null
initially, and has no
+ * validator.
+ *
+ * @param parent the parent control
+ */
+ protected this(Composite parent) {
+ this(parent, defaultStyle);
+ }
+
+ /**
+ * Creates a new dialog cell editor parented under the given control.
+ * The cell editor value is null
initially, and has no
+ * validator.
+ *
+ * @param parent the parent control
+ * @param style the style bits
+ * @since 2.1
+ */
+ protected this(Composite parent, int style) {
+ super(parent, style);
+ }
+
+ /**
+ * Creates the button for this cell editor under the given parent control.
+ * + * The default implementation of this framework method creates the button + * display on the right hand side of the dialog cell editor. Subclasses + * may extend or reimplement. + *
+ * + * @param parent the parent control + * @return the new button control + */ + protected Button createButton(Composite parent) { + Button result = new Button(parent, DWT.DOWN); + result.setText("..."); //$NON-NLS-1$ + return result; + } + + /** + * Creates the controls used to show the value of this cell editor. + *+ * The default implementation of this framework method creates + * a label widget, using the same font and background color as the parent control. + *
+ *
+ * Subclasses may reimplement. If you reimplement this method, you
+ * should also reimplement updateContents
.
+ *
createContents
.
+ *
+ * @return the default label widget
+ */
+ protected Label getDefaultLabel() {
+ return defaultLabel;
+ }
+
+ /**
+ * Opens a dialog box under the given parent control and returns the
+ * dialog's value when it closes, or null
if the dialog
+ * was canceled or no selection was made in the dialog.
+ * + * This framework method must be implemented by concrete subclasses. + * It is called when the user has pressed the button and the dialog + * box must pop up. + *
+ * + * @param cellEditorWindow the parent control cell editor's window + * so that a subclass can adjust the dialog box accordingly + * @return the selected value, ornull
if the dialog was
+ * canceled or no selection was made in the dialog
+ */
+ protected abstract Object openDialogBox(Control cellEditorWindow);
+
+ /**
+ * Updates the controls showing the value of this cell editor.
+ *
+ * The default implementation of this framework method just converts
+ * the passed object to a string using toString
and
+ * sets this as the text of the label widget.
+ *
+ * Subclasses may reimplement. If you reimplement this method, you
+ * should also reimplement createContents
.
+ *
+ * Subclasses should overwrite! + *
+ * + * @param element + * the model element + * @param value + * the new value + */ + protected abstract void setValue(Object element, Object value); + + /** + * @return the viewer this editing support works for + */ + public ColumnViewer getViewer() { + return viewer; + } + + /** + * Initialize the editor. Frameworks like Databinding can hook in here and provide + * a customized implementation.Standard customers should not overwrite this method but {@link #getValue(Object)}
+ * + * @param cellEditor + * the cell editor + * @param cell + * the cell the editor is working for + */ + protected void initializeCellEditorValue(CellEditor cellEditor, ViewerCell cell) { + Object value = getValue(cell.getElement()); + cellEditor.setValue(value); + } + package void initializeCellEditorValue_package(CellEditor cellEditor, ViewerCell cell) { + initializeCellEditorValue(cellEditor, cell); + } + + /** + * Save the value of the cell editor back to the model. Frameworks like Databinding can hook in here and provide + * a customized implementation.Standard customers should not overwrite this method but {@link #setValue(Object, Object)}
+ * @param cellEditor + * the cell-editor + * @param cell + * the cell the editor is working for + */ + protected void saveCellEditorValue(CellEditor cellEditor, ViewerCell cell) { + Object value = cellEditor.getValue(); + setValue(cell.getElement(), value); + } + package void saveCellEditorValue_package(CellEditor cellEditor, ViewerCell cell) { + saveCellEditorValue(cellEditor, cell); + } + + bool isLegacySupport() { + return false; + } +} diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/FocusCellHighlighter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/viewers/FocusCellHighlighter.d Mon Mar 31 00:47:19 2008 +0200 @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank BenoitILabelProvider
or
+ * an ITableLabelProvider
.
+ * + * A label provider must not be shared between viewers + * since a label provider generally manages DWT resources (images), + * which must be disposed when the viewer is disposed. + * To simplify life cycle management, the current label provider + * of a viewer is disposed when the viewer is disposed. + *
+ *
+ * Label providers can be used outside the context of viewers wherever
+ * images are needed. When label providers are used in this fashion
+ * it is the responsibility of the user to ensure dispose
+ * is called when the provider is no longer needed.
+ *
+ * Label provider listeners are informed about state changes + * that affect the rendering of the viewer that uses this label provider. + *
+ * + * @param listener a label provider listener + */ + public void addListener(ILabelProviderListener listener); + + /** + * Disposes of this label provider. When a label provider is + * attached to a viewer, the viewer will automatically call + * this method when the viewer is being closed. When label providers + * are used outside of the context of a viewer, it is the client's + * responsibility to ensure that this method is called when the + * provider is no longer needed. + */ + public void dispose(); + + /** + * Returns whether the label would be affected + * by a change to the given property of the given element. + * This can be used to optimize a non-structural viewer update. + * If the property mentioned in the update does not affect the label, + * then the viewer need not update the label. + * + * @param element the element + * @param property the property + * @returntrue
if the label would be affected,
+ * and false
if it would be unaffected
+ */
+ public bool isLabelProperty(Object element, String property);
+
+ /**
+ * Removes a listener to this label provider.
+ * Has no affect if an identical listener is not registered.
+ *
+ * @param listener a label provider listener
+ */
+ public void removeListener(ILabelProviderListener listener);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IBasicPropertyConstants.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IBasicPropertyConstants.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit "dwtx.jface.text"
)
+ * for an element's label text.
+ *
+ * @see dwtx.jface.viewers.ILabelProvider#getText
+ */
+ public static final String P_TEXT = "dwtx.jface.text"; //$NON-NLS-1$
+
+ /**
+ * Property name constant (value "dwtx.jface.image"
)
+ * for an element's label image.
+ *
+ * @see dwtx.jface.viewers.ILabelProvider#getImage
+ */
+ public static final String P_IMAGE = "dwtx.jface.image"; //$NON-NLS-1$
+
+ /**
+ * Property name constant (value "dwtx.jface.children"
)
+ * for an element's children.
+ */
+ public static final String P_CHILDREN = "dwtx.jface.children"; //$NON-NLS-1$
+
+ /**
+ * Property name constant (value "dwtx.jface.parent"
)
+ * for an element's parent object.
+ */
+ public static final String P_PARENT = "dwtx.jface.parent"; //$NON-NLS-1$
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ICellEditorListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ICellEditorListener.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * This interface should be implemented by classes that wish to + * react to cell editor activity. + *
+ *+ * Note: the cell editor is not passed as a parameter to any + * of these methods; so the assumption is that the listener + * knows which cell editor is talking to it. + *
+ */ +public interface ICellEditorListener { + /** + * Notifies that the end user has requested applying a value. + * All cell editors send this notification. + *+ * The normal reaction is to update the model with the current cell editor value. + * However, if the value is not valid, it should not be applied. + * A typical text-based cell editor would send this message + * when the end user hits Return, whereas other editors would + * send it whenever their value changes. + *
+ */ + public void applyEditorValue(); + + /** + * Notifies that the end user has canceled editing. + * All cell editors send this notification. + * A listener should not update the model based on this + * notification; seeapplyEditorValue
.
+ */
+ public void cancelEditor();
+
+ /**
+ * Notifies that the end user is changing the value in the cell editor. This
+ * notification is normally sent only by text-based editors in response to a
+ * keystroke, so that the listener may show an error message reflecting the
+ * current valid state. This notification is sent while the value is being
+ * actively edited, before the value is applied or canceled. A listener should
+ * not update the model based on this notification; see
+ * applyEditorValue
.
+ *
+ * If the newValidState
parameter is true
,
+ * the new value may be retrieved by calling ICellEditor.getValue
+ * on the appropriate cell editor.
+ *
+ * This interface should be implemented by classes that wish to + * act as cell editor validators. + *
+ */ +public interface ICellEditorValidator { + /** + * Returns a string indicating whether the given value is valid; + *null
means valid, and non-null
means
+ * invalid, with the result being the error message to display
+ * to the end user.
+ * + * It is the responsibility of the implementor to fully format the + * message before returning it. + *
+ * + * @param value the value to be validated + * @return the error message, ornull
indicating
+ * that the value is valid
+ */
+ public String isValid(Object value);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ICellModifier.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ICellModifier.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * This interface should be implemented by classes that wish to + * act as cell modifiers. + *
+ */ +public interface ICellModifier { + /** + * Checks whether the given property of the given element can be + * modified. + * + * @param element the element + * @param property the property + * @returntrue
if the property can be modified,
+ * and false
if it is not modifiable
+ */
+ public bool canModify(Object element, String property);
+
+ /**
+ * Returns the value for the given property of the given element.
+ * Returns null
if the element does not have the given property.
+ *
+ * @param element the element
+ * @param property the property
+ * @return the property value
+ */
+ public Object getValue(Object element, String property);
+
+ /**
+ * Modifies the value for the given property of the given element.
+ * Has no effect if the element does not have the given property,
+ * or if the property cannot be modified.
+ * + * Note that it is possible for an DWT Item to be passed instead of + * the model element. To handle this case in a safe way, use: + *
+ * if (element instanceof Item) { + * element = ((Item) element).getData(); + * } + * // modify the element's property here + *+ * + * + * @param element the model element or DWT Item (see above) + * @param property the property + * @param value the new property value + * + * @see dwt.widgets.Item + */ + public void modify(Object element, String property, Object value); +} diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ICheckStateListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/viewers/ICheckStateListener.d Mon Mar 31 00:47:19 2008 +0200 @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit
true
if the element is checked,
+ * and false
if not checked
+ */
+ public bool getChecked(Object element);
+
+ /**
+ * Removes the given check state listener from this viewer.
+ * Has no effect if an identical listener is not registered.
+ *
+ * @param listener a check state listener
+ */
+ public void removeCheckStateListener(ICheckStateListener listener);
+
+ /**
+ * Sets the checked state for the given element in this viewer.
+ * Does not fire events to check state listeners.
+ *
+ * @param element the element
+ * @param state true
if the item should be checked,
+ * and false
if it should be unchecked
+ * @return true
if the checked state could be set,
+ * and false
otherwise
+ */
+ public bool setChecked(Object element, bool state);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IColorDecorator.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IColorDecorator.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
if there
+ * is not one.
+ * @param element
+ * @return Color or null
+ */
+ public Color decorateForeground(Object element);
+
+ /**
+ * Return the background Color for element or null
if there
+ * is not one.
+ * @param element
+ * @return Color or null
+ */
+ public Color decorateBackground(Object element);
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IColorProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IColorProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
+ * to use the default foreground color
+ */
+ Color getForeground(Object element);
+
+ /**
+ * Provides a background color for the given element.
+ *
+ * @param element the element
+ * @return the background color for the element, or null
+ * to use the default background color
+ */
+ Color getBackground(Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IContentProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IContentProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * The viewer should not be updated during this call, as it is in the process + * of being disposed. + *
+ */ + public void dispose(); + + /** + * Notifies this content provider that the given viewer's input + * has been switched to a different element. + *+ * A typical use for this method is registering the content provider as a listener + * to changes on the new input (using model-specific means), and deregistering the viewer + * from the old input. In response to these change notifications, the content provider + * should update the viewer (see the add, remove, update and refresh methods on the viewers). + *
+ *+ * The viewer should not be updated during this call, as it might be in the process + * of being disposed. + *
+ * + * @param viewer the viewer + * @param oldInput the old input element, ornull
if the viewer
+ * did not previously have an input
+ * @param newInput the new input element, or null
if the viewer
+ * does not have an input
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IDecoration.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IDecoration.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit ILightweightLabelDecorator
.
+ */
+public interface IDecoration{
+
+ /**
+ * Constants for placement of image decorations.
+ */
+ public static const int TOP_LEFT = 0;
+
+ /**
+ * Constant for the top right quadrant.
+ */
+ public static const int TOP_RIGHT = 1;
+
+ /**
+ * Constant for the bottom left quadrant.
+ */
+ public static const int BOTTOM_LEFT = 2;
+
+ /**
+ * Constant for the bottom right quadrant.
+ */
+ public static const int BOTTOM_RIGHT = 3;
+
+ /**
+ * Constant for the underlay.
+ */
+ public static const int UNDERLAY = 4;
+
+ /**
+ * Adds a prefix to the element's label.
+ *
+ * @param prefix
+ * the prefix
+ */
+ public void addPrefix(String prefix);
+
+ /**
+ * Adds a suffix to the element's label.
+ *
+ * @param suffix
+ * the suffix
+ */
+ public void addSuffix(String suffix);
+
+ /**
+ * Adds an overlay to the element's image.
+ *
+ * @param overlay
+ * the overlay image descriptor
+ */
+ public void addOverlay(ImageDescriptor overlay);
+
+ /**
+ * Adds an overlay to the element's image.
+ *
+ * @param overlay
+ * the overlay image descriptor
+ * @param quadrant
+ * The constant for the quadrant to draw the image on.
+ */
+ public void addOverlay(ImageDescriptor overlay, int quadrant);
+
+ /**
+ * Set the foreground color for this decoration.
+ * @param color the color to be set for the foreground
+ *
+ * @since 3.1
+ */
+ public void setForegroundColor(Color color);
+
+ /**
+ * Set the background color for this decoration.
+ * @param color the color to be set for the background
+ *
+ * @since 3.1
+ */
+ public void setBackgroundColor(Color color);
+
+ /**
+ * Set the font for this decoration.
+ * @param font the font to use in this decoration
+ *
+ * @since 3.1
+ */
+ public void setFont(Font font);
+
+ /**
+ * Return the decoration context in which this decoration
+ * will be applied.
+ * @return the decoration context
+ *
+ * @since 3.2
+ */
+ public IDecorationContext getDecorationContext();
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IDecorationContext.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IDecorationContext.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit
+ * This interface is not intended to be implemented by clients
+ *
+ * @see LabelDecorator
+ *
+ * @since 3.2
+ */
+public interface IDecorationContext {
+
+ /**
+ * Get the value of the given property or
+ * A typical response would be to refresh all labels by
+ * re-requesting them from the label provider.
+ *
+ * Intended as an optimization for when the viewer does not need the actual
+ * children. Clients may be able to implement this more efficiently than
+ *
+ * The difference between this method and
+ * Intended as an optimization for when the viewer does not
+ * need the actual children. Clients may be able to implement
+ * this more efficiently than
+ * The provided path is relative to the input. The root elements must
+ * be obtained by calling
+ * {@link IStructuredContentProvider#getElements(Object)}.
+ *
+ * Intended as an optimization for when the viewer does not need the actual
+ * children. Clients may be able to implement this more efficiently than
+ *
+ * It also allows the current values for the text and image to be considered by
+ * the label provider, allowing for potential optimizations.
+ * For example, decorating label providers that run in the background can hold off
+ * applying an update to a previously populated label until the decoration is ready,
+ * thereby reducing flicker.
+ *
+ * This class may be used as is, or subclassed to provide richer labels.
+ * Subclasses may override any of the following methods:
+ * null
+ * if the property does not exist in this context.
+ * @param property the property
+ * @return the value of the given property or null
+ */
+ Object getProperty(String property);
+
+ /**
+ * Return the properties that exist in this context
+ * (i.e. the set of properties that have values associated
+ * with them.
+ * @return the properties that exist in this context
+ */
+ String[] getProperties();
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IDelayedLabelDecorator.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IDelayedLabelDecorator.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if the decoration is ready for this element
+ */
+
+ public bool prepareDecoration(Object element, String originalText);
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IDoubleClickListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IDoubleClickListener.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit equals
and hashCode
implementations of the
+ * elements themselves.
+ *
+ * @see StructuredViewer#setComparer
+ */
+public interface IElementComparer {
+
+ /**
+ * Compares two elements for equality
+ *
+ * @param a the first element
+ * @param b the second element
+ * @return whether a is equal to b
+ */
+ int opEquals(Object a, Object b);
+
+ /**
+ * Returns the hash code for the given element.
+ * @param element the element the hash code is calculated for
+ *
+ * @return the hash code for the given element
+ */
+ hash_t toHash(Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IFilter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IFilter.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if the object is accepted by the filter.
+ */
+ public bool select(Object toTest);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IFontDecorator.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IFontDecorator.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
if there
+ * is not one.
+ *
+ * @param element
+ * @return Font or null
+ */
+ public Font decorateFont(Object element);
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IFontProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IFontProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
+ * to use the default font
+ */
+ public Font getFont(Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IInputProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IInputProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
if the element has no image
+ * @param element the element whose image is being decorated
+ * @return the decorated image, or null
if no decoration is to be applied
+ *
+ * @see dwtx.jface.resource.CompositeImageDescriptor
+ */
+ public Image decorateImage(Image image, Object element);
+
+ /**
+ * Returns a text label that is based on the given text label,
+ * but decorated with additional information relating to the state
+ * of the provided element.
+ *
+ * Text and image decoration updates can occur as a result of other updates
+ * within the workbench including deferred decoration by background processes.
+ * Clients should handle labelProviderChangedEvents for the given element to get
+ * the complete decoration.
+ * @see LabelProviderChangedEvent
+ * @see IBaseLabelProvider#addListener
+ *
+ * @param text the input text label to decorate
+ * @param element the element whose image is being decorated
+ * @return the decorated text label, or null
if no decoration is to be applied
+ */
+ public String decorateText(String text, Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ILabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ILabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit IBaseLabelProvider
with the methods
+ * to provide the text and/or image for the label of a given element.
+ * Used by most structured viewers, except table viewers.
+ */
+public interface ILabelProvider : IBaseLabelProvider {
+ /**
+ * Returns the image for the label of the given element. The image
+ * is owned by the label provider and must not be disposed directly.
+ * Instead, dispose the label provider when no longer needed.
+ *
+ * @param element the element for which to provide the label image
+ * @return the image used to label the element, or null
+ * if there is no image for the given object
+ */
+ public Image getImage(Object element);
+
+ /**
+ * Returns the text for the label of the given element.
+ *
+ * @param element the element for which to provide the label text
+ * @return the text string used to label the element, or null
+ * if there is no text label for the given object
+ */
+ public String getText(Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ILabelProviderListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ILabelProviderListener.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit #setItemCount
on the
+ * viewer that uses it.
+ */
+public interface ILazyContentProvider : IContentProvider {
+ /**
+ * Called when a previously-blank item becomes visible in the
+ * TableViewer. If the content provider knows the element
+ * at this row, it should respond by calling
+ * TableViewer#replace(Object, int).
+ *
+ * NOTE #updateElement(int index) can be used to determine selection
+ * values. TableViewer#replace(Object, int) is not called before
+ * returning from this method selections may have missing or stale elements.
+ * In this situation it is suggested that the selection is asked
+ * for again after he update.
+ *
+ * @param index The index that is being updated in the
+ * table.
+ */
+ public void updateElement(int index);
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ILazyTreeContentProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ILazyTreeContentProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
+ * indicating that the parent can't be computed.
+ * In this case the tree-structured viewer can't expand
+ * a given node correctly if requested.
+ *
+ * @param element the element
+ * @return the parent element, or null
if it
+ * has none or if the parent cannot be computed
+ */
+ public Object getParent(Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ILazyTreePathContentProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ILazyTreePathContentProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit updateChildCount
.
+ * ILightweightLabelDecorator
is a decorator that decorates
+ * using a prefix, suffix and overlay image rather than doing all
+ * of the image and text management itself like an ILabelDecorator
.
+ */
+public interface ILightweightLabelDecorator : IBaseLabelProvider {
+
+ /**
+ * Calculates decorations based on element.
+ *
+ * @param element the element to decorate
+ * @param decoration the decoration to set
+ */
+ public void decorate(Object element, IDecoration decoration);
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/IOpenListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/IOpenListener.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if this selection is empty,
+ * and false
otherwise
+ */
+ public bool isEmpty();
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ISelectionChangedListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ISelectionChangedListener.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
+ * if the selection is empty.
+ *
+ * @return an element, or null
if none
+ */
+ public Object getFirstElement();
+
+ /**
+ * Returns an iterator over the elements of this selection.
+ *
+ * @return an iterator over the selected elements
+ */
+ public Iterator!(Object) iterator();
+
+ /**
+ * Returns the number of elements selected in this selection.
+ *
+ * @return the number of elements selected
+ */
+ public int size();
+
+ /**
+ * Returns the elements in this selection as an array.
+ *
+ * @return the selected elements as an array
+ */
+ public Object[] toArray();
+
+ /**
+ * Returns the elements in this selection as a List
.
+ *
+ * @return the selected elements as a list
+ */
+ public SeqView!(Object) toList();
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ITableColorProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ITableColorProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation 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:
+ * Initial implementation - Gunnar Ahlberg (IBS AB, www.ibs.net)
+ * IBM Corporation - further revisions
+ * Port to the D programming language:
+ * Frank Benoit null
to
+ * use the default foreground color
+ */
+ Color getForeground(Object element, int columnIndex);
+
+ /**
+ * Provides a background color for the given element at the specified index
+ *
+ * @param element the element
+ * @param columnIndex the zero-based index of the column in which the color appears
+ * @return the background color for the element, or null
to
+ * use the default background color
+ *
+ */
+ Color getBackground(Object element, int columnIndex);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ITableFontProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ITableFontProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit IBaseLabelProvider
with the methods
+ * to provide the text and/or image for each column of a given element.
+ * Used by table viewers.
+ *
+ * @see TableViewer
+ */
+public interface ITableLabelProvider : IBaseLabelProvider {
+ /**
+ * Returns the label image for the given column of the given element.
+ *
+ * @param element the object representing the entire row, or
+ * null
indicating that no input object is set
+ * in the viewer
+ * @param columnIndex the zero-based index of the column in which
+ * the label appears
+ * @return Image or null
if there is no image for the
+ * given object at columnIndex
+ */
+ public Image getColumnImage(Object element, int columnIndex);
+
+ /**
+ * Returns the label text for the given column of the given element.
+ *
+ * @param element the object representing the entire row, or
+ * null
indicating that no input object is set
+ * in the viewer
+ * @param columnIndex the zero-based index of the column in which the label appears
+ * @return String or or null
if there is no text for the
+ * given object at columnIndex
+ */
+ public String getColumnText(Object element, int columnIndex);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ITreeContentProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ITreeContentProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit IStructuredContentProvider.getElements
+ * is that getElements
is called to obtain the
+ * tree viewer's root elements, whereas getChildren
is used
+ * to obtain the children of a given parent element in the tree (including a root).
+ * null
+ * indicating that the parent can't be computed.
+ * In this case the tree-structured viewer can't expand
+ * a given node correctly if requested.
+ *
+ * @param element the element
+ * @return the parent element, or null
if it
+ * has none or if the parent cannot be computed
+ */
+ public Object getParent(Object element);
+
+ /**
+ * Returns whether the given element has children.
+ * getChildren
.
+ * true
if the given element has children,
+ * and false
if it has no children
+ */
+ public bool hasChildren(Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ITreePathContentProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ITreePathContentProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit getChildren
.
+ * true
if the lat element of the path has children,
+ * and false
if it has no children
+ */
+ public bool hasChildren(TreePath path);
+
+ /**
+ * Return the possible parent paths for the given element. An empty array
+ * can be returned if the paths cannot be computed. If the element is
+ * a potential child of the input of the viewer, an empty tree path
+ * should be an entry in the returned array.
+ *
+ * @param element
+ * the element
+ * @return the possible parent paths for the given element
+ */
+ public TreePath[] getParents(Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ITreePathLabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ITreePathLabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit IBaseLabelProvider
with the methods
+ * to update the label for a given element. The label is represented by a
+ * ViewerLabel
.
+ * Unlike ILabelProvider
, this allows the text and image to be
+ * set in the same request, rather than via separate requests.
+ * null
if the element has no image
+ * @param element the element whose image is being decorated
+ * @param context additional context information about the element being decorated
+ * @return the decorated image, or null
if no decoration is to be applied
+ *
+ * @see dwtx.jface.resource.CompositeImageDescriptor
+ */
+ public abstract Image decorateImage(Image image, Object element, IDecorationContext context);
+
+ /**
+ * Returns a text label that is based on the given text label,
+ * but decorated with additional information relating to the state
+ * of the provided element taking into account the provided context.
+ *
+ * Text and image decoration updates can occur as a result of other updates
+ * within the workbench including deferred decoration by background processes.
+ * Clients should handle labelProviderChangedEvents for the given element to get
+ * the complete decoration.
+ * @see LabelProviderChangedEvent
+ * @see IBaseLabelProvider#addListener
+ *
+ * @param text the input text label to decorate
+ * @param element the element whose image is being decorated
+ * @param context additional context information about the element being decorated
+ * @return the decorated text label, or null
if no decoration is to be applied
+ */
+ public abstract String decorateText(String text, Object element, IDecorationContext context);
+
+ /**
+ * Prepare the element for decoration. If it is already decorated and ready for update
+ * return true. If decoration is pending return false.
+ * @param element The element to be decorated
+ * @param originalText The starting text.
+ * @param context The decoration context
+ * @return bool true
if the decoration is ready for this element
+ */
+ public abstract bool prepareDecoration(Object element, String originalText, IDecorationContext context);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/LabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/LabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit toString
value for its text and null
for its
+ * image.
+ *
+ *
+ * isLabelProperty
getImage
getText
dispose
LabelProvider
implementation of this
+ * ILabelProvider
method returns null
.
+ * Subclasses may override.
+ */
+ public Image getImage(Object element) {
+ return null;
+ }
+
+ /**
+ * The LabelProvider
implementation of this
+ * ILabelProvider
method returns the element's
+ * toString
string. Subclasses may override.
+ */
+ public String getText(Object element) {
+ return element is null ? "" : element.toString();//$NON-NLS-1$
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/LabelProviderChangedEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/LabelProviderChangedEvent.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
.
+ */
+ private Object[] elements;
+
+ /**
+ * Creates a new event for the given source, indicating that all labels
+ * provided by the source are no longer valid and should be updated.
+ *
+ * @param source the label provider
+ */
+ public this(IBaseLabelProvider source) {
+ super(cast(Object)source);
+ }
+
+ /**
+ * Creates a new event for the given source, indicating that the label
+ * provided by the source for the given elements is no longer valid and should be updated.
+ *
+ * @param source the label provider
+ * @param elements the element whose labels have changed
+ */
+ public this(IBaseLabelProvider source,
+ Object[] elements) {
+ super(cast(Object)source);
+ this.elements = elements;
+ }
+
+ /**
+ * Creates a new event for the given source, indicating that the label
+ * provided by the source for the given element is no longer valid and should be updated.
+ *
+ * @param source the label provider
+ * @param element the element whose label needs to be updated
+ */
+ public this(IBaseLabelProvider source, Object element) {
+ super(cast(Object)source);
+ this.elements = new Object[1];
+ this.elements[0] = element;
+ }
+
+ /**
+ * Returns the first element whose label needs to be updated,
+ * or null
if all labels need to be updated.
+ *
+ * @return the element whose label needs to be updated or null
+ */
+ public Object getElement() {
+ if (this.elements is null || this.elements.length is 0) {
+ return null;
+ } else {
+ return this.elements[0];
+ }
+ }
+
+ /**
+ * Returns the elements whose labels need to be updated,
+ * or null
if all labels need to be updated.
+ *
+ * @return the element whose labels need to be updated or null
+ */
+ public Object[] getElements() {
+ if (this.elements is null) {
+ return null;
+ } else {
+ return this.elements;
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ListViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ListViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Brad Reynolds - bug 141435
+ * Tom Schindl List
control.
+ *
+ * This class is not intended to be subclassed. It is designed to be
+ * instantiated with a pre-existing DWT List
control and configured
+ * with a domain-specific content provider, label provider, element filter (optional),
+ * and element sorter (optional).
+ *
+ * Note that the DWT List
control only supports the display of strings, not icons.
+ * If you need to show icons for items, use TableViewer
instead.
+ *
MULTI, H_SCROLL, V_SCROLL,
and BORDER
.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param parent the parent control
+ */
+ public this(Composite parent) {
+ this(parent, DWT.MULTI | DWT.H_SCROLL | DWT.V_SCROLL | DWT.BORDER);
+ }
+
+ /**
+ * Creates a list viewer on a newly-created list control under the given parent.
+ * The list control is created using the given DWT style bits.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param parent the parent control
+ * @param style the DWT style bits
+ */
+ public this(Composite parent, int style) {
+ this(new dwt.widgets.List.List(parent, style));
+ }
+
+ /**
+ * Creates a list viewer on the given list control.
+ * The viewer has no input, no content provider, a default label provider,
+ * no sorter, and no filters.
+ *
+ * @param list the list control
+ */
+ public this(dwt.widgets.List.List list) {
+ this.list = list;
+ hookControl(list);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Viewer.
+ */
+ public Control getControl() {
+ return list;
+ }
+
+ /**
+ * Returns this list viewer's list control.
+ *
+ * @return the list control
+ */
+ public dwt.widgets.List.List getList() {
+ return list;
+ }
+
+ /*
+ * Non-Javadoc.
+ * Method defined on StructuredViewer.
+ */
+ public void reveal(Object element) {
+ Assert.isNotNull(element);
+ int index = getElementIndex(element);
+ if (index is -1) {
+ return;
+ }
+ // algorithm patterned after List.showSelection()
+ int count = list.getItemCount();
+ if (count is 0) {
+ return;
+ }
+ int height = list.getItemHeight();
+ Rectangle rect = list.getClientArea();
+ int topIndex = list.getTopIndex();
+ int visibleCount = Math.max(rect.height / height, 1);
+ int bottomIndex = Math.min(topIndex + visibleCount, count) - 1;
+ if ((topIndex <= index) && (index <= bottomIndex)) {
+ return;
+ }
+ int newTop = Math.min(Math.max(index - (visibleCount / 2), 0),
+ count - 1);
+ list.setTopIndex(newTop);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listAdd(java.lang.String, int)
+ */
+ protected void listAdd(String string, int index) {
+ list.add(string, index);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listSetItem(int, java.lang.String)
+ */
+ protected void listSetItem(int index, String string) {
+ list.setItem(index, string);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listGetSelectionIndices()
+ */
+ protected int[] listGetSelectionIndices() {
+ return list.getSelectionIndices();
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listGetItemCount()
+ */
+ protected int listGetItemCount() {
+ return list.getItemCount();
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listSetItems(java.lang.String[])
+ */
+ protected void listSetItems(String[] labels) {
+ list.setItems(labels);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listRemoveAll()
+ */
+ protected void listRemoveAll() {
+ list.removeAll();
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listRemove(int)
+ */
+ protected void listRemove(int index) {
+ list.remove(index);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listSelectAndShow(int[])
+ */
+ protected void listSetSelection(int[] ixs) {
+ list.setSelection(ixs);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listDeselectAll()
+ */
+ protected void listDeselectAll() {
+ list.deselectAll();
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listShowSelection()
+ */
+ protected void listShowSelection() {
+ list.showSelection();
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listGetTopIndex()
+ */
+ protected int listGetTopIndex() {
+ return list.getTopIndex();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#listSetTopIndex(int)
+ */
+ protected void listSetTopIndex(int index) {
+ list.setTopIndex(index);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractListViewer#setSelectionToWidget(java.util.List, bool)
+ */
+ protected void setSelectionToWidget(SeqView!(Object) in_, bool reveal) {
+ if( reveal ) {
+ super.setSelectionToWidget(in_, reveal);
+ } else {
+ if (in_ is null || in_.size() is 0) { // clear selection
+ list.deselectAll();
+ } else {
+ int n = in_.size();
+ int[] ixs = new int[n];
+ int count = 0;
+ for (int i = 0; i < n; ++i) {
+ Object el = in_.get(i);
+ int ix = getElementIndex(el);
+ if (ix >= 0) {
+ ixs[count++] = ix;
+ }
+ }
+ if (count < n) {
+ System.arraycopy(ixs, 0, ixs = new int[count], 0, count);
+ }
+ list.deselectAll();
+ list.select(ixs);
+ }
+ }
+ }
+
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/NamedHandleObjectLabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/NamedHandleObjectLabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit NamedHandlerObject
, which
+ * exposes the name as the label.
+ *
+ * @since 3.2
+ */
+public final class NamedHandleObjectLabelProvider : LabelProvider {
+
+ /**
+ * The text of the element is simply the name of the element if its a
+ * defined instance of NamedHandleObject
. Otherwise, this
+ * method just returns null
.
+ *
+ * @param element
+ * The element for which the text should be retrieved; may be
+ * null
.
+ * @return the name of the handle object; null
if there is no
+ * name or if the element is not a named handle object.
+ */
+ public final String getText(Object element) {
+ if ( cast(NamedHandleObject)element ) {
+ try {
+ return (cast(NamedHandleObject) element).getName();
+ } catch (NotDefinedException e) {
+ return null;
+ }
+ }
+
+ return null;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/OpenEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/OpenEvent.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * This class is intended to be subclassed by implementors. + *
+ * + * @since 3.3 + * + */ +public abstract class OwnerDrawLabelProvider : CellLabelProvider { + + /** + * Set up the owner draw callbacks for the viewer. + * + * @param viewer + * the viewer the owner draw is set up + */ + public static void setUpOwnerDraw(ColumnViewer viewer) { + viewer.getControl().addListener(DWT.MeasureItem, new class Listener { + ColumnViewer viewer_; + this(){ + viewer_=viewer; + } + /* + * (non-Javadoc) + * + * @see dwt.widgets.Listener#handleEvent(dwt.widgets.Event) + */ + public void handleEvent(Event event) { + CellLabelProvider provider = viewer_ + .getViewerColumn(event.index).getLabelProvider(); + Object element = event.item.getData(); + + if ( auto p = cast(OwnerDrawLabelProvider) provider ) + p.measure(event, element); + } + }); + + viewer.getControl().addListener(DWT.PaintItem, new class Listener { + ColumnViewer viewer_; + this(){ + viewer_=viewer; + } + /* + * (non-Javadoc) + * + * @see dwt.widgets.Listener#handleEvent(dwt.widgets.Event) + */ + public void handleEvent(Event event) { + CellLabelProvider provider = viewer_ + .getViewerColumn(event.index).getLabelProvider(); + Object element = event.item.getData(); + + if ( auto p = cast(OwnerDrawLabelProvider) provider ) + p.paint(event, element); + } + }); + + viewer.getControl().addListener(DWT.EraseItem, new class Listener { + ColumnViewer viewer_; + this(){ + viewer_=viewer; + } + /* + * (non-Javadoc) + * + * @see dwt.widgets.Listener#handleEvent(dwt.widgets.Event) + */ + public void handleEvent(Event event) { + + CellLabelProvider provider = getLabelProvider(viewer_, event); + Object element = getElement(event); + + if ( auto p = cast(OwnerDrawLabelProvider) provider ) + p.erase(event, element); + + } + + /** + * Return the item for the event + * + * @param event + * @return Object + */ + private Object getElement(Event event) { + return event.item.getData(); + } + + /** + * Return the label provider for the column. + * + * @param viewer + * @param event + * @return CellLabelProvider + */ + private CellLabelProvider getLabelProvider( + ColumnViewer viewer, Event event) { + return viewer.getViewerColumn(event.index).getLabelProvider(); + } + }); + } + + /** + * Handle the erase event. The default implementation colors the background + * of selected areas with {@link DWT#COLOR_LIST_SELECTION} and foregrounds + * with {@link DWT#COLOR_LIST_SELECTION_TEXT} + * + * @param event + * the erase event + * @param element + * the model object + * @see DWT#EraseItem + * @see DWT#COLOR_LIST_SELECTION + * @see DWT#COLOR_LIST_SELECTION_TEXT + */ + protected void erase(Event event, Object element) { + + Rectangle bounds = event.getBounds(); + if ((event.detail & DWT.SELECTED) !is 0) { + + Color oldForeground = event.gc.getForeground(); + Color oldBackground = event.gc.getBackground(); + + event.gc.setBackground(event.item.getDisplay().getSystemColor( + DWT.COLOR_LIST_SELECTION)); + event.gc.setForeground(event.item.getDisplay().getSystemColor( + DWT.COLOR_LIST_SELECTION_TEXT)); + event.gc.fillRectangle(bounds); + /* restore the old GC colors */ + event.gc.setForeground(oldForeground); + event.gc.setBackground(oldBackground); + /* ensure that default selection is not drawn */ + event.detail &= ~DWT.SELECTED; + + } + + } + + /** + * Handle the paint event. + * + * @param event + * the paint event + * @param element + * the model element + * @see DWT#PaintItem + */ + protected abstract void paint(Event event, Object element); + + /** + * Handle the measure event. + * + * @param event + * the measure event + * @param element + * the model element + * @see DWT#MeasureItem + */ + protected abstract void measure(Event event, Object element); + + /** + * Create a new instance of the receiver based on a column viewer. + * + */ + public this() { + + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.viewers.ViewerLabelProvider#update(dwtx.jface.viewers.ViewerCell) + */ + public void update(ViewerCell cell) { + // Force a redraw + Rectangle cellBounds = cell.getBounds(); + cell.getControl().redraw(cellBounds.x, cellBounds.y, cellBounds.width, + cellBounds.height, true); + + } + +} diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/SWTFocusCellManager.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/viewers/SWTFocusCellManager.d Mon Mar 31 00:47:19 2008 +0200 @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Tom SchindlIStructuredSelection
interface,
+ * suitable for instantiating.
+ * + * This class is not intended to be subclassed. + *
+ */ +public class StructuredSelection : IStructuredSelection { + + /** + * The element that make up this structured selection. + */ + private Object[] elements; + + /** + * The canonical empty selection. This selection should be used instead of + *null
.
+ */
+ public static const StructuredSelection EMPTY;
+ static this(){
+ EMPTY = new StructuredSelection();
+ }
+ /**
+ * Creates a new empty selection.
+ * See also the static field EMPTY
which contains an empty selection singleton.
+ *
+ * @see #EMPTY
+ */
+ public this() {
+ }
+
+ /**
+ * Creates a structured selection from the given elements.
+ *
+ * @param elements an array of elements
+ */
+ public this(Object[] elements) {
+ this.elements = new Object[elements.length];
+ System.arraycopy(elements, 0, this.elements, 0, elements.length);
+ }
+
+ /**
+ * Creates a structured selection containing a single object.
+ * The object must not be null
.
+ *
+ * @param element the element
+ */
+ public this(Object element) {
+ Assert.isNotNull(element);
+ elements = [ element ];
+ }
+
+ /**
+ * Creates a structured selection from the given List
.
+ * @param elements list of selected elements
+ */
+ public this(SeqView!(Object) elements) {
+ Assert.isNotNull(cast(Object)elements);
+ this.elements = elements.toArray();
+ }
+
+ /**
+ * Returns whether this structured selection is equal to the given object.
+ * Two structured selections are equal if they contain the same elements
+ * in the same order.
+ *
+ * @param o the other object
+ * @return true
if they are equal, and false
otherwise
+ */
+ public bool equals(Object o) {
+ if (this is o) {
+ return true;
+ }
+ //null and other classes
+ if (!(cast(StructuredSelection)o )) {
+ return false;
+ }
+ StructuredSelection s2 = cast(StructuredSelection) o;
+
+ // either or both empty?
+ if (isEmpty()) {
+ return s2.isEmpty();
+ }
+ if (s2.isEmpty()) {
+ return false;
+ }
+
+ //size
+ int myLen = elements.length;
+ if (myLen !is s2.elements.length) {
+ return false;
+ }
+ //element comparison
+ for (int i = 0; i < myLen; i++) {
+ if (!elements[i].opEquals(s2.elements[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * Method declared in IStructuredSelection.
+ */
+ public Object getFirstElement() {
+ return isEmpty() ? null : elements[0];
+ }
+
+ /* (non-Javadoc)
+ * Method declared in ISelection.
+ */
+ public bool isEmpty() {
+ return elements is null || elements.length is 0;
+ }
+
+ /* (non-Javadoc)
+ * Method declared in IStructuredSelection.
+ */
+ public Iterator!(Object) iterator() {
+ auto res = new ArraySeq!(Object);
+ res.capacity( elements.length );
+ foreach( o; elements ){
+ res.append( o );
+ }
+ return res.elements;
+ }
+
+ /* (non-Javadoc)
+ * Method declared in IStructuredSelection.
+ */
+ public int size() {
+ return elements is null ? 0 : elements.length;
+ }
+
+ /* (non-Javadoc)
+ * Method declared in IStructuredSelection.
+ */
+ public Object[] toArray() {
+ return elements is null ? new Object[0] : elements.dup;
+ }
+
+ /* (non-Javadoc)
+ * Method declared in IStructuredSelection.
+ */
+ public SeqView!(Object) toList() {
+ auto res = new ArraySeq!(Object);
+ res.capacity( elements.length );
+ foreach( o; elements ){
+ res.append( o );
+ }
+ return res;
+ }
+
+ /**
+ * Internal method which returns a string representation of this
+ * selection suitable for debug purposes only.
+ *
+ * @return debug string
+ */
+ public String toString() {
+ return isEmpty() ? JFaceResources.getString("
+ * Any number of viewer filters can be added to this viewer (using
+ * addFilter
). When the viewer receives an update, it asks each
+ * of its filters if it is out of date, and refilters elements as required.
+ *
Object
, value type: Widget
, or Widget[]
).
+ * null
means that the element map is disabled.
+ */
+ private CustomHashtable elementMap;
+
+ /**
+ * The comparer to use for comparing elements, or null
to use
+ * the default equals
and hashCode
methods on
+ * the element itself.
+ */
+ private IElementComparer comparer;
+
+ /**
+ * This viewer's comparator used for sorting. null
means there is no comparator.
+ */
+ private ViewerComparator sorter;
+
+ /**
+ * This viewer's filters (element type: ViewerFilter
).
+ * null
means there are no filters.
+ */
+ private Seq!(ViewerFilter) filters;
+
+ /**
+ * Indicates whether a selection change is in progress on this viewer.
+ *
+ * @see #setSelection(ISelection, bool)
+ */
+ private bool inChange;
+
+ /**
+ * Used while a selection change is in progress on this viewer to indicates
+ * whether the selection should be restored.
+ *
+ * @see #setSelection(ISelection, bool)
+ */
+ private bool restoreSelection;
+
+ /**
+ * List of double-click state listeners (element type:
+ * IDoubleClickListener
).
+ *
+ * @see #fireDoubleClick
+ */
+ private ListenerList doubleClickListeners;
+
+ /**
+ * List of open listeners (element type:
+ * ISelectionActivateListener
).
+ *
+ * @see #fireOpen
+ */
+ private ListenerList openListeners;
+
+ /**
+ * List of post selection listeners (element type:
+ * ISelectionActivateListener
).
+ *
+ * @see #firePostSelectionChanged
+ */
+ private ListenerList postSelectionChangedListeners;
+
+ /**
+ * The colorAndFontCollector is an object used by viewers that
+ * support the IColorProvider, the IFontProvider and/or the
+ * IViewerLabelProvider for color and font updates.
+ * Initialize it to have no color or font providing
+ * initially.
+ * @since 3.1
+ */
+ private ColorAndFontCollector colorAndFontCollector;
+
+ /**
+ * Empty array of widgets.
+ */
+ private static Widget[] NO_WIDGETS = null;
+
+ /**
+ * The ColorAndFontCollector is a helper class for viewers
+ * that have color and font support ad optionally decorators.
+ * @see IColorDecorator
+ * @see IFontDecorator
+ * @see IColorProvider
+ * @see IFontProvider
+ * @see IDecoration
+ */
+ protected class ColorAndFontCollectorWithProviders : ColorAndFontCollector{
+
+ IColorProvider colorProvider;
+
+ IFontProvider fontProvider;
+
+ /**
+ * Create a new instance of the receiver using the supplied
+ * label provider. If it is an IColorProvider or IFontProvider
+ * set these values up.
+ * @param provider IBaseLabelProvider
+ * @see IColorProvider
+ * @see IFontProvider
+ */
+ public this(IBaseLabelProvider provider) {
+ super();
+ if ( auto cp = cast(IColorProvider) provider ) {
+ colorProvider = cp;
+ }
+ if ( auto fp = cast(IFontProvider) provider ) {
+ fontProvider = fp;
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.StructuredViewer.ColorAndFontManager#setFontsAndColors(java.lang.Object)
+ */
+ public void setFontsAndColors(Object element){
+
+ if(fontProvider !is null){
+ if(font is null) {
+ font = fontProvider.getFont(element);
+ }
+ }
+
+ if(colorProvider is null) {
+ return;
+ }
+ //Set the colors if they are not set yet
+ if(background is null) {
+ background = colorProvider.getBackground(element);
+ }
+
+ if(foreground is null) {
+ foreground = colorProvider.getForeground(element);
+ }
+ }
+
+ /**
+ * Apply the fonts and colors to the control if
+ * required.
+ * @param control
+ */
+ public void applyFontsAndColors(TableItem control) {
+
+ if(colorProvider is null){
+ if(usedDecorators){
+ //If there is no provider only apply set values
+ if(background !is null) {
+ control.setBackground(background);
+ }
+
+ if(foreground !is null) {
+ control.setForeground(foreground);
+ }
+ }
+ }
+ else{
+ //Always set the value if there is a provider
+ control.setBackground(background);
+ control.setForeground(foreground);
+ }
+
+ if(fontProvider is null){
+ if(usedDecorators && font !is null) {
+ control.setFont(font);
+ }
+ } else {
+ control.setFont(font);
+ }
+
+ clear();
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.StructuredViewer.ColorAndFontManager#applyFontsAndColors(dwt.widgets.TreeItem)
+ */
+ public void applyFontsAndColors(TreeItem control) {
+
+ if(colorProvider is null){
+ if(usedDecorators){
+ //If there is no provider only apply set values
+ if(background !is null) {
+ control.setBackground(background);
+ }
+
+ if(foreground !is null) {
+ control.setForeground(foreground);
+ }
+ }
+ }
+ else{
+ //Always set the value if there is a provider
+ control.setBackground(background);
+ control.setForeground(foreground);
+ }
+
+ if(fontProvider is null){
+ if(usedDecorators && font !is null) {
+ control.setFont(font);
+ }
+ } else {
+ control.setFont(font);
+ }
+
+ clear();
+ }
+
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.StructuredViewer.ColorAndFontManager#applyFontsAndColors(dwt.custom.TableTreeItem)
+ */
+ public void applyFontsAndColors(TableTreeItem control) {
+
+ if(colorProvider is null){
+ if(usedDecorators){
+ //If there is no provider only apply set values
+ if(background !is null) {
+ control.setBackground(background);
+ }
+
+ if(foreground !is null) {
+ control.setForeground(foreground);
+ }
+ }
+ }
+ else{
+ //Always set the value if there is a provider
+ control.setBackground(background);
+ control.setForeground(foreground);
+ }
+
+ if(fontProvider is null){
+ if(usedDecorators && font !is null) {
+ control.setFont(font);
+ }
+ } else {
+ control.setFont(font);
+ }
+
+ clear();
+ }
+
+
+ }
+
+ /**
+ * The ColorAndFontManager collects fonts and colors without a
+ * a color or font provider.
+ *
+ */
+ protected class ColorAndFontCollector {
+
+ Color foreground = null;
+
+ Color background = null;
+
+ Font font = null;
+
+ bool usedDecorators = false;
+
+ /**
+ * Create a new instance of the receiver with
+ * no color and font provider.
+ */
+ public this(){
+ }
+
+
+ /**
+ * Clear all of the results.
+ */
+ public void clear() {
+ foreground = null;
+ background = null;
+ font = null;
+ usedDecorators = false;
+ }
+
+
+ /**
+ * Set the initial fonts and colors for the element from the
+ * content providers.
+ * @param element Object
+ */
+ public void setFontsAndColors(Object element){
+ //Do nothing if there are no providers
+ }
+
+ /**
+ * Set that decorators were applied.
+ */
+ public void setUsedDecorators() {
+ this.usedDecorators = true;
+ }
+
+ /**
+ * Apply the fonts and colors to the control if
+ * required.
+ * @param control
+ */
+ public void applyFontsAndColors(TableItem control) {
+
+ if(usedDecorators){
+ //If there is no provider only apply set values
+ if(background !is null) {
+ control.setBackground(background);
+ }
+
+ if(foreground !is null) {
+ control.setForeground(foreground);
+ }
+
+ if(font !is null) {
+ control.setFont(font);
+ }
+ }
+ clear();
+ }
+
+ /**
+ * Apply the fonts and colors to the control if
+ * required.
+ * @param control
+ */
+ public void applyFontsAndColors(TreeItem control) {
+ if(usedDecorators){
+ //If there is no provider only apply set values
+ if(background !is null) {
+ control.setBackground(background);
+ }
+
+ if(foreground !is null) {
+ control.setForeground(foreground);
+ }
+
+ if(font !is null) {
+ control.setFont(font);
+ }
+ }
+ clear();
+ }
+
+ /**
+ * Apply the fonts and colors to the control if
+ * required.
+ * @param control
+ */
+ public void applyFontsAndColors(TableTreeItem control) {
+ if(usedDecorators){
+ //If there is no provider only apply set values
+ if(background !is null) {
+ control.setBackground(background);
+ }
+
+ if(foreground !is null) {
+ control.setForeground(foreground);
+ }
+
+ if(font !is null) {
+ control.setFont(font);
+ }
+ }
+ clear();
+ }
+
+ /**
+ * Set the background color.
+ * @param background
+ */
+ public void setBackground(Color background) {
+ this.background = background;
+ }
+ /**
+ * Set the font.
+ * @param font
+ */
+ public void setFont(Font font) {
+ this.font = font;
+ }
+ /**
+ * Set the foreground color.
+ * @param foreground
+ */
+ public void setForeground(Color foreground) {
+ this.foreground = foreground;
+ }
+
+
+ }
+
+ /**
+ * The safe runnable used to update an item.
+ */
+ class UpdateItemSafeRunnable : SafeRunnable {
+ private Widget widget;
+
+ private Object element;
+
+ private bool fullMap;
+
+ this(Widget widget, Object element, bool fullMap) {
+ this.widget = widget;
+ this.element = element;
+ this.fullMap = fullMap;
+ }
+
+ public void run() {
+ doUpdateItem(widget, element, fullMap);
+ }
+ }
+
+ /**
+ * Creates a structured element viewer. The viewer has no input, no content
+ * provider, a default label provider, no sorter, and no filters.
+ */
+ protected this() {
+ doubleClickListeners = new ListenerList();
+ openListeners = new ListenerList();
+ postSelectionChangedListeners = new ListenerList();
+ colorAndFontCollector = new ColorAndFontCollector();
+ // do nothing
+ }
+
+ /**
+ * Adds a listener for double-clicks in this viewer. Has no effect if an
+ * identical listener is already registered.
+ *
+ * @param listener
+ * a double-click listener
+ */
+ public void addDoubleClickListener(IDoubleClickListener listener) {
+ doubleClickListeners.add(cast(Object)listener);
+ }
+
+ /**
+ * Adds a listener for selection-open in this viewer. Has no effect if an
+ * identical listener is already registered.
+ *
+ * @param listener
+ * a double-click listener
+ */
+ public void addOpenListener(IOpenListener listener) {
+ openListeners.add(cast(Object)listener);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IPostSelectionProvider.
+ */
+ public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
+ postSelectionChangedListeners.add(cast(Object)listener);
+ }
+
+ /**
+ * Adds support for dragging items out of this viewer via a user
+ * drag-and-drop operation.
+ *
+ * @param operations
+ * a bitwise OR of the supported drag and drop operation types (
+ * DROP_COPY
,DROP_LINK
, and
+ * DROP_MOVE
)
+ * @param transferTypes
+ * the transfer types that are supported by the drag operation
+ * @param listener
+ * the callback that will be invoked to set the drag data and to
+ * cleanup after the drag and drop operation finishes
+ * @see dwt.dnd.DND
+ */
+ public void addDragSupport(int operations, Transfer[] transferTypes, DragSourceListener listener) {
+
+ Control myControl = getControl();
+ final DragSource dragSource = new DragSource(myControl, operations);
+ dragSource.setTransfer(transferTypes);
+ dragSource.addDragListener(listener);
+ }
+
+ /**
+ * Adds support for dropping items into this viewer via a user drag-and-drop
+ * operation.
+ *
+ * @param operations
+ * a bitwise OR of the supported drag and drop operation types (
+ * DROP_COPY
,DROP_LINK
, and
+ * DROP_MOVE
)
+ * @param transferTypes
+ * the transfer types that are supported by the drop operation
+ * @param listener
+ * the callback that will be invoked after the drag and drop
+ * operation finishes
+ * @see dwt.dnd.DND
+ */
+ public void addDropSupport(int operations, Transfer[] transferTypes,
+ DropTargetListener listener) {
+ Control control = getControl();
+ DropTarget dropTarget = new DropTarget(control, operations);
+ dropTarget.setTransfer(transferTypes);
+ dropTarget.addDropListener(listener);
+ }
+
+ /**
+ * Adds the given filter to this viewer, and triggers refiltering and
+ * resorting of the elements. If you want to add more than one filter
+ * consider using {@link StructuredViewer#setFilters(ViewerFilter[])}.
+ *
+ * @param filter
+ * a viewer filter
+ * @see StructuredViewer#setFilters(ViewerFilter[])
+ */
+ public void addFilter(ViewerFilter filter) {
+ if (filters is null) {
+ filters = new ArraySeq!(ViewerFilter);
+ }
+ filters.append(filter);
+ refresh();
+ }
+
+ /**
+ * Asserts that the given array of elements is itself non- null
+ * and contains no null
elements.
+ *
+ * @param elements
+ * the array to check
+ */
+ protected void assertElementsNotNull(Object[] elements) {
+// Assert.isNotNull(elements);
+ for (int i = 0, n = elements.length; i < n; ++i) {
+ Assert.isNotNull(elements[i]);
+ }
+ }
+
+ /**
+ * Associates the given element with the given widget. Sets the given item's
+ * data to be the element, and maps the element to the item in the element
+ * map (if enabled).
+ *
+ * @param element
+ * the element
+ * @param item
+ * the widget
+ */
+ protected void associate(Object element, Item item) {
+ Object data = item.getData();
+ if (data !is element) {
+ if (data !is null) {
+ disassociate(item);
+ }
+ item.setData(element);
+ }
+ // Always map the element, even if data is element,
+ // since unmapAllElements() can leave the map inconsistent
+ // See bug 2741 for details.
+ mapElement(element, item);
+ }
+
+ /**
+ * Disassociates the given DWT item from its corresponding element. Sets the
+ * item's data to null
and removes the element from the
+ * element map (if enabled).
+ *
+ * @param item
+ * the widget
+ */
+ protected void disassociate(Item item) {
+ Object element = item.getData();
+ Assert.isNotNull(element);
+ //Clear the map before we clear the data
+ unmapElement(element, item);
+ item.setData(null);
+ }
+
+ /**
+ * Returns the widget in this viewer's control which represents the given
+ * element if it is the viewer's input.
+ * + * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param element + * @return the corresponding widget, ornull
if none
+ */
+ protected abstract Widget doFindInputItem(Object element);
+
+ /**
+ * Returns the widget in this viewer's control which represent the given
+ * element. This method searches all the children of the input element.
+ * + * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param element + * @return the corresponding widget, ornull
if none
+ */
+ protected abstract Widget doFindItem(Object element);
+
+ /**
+ * Copies the attributes of the given element into the given DWT item. The
+ * element map is updated according to the value of fullMap
.
+ * If fullMap
is true
then the current mapping
+ * from element to widgets is removed and the new mapping is added. If
+ * full map is false
then only the new map gets installed.
+ * Installing only the new map is necessary in cases where only the order of
+ * elements changes but not the set of elements.
+ * + * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param item + * @param element element + * @param fullMap + *true
if mappings are added and removed, and
+ * false
if only the new map gets installed
+ */
+ protected abstract void doUpdateItem(Widget item, Object element, bool fullMap);
+
+ /**
+ * Compares two elements for equality. Uses the element comparer if one has
+ * been set, otherwise uses the default equals
method on the
+ * elements themselves.
+ *
+ * @param elementA
+ * the first element
+ * @param elementB
+ * the second element
+ * @return whether elementA is equal to elementB
+ */
+ protected int opEquals(Object elementA, Object elementB) {
+ if (comparer is null) {
+ return elementA is null ? elementB is null : elementA.opEquals(elementB);
+ } else {
+ return elementA is null ? elementB is null : comparer.opEquals(elementA, elementB);
+ }
+ }
+
+ /**
+ * Returns the result of running the given elements through the filters.
+ *
+ * @param elements
+ * the elements to filter
+ * @return only the elements which all filters accept
+ */
+ protected Object[] filter(Object[] elements) {
+ if (filters !is null) {
+ ArraySeq!(Object) filtered = new ArraySeq!(Object);
+ filtered.capacity(elements.length);
+ Object root = getRoot();
+ for (int i = 0; i < elements.length; i++) {
+ bool add = true;
+ for (int j = 0; j < filters.size(); j++) {
+ add = (cast(ViewerFilter) filters.get(j)).select(this, root, elements[i]);
+ if (!add) {
+ break;
+ }
+ }
+ if (add) {
+ filtered.append(elements[i]);
+ }
+ }
+ return filtered.toArray();
+ }
+ return elements;
+ }
+
+ /**
+ * Finds the widget which represents the given element.
+ *
+ * The default implementation of this method tries first to find the widget
+ * for the given element assuming that it is the viewer's input; this is
+ * done by calling doFindInputItem
. If it is not found
+ * there, it is looked up in the internal element map provided that this
+ * feature has been enabled. If the element map is disabled, the widget is
+ * found via doFindInputItem
.
+ *
null
if none
+ */
+ protected final Widget findItem(Object element) {
+ Widget[] result = findItems(element);
+ return result.length is 0 ? null : result[0];
+ }
+
+ /**
+ * Finds the widgets which represent the given element. The returned array
+ * must not be changed by clients; it might change upon calling other
+ * methods on this viewer.
+ *
+ * This method was introduced to support multiple equal elements in a viewer
+ * (@see {@link AbstractTreeViewer}). Multiple equal elements are only
+ * supported if the element map is enabled by calling
+ * {@link #setUseHashlookup(bool)} and passing true
.
+ *
+ * The default implementation of this method tries first to find the widget
+ * for the given element assuming that it is the viewer's input; this is
+ * done by calling doFindInputItem
. If it is not found
+ * there, the widgets are looked up in the internal element map provided
+ * that this feature has been enabled. If the element map is disabled, the
+ * widget is found via doFindInputItem
.
+ *
null
if none has been set. If specified,
+ * the viewer uses this to compare and hash elements rather
+ * than the elements' own equals and hashCode methods.
+ *
+ * @return the comparer to use for comparing elements or
+ * null
+ */
+ public IElementComparer getComparer() {
+ return comparer;
+ }
+
+ /**
+ * Returns the filtered array of children of the given element. The
+ * resulting array must not be modified, as it may come directly from the
+ * model's internal state.
+ *
+ * @param parent
+ * the parent element
+ * @return a filtered array of child elements
+ */
+ protected Object[] getFilteredChildren(Object parent) {
+ Object[] result = getRawChildren(parent);
+ if (filters !is null) {
+ foreach (f;filters) {
+ result = f.filter(this, parent, result);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns this viewer's filters.
+ *
+ * @return an array of viewer filters
+ * @see StructuredViewer#setFilters(ViewerFilter[])
+ */
+ public ViewerFilter[] getFilters() {
+ if (filters is null) {
+ return new ViewerFilter[0];
+ }
+ return filters.toArray();
+ }
+
+ /**
+ * Returns the item at the given display-relative coordinates, or
+ * null
if there is no item at that location or
+ * the underlying DWT-Control is not made up of {@link Item}
+ * (e.g {@link ListViewer})
+ *
+ * The default implementation of this method returns null
.
+ *
null
if there is no item at the given
+ * coordinates
+ * @deprecated This method is deprecated in 3.3 in favor of {@link ColumnViewer#getItemAt(dwt.graphics.Point)}.
+ * Viewers who are not subclasses of {@link ColumnViewer} should consider using a
+ * widget relative implementation like {@link ColumnViewer#getItemAt(dwt.graphics.Point)}.
+ *
+ */
+ protected Item getItem(int x, int y) {
+ return null;
+ }
+
+ /**
+ * Returns the children of the given parent without sorting and filtering
+ * them. The resulting array must not be modified, as it may come directly
+ * from the model's internal state.
+ *
+ * Returns an empty array if the given parent is null
.
+ *
+ * The default implementation of this framework method forwards to
+ * getInput
. Override if the root element is different from
+ * the viewer's input element.
+ *
null
if none
+ */
+ protected Object getRoot() {
+ return getInput();
+ }
+
+ /**
+ * The StructuredViewer
implementation of this method returns
+ * the result as an IStructuredSelection
.
+ *
+ * Subclasses do not typically override this method, but implement
+ * getSelectionFromWidget(List)
instead.
+ *
+ * @return ISelection
+ */
+ public ISelection getSelection() {
+ Control control = getControl();
+ if (control is null || control.isDisposed()) {
+ return StructuredSelection.EMPTY;
+ }
+ auto list = getSelectionFromWidget();
+ return new StructuredSelection(list);
+ }
+
+ /**
+ * Retrieves the selection, as a List
, from the underlying
+ * widget.
+ *
+ * @return the list of selected elements
+ */
+ protected abstract SeqView!(Object) getSelectionFromWidget();
+ package SeqView!(Object) getSelectionFromWidget_package(){
+ return getSelectionFromWidget();
+ }
+
+ /**
+ * Returns the sorted and filtered set of children of the given element. The
+ * resulting array must not be modified, as it may come directly from the
+ * model's internal state.
+ *
+ * @param parent
+ * the parent element
+ * @return a sorted and filtered array of child elements
+ */
+ protected Object[] getSortedChildren(Object parent) {
+ Object[] result = getFilteredChildren(parent);
+ if (sorter !is null) {
+ // be sure we're not modifying the original array from the model
+ result = result.dup;
+ sorter.sort(this, result);
+ }
+ return result;
+ }
+
+ /**
+ * Returns this viewer's sorter, or null
if it does not have
+ * one. If this viewer has a comparator that was set via
+ * setComparator(ViewerComparator)
then this method will return
+ * null
if the comparator is not an instance of ViewerSorter.
+ *
+ * It is recommended to use getComparator()
instead.
+ *
null
if none or if the comparator is
+ * not an instance of ViewerSorter
+ */
+ public ViewerSorter getSorter() {
+ if ( auto vs = cast(ViewerSorter)sorter )
+ return vs;
+ return null;
+ }
+
+ /**
+ * Return this viewer's comparator used to sort elements.
+ * This method should be used instead of getSorter()
.
+ *
+ * @return a viewer comparator, or null
if none
+ *
+ * @since 3.2
+ */
+ public ViewerComparator getComparator(){
+ return sorter;
+ }
+
+ /**
+ * Handles a double-click select event from the widget.
+ * + * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param event + * the DWT selection event + */ + protected void handleDoubleSelect(SelectionEvent event) { + // This method is reimplemented in AbstractTreeViewer to fix bug 108102. + + // handle case where an earlier selection listener disposed the control. + Control control = getControl(); + if (control !is null && !control.isDisposed()) { + // If the double-clicked element can be obtained from the event, use it + // otherwise get it from the control. Some controls like List do + // not have the notion of item. + // For details, see bug 90161 [Navigator] DefaultSelecting folders shouldn't always expand first one + ISelection selection; + if (event.item !is null && event.item.getData() !is null) { + selection = new StructuredSelection(event.item.getData()); + } + else { + selection = getSelection(); + updateSelection(selection); + } + fireDoubleClick(new DoubleClickEvent(this, selection)); + } + } + + /** + * Handles an open event from the OpenStrategy. + *+ * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param event + * the DWT selection event + */ + protected void handleOpen(SelectionEvent event) { + Control control = getControl(); + if (control !is null && !control.isDisposed()) { + ISelection selection = getSelection(); + fireOpen(new OpenEvent(this, selection)); + } + } + + /** + * Handles an invalid selection. + *
+ * This framework method is called if a model change picked up by a viewer
+ * results in an invalid selection. For instance if an element contained in
+ * the selection has been removed from the viewer, the viewer is free to
+ * either remove the element from the selection or to pick another element
+ * as its new selection. The default implementation of this method calls
+ * updateSelection
. Subclasses may override it to implement
+ * a different strategy for picking a new selection when the old selection
+ * becomes invalid.
+ *
null
if none
+ */
+ protected void handleInvalidSelection(ISelection invalidSelection, ISelection newSelection) {
+ updateSelection(newSelection);
+ SelectionChangedEvent event = new SelectionChangedEvent(this, newSelection);
+ firePostSelectionChanged(event);
+ }
+
+ /**
+ * The StructuredViewer
implementation of this
+ * ContentViewer
method calls update
if the
+ * event specifies that the label of a given element has changed, otherwise
+ * it calls super. Subclasses may reimplement or extend.
+ *
+ * @param event the event that generated this update
+ */
+ protected void handleLabelProviderChanged(LabelProviderChangedEvent event) {
+ Object[] elements = event.getElements();
+ if (elements !is null) {
+ update(elements, null);
+ } else {
+ super.handleLabelProviderChanged(event);
+ }
+ }
+ package void handleLabelProviderChanged_package(LabelProviderChangedEvent event) {
+ handleLabelProviderChanged(event);
+ }
+
+ /**
+ * Handles a select event from the widget.
+ * + * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param event + * the DWT selection event + */ + protected void handleSelect(SelectionEvent event) { + // handle case where an earlier selection listener disposed the control. + Control control = getControl(); + if (control !is null && !control.isDisposed()) { + updateSelection(getSelection()); + } + } + + /** + * Handles a post select event from the widget. + *+ * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param e the DWT selection event + */ + protected void handlePostSelect(SelectionEvent e) { + SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection()); + firePostSelectionChanged(event); + } + + /* + * (non-Javadoc) Method declared on Viewer. + */ + protected void hookControl(Control control) { + super.hookControl(control); + OpenStrategy handler = new OpenStrategy(control); + handler.addSelectionListener(new class SelectionListener { + public void widgetSelected(SelectionEvent e) { + // On Windows, selection events may happen during a refresh. + // Ignore these events if we are currently in preservingSelection(). + // See bug 184441. + if (!inChange) { + handleSelect(e); + } + } + + public void widgetDefaultSelected(SelectionEvent e) { + handleDoubleSelect(e); + } + }); + handler.addPostSelectionListener(new class SelectionAdapter { + public void widgetSelected(SelectionEvent e) { + handlePostSelect(e); + } + }); + handler.addOpenListener(new class IOpenEventListener { + public void handleOpen(SelectionEvent e) { + this.outer.handleOpen(e); + } + }); + } + + /** + * Returns whether this viewer has any filters. + * @return bool + */ + protected bool hasFilters() { + return filters !is null && filters.size() > 0; + } + + /** + * Refreshes this viewer starting at the given element. + * + * @param element + * the element + */ + protected abstract void internalRefresh(Object element); + + /** + * Refreshes this viewer starting at the given element. Labels are updated + * as described inrefresh(bool updateLabels)
.
+ *
+ * The default implementation simply calls
+ * internalRefresh(element)
, ignoring
+ * updateLabels
.
+ *
+ * If this method is overridden to do the actual refresh, then
+ * internalRefresh(Object element)
should simply call
+ * internalRefresh(element, true)
.
+ *
+ * @param element
+ * the element
+ * @param updateLabels
+ * true
to update labels for existing elements,
+ * false
to only update labels as needed, assuming
+ * that labels for existing elements are unchanged.
+ *
+ * @since 2.0
+ */
+ protected void internalRefresh(Object element, bool updateLabels) {
+ internalRefresh(element);
+ }
+
+ /**
+ * Adds the element item pair to the element map.
+ *
+ * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param element + * the element + * @param item + * the corresponding widget + */ + protected void mapElement(Object element, Widget item) { + if (elementMap !is null) { + Object widgetOrWidgets = elementMap.get(element); + if (widgetOrWidgets is null) { + elementMap.put(element, item); + } else if ( auto w = cast(Widget)widgetOrWidgets ) { + if (widgetOrWidgets !is item) { + elementMap.put(element, new ArrayWrapperObject([ cast(Object) + w, item ])); + } + } else { + Widget[] widgets = (cast(ArrayWrapperT!(Widget)) widgetOrWidgets).array; + int indexOfItem = -1; + foreach( idx, w; widgets ){ + if( w == item ){ + indexOfItem = idx; + break; + } + } + if (indexOfItem is -1) { + int length_ = widgets.length; + System.arraycopy(widgets, 0, + widgets = new Widget[length_ + 1], 0, length_); + widgets[length_] = item; + elementMap.put(element, new ArrayWrapperObject(widgets)); + } + } + } + } + + /** + * Determines whether a change to the given property of the given element + * would require refiltering and/or resorting. + *+ * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param element + * the element + * @param property + * the property + * @returntrue
if refiltering is required, and
+ * false
otherwise
+ */
+ protected bool needsRefilter(Object element, String property) {
+ if (sorter !is null && sorter.isSorterProperty(element, property)) {
+ return true;
+ }
+
+ if (filters !is null) {
+ foreach( filter; filters ){
+ if (filter.isFilterProperty(element, property)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a new hashtable using the given capacity and this viewer's element comparer.
+ *
+ * @param capacity the initial capacity of the hashtable
+ * @return a new hashtable
+ *
+ * @since 3.0
+ */
+ CustomHashtable newHashtable(int capacity) {
+ return new CustomHashtable(capacity, getComparer());
+ }
+
+ /**
+ * Attempts to preserves the current selection across a run of the given
+ * code.
+ * + * The default implementation of this method: + *
getSelection
)setSelectionToWidget
getSelection
)
+ * handleInvalidSelection
if the selection did not
+ * takepostUpdateHook
reveal
is false,
+ * or to reveal the selection if reveal
is true.
+ * + * The default implementation of this method: + *
getSelection
)setSelectionToWidget
getSelection
)
+ * handleInvalidSelection
if the selection did not
+ * takepostUpdateHook
true
if the selection should be made visible,
+ * false
if scrolling should be avoided
+ * @since 3.3
+ */
+ void preservingSelection(Runnable updateCode, bool reveal) {
+
+ ISelection oldSelection = null;
+ try {
+ // preserve selection
+ oldSelection = getSelection();
+ inChange = restoreSelection = true;
+
+ // perform the update
+ updateCode.run();
+
+ } finally {
+ inChange = false;
+
+ // restore selection
+ if (restoreSelection) {
+ setSelectionToWidget(oldSelection, reveal);
+ }
+
+ // send out notification if old and new differ
+ ISelection newSelection = getSelection();
+ if (!(cast(Object)newSelection).opEquals(cast(Object)oldSelection)) {
+ handleInvalidSelection(oldSelection, newSelection);
+ }
+ }
+ }
+
+ /*
+ * Non-Javadoc. Method declared on Viewer.
+ */
+ public void refresh() {
+ refresh(getRoot());
+ }
+
+ /**
+ * Refreshes this viewer with information freshly obtained from this
+ * viewer's model. If updateLabels
is true
+ * then labels for otherwise unaffected elements are updated as well.
+ * Otherwise, it assumes labels for existing elements are unchanged, and
+ * labels are only obtained as needed (for example, for new elements).
+ *
+ * Calling refresh(true)
has the same effect as
+ * refresh()
.
+ *
+ * Note that the implementation may still obtain labels for existing
+ * elements even if updateLabels
is false. The intent is
+ * simply to allow optimization where possible.
+ *
+ * @param updateLabels
+ * true
to update labels for existing elements,
+ * false
to only update labels as needed, assuming
+ * that labels for existing elements are unchanged.
+ *
+ * @since 2.0
+ */
+ public void refresh(bool updateLabels) {
+ refresh(getRoot(), updateLabels);
+ }
+
+ /**
+ * Refreshes this viewer starting with the given element.
+ *
+ * Unlike the update
methods, this handles structural changes
+ * to the given element (e.g. addition or removal of children). If only the
+ * given element needs updating, it is more efficient to use the
+ * update
methods.
+ *
refresh(bool updateLabels)
.
+ *
+ * Unlike the update
methods, this handles structural changes
+ * to the given element (e.g. addition or removal of children). If only the
+ * given element needs updating, it is more efficient to use the
+ * update
methods.
+ *
true
to update labels for existing elements,
+ * false
to only update labels as needed, assuming
+ * that labels for existing elements are unchanged.
+ *
+ * @since 2.0
+ */
+ public void refresh(Object element, bool updateLabels) {
+ preservingSelection(new class Runnable {
+ Object element_;
+ bool updateLabels_;
+ this(){
+ element_ = element;
+ updateLabels_ = updateLabels;
+ }
+ public void run() {
+ internalRefresh(element_, updateLabels_);
+ }
+ });
+ }
+
+ /**
+ *
+ * Refreshes the given TableItem with the given element. Calls
+ * doUpdateItem(..., false)
.
+ * + * This method is internal to the framework; subclassers should not call + * this method. + *
+ * @param widget + * the widget + * @param element + * the element + */ + protected final void refreshItem(Widget widget, Object element) { + SafeRunnable.run(new UpdateItemSafeRunnable(widget, element, true)); + } + + /** + * Removes the given open listener from this viewer. Has no affect if an + * identical listener is not registered. + * + * @param listener + * a double-click listener + */ + public void removeOpenListener(IOpenListener listener) { + openListeners.remove(cast(Object)listener); + } + + /* + * (non-Javadoc) Method declared on IPostSelectionProvider. + */ + public void removePostSelectionChangedListener(ISelectionChangedListener listener) { + postSelectionChangedListeners.remove(cast(Object)listener); + } + + /** + * Removes the given double-click listener from this viewer. Has no affect + * if an identical listener is not registered. + * + * @param listener + * a double-click listener + */ + public void removeDoubleClickListener(IDoubleClickListener listener) { + doubleClickListeners.remove(cast(Object)listener); + } + + /** + * Removes the given filter from this viewer, and triggers refiltering and + * resorting of the elements if required. Has no effect if the identical + * filter is not registered. If you want to remove more than one filter + * consider using {@link StructuredViewer#setFilters(ViewerFilter[])}. + * + * @param filter + * a viewer filter + * @see StructuredViewer#setFilters(ViewerFilter[]) + */ + public void removeFilter(ViewerFilter filter) { + Assert.isNotNull(filter); + if (filters !is null) { + // Note: can't use List.remove(Object). Use identity comparison + // instead. + int delIdx = 0; + foreach( o; filters ){ + if (o is filter) { + filters.removeAt(delIdx); + refresh(); + if (filters.size() is 0) { + filters = null; + } + return; + } + delIdx++; + } + } + } + + /** + * Sets the filters, replacing any previous filters, and triggers + * refiltering and resorting of the elements. + * + * @param filters + * an array of viewer filters + * @since 3.3 + */ + public void setFilters(ViewerFilter[] filters) { + if (filters.length is 0) { + resetFilters(); + } else { + this.filters = new ArraySeq!(ViewerFilter); + foreach( f; filters ){ + this.filters.append(f); + } + refresh(); + } + } + + /** + * Discards this viewer's filters and triggers refiltering and resorting of + * the elements. + */ + public void resetFilters() { + if (filters !is null) { + filters = null; + refresh(); + } + } + + /** + * Ensures that the given element is visible, scrolling the viewer if + * necessary. The selection is unchanged. + * + * @param element + * the element to reveal + */ + public abstract void reveal(Object element); + + /* + * (non-Javadoc) + * @see dwtx.jface.viewers.ContentViewer#setContentProvider(dwtx.jface.viewers.IContentProvider) + */ + public void setContentProvider(IContentProvider provider) { + assertContentProviderType(provider); + super.setContentProvider(provider); + } + + /** + * Assert that the content provider is of one of the + * supported types. + * @param provider + */ + protected void assertContentProviderType(IContentProvider provider) { + Assert.isTrue( null !is cast(IStructuredContentProvider)provider ); + } + + /* + * (non-Javadoc) + * @see dwtx.jface.viewers.Viewer#setInput(java.lang.Object) + */ + public final void setInput(Object input) { + + try { + // fInChange= true; + + unmapAllElements(); + + super.setInput(input); + + } finally { + // fInChange= false; + } + } + + /* + * (non-Javadoc) + * @see dwtx.jface.viewers.Viewer#setSelection(dwtx.jface.viewers.ISelection, bool) + */ + public void setSelection(ISelection selection, bool reveal) { + /** + *
+ * If the new selection differs from the current selection the hook
+ * updateSelection
is called.
+ *
+ * If setSelection
is called from within
+ * preserveSelection
, the call to
+ * updateSelection
is delayed until the end of
+ * preserveSelection
.
+ *
+ * Subclasses do not typically override this method, but implement
+ * setSelectionToWidget
instead.
+ *
+ * Subclasses should override to set their selection based on the given list + * of elements. + *
+ * + * @param l + * list of selected elements (element type:Object
)
+ * or null
if the selection is to be cleared
+ * @param reveal
+ * true
if the selection is to be made visible,
+ * and false
otherwise
+ */
+ protected abstract void setSelectionToWidget(SeqView!(Object) l, bool reveal);
+
+ /**
+ * Converts the selection to a List
and calls
+ * setSelectionToWidget(List, bool)
. The selection is
+ * expected to be an IStructuredSelection
of elements. If
+ * not, the selection is cleared.
+ *
+ * Subclasses do not typically override this method, but implement
+ * setSelectionToWidget(List, bool)
instead.
+ *
+ * @param selection
+ * an IStructuredSelection of elements
+ * @param reveal
+ * true
to reveal the first element in the
+ * selection, or false
otherwise
+ */
+ protected void setSelectionToWidget(ISelection selection, bool reveal) {
+ if ( auto ss = cast(IStructuredSelection) selection ) {
+ setSelectionToWidget(ss.toList(), reveal);
+ } else {
+ setSelectionToWidget(cast(SeqView!(Object)) null, reveal);
+ }
+ }
+
+ /**
+ * Sets this viewer's sorter and triggers refiltering and resorting of this
+ * viewer's element. Passing null
turns sorting off.
+ *
+ * It is recommended to use setComparator()
instead.
+ *
null
if none
+ */
+ public void setSorter(ViewerSorter sorter) {
+ if (this.sorter !is sorter) {
+ this.sorter = sorter;
+ refresh();
+ }
+ }
+
+ /**
+ * Sets this viewer's comparator to be used for sorting elements, and triggers refiltering and
+ * resorting of this viewer's element. null
turns sorting off.
+ * To get the viewer's comparator, call getComparator()
.
+ *
+ * IMPORTANT: This method was introduced in 3.2. If a reference to this viewer object
+ * is passed to clients who call getSorter()
, null may be returned from
+ * from that method even though the viewer is sorting its elements using the
+ * viewer's comparator.
+ *
null
if none
+ *
+ * @since 3.2
+ */
+ public void setComparator(ViewerComparator comparator){
+ if (this.sorter !is comparator){
+ this.sorter = comparator;
+ refresh();
+ }
+ }
+
+ /**
+ * Configures whether this structured viewer uses an internal hash table to
+ * speeds up the mapping between elements and DWT items. This must be called
+ * before the viewer is given an input (via setInput
).
+ *
+ * @param enable
+ * true
to enable hash lookup, and
+ * false
to disable it
+ */
+ public void setUseHashlookup(bool enable) {
+ Assert.isTrue(getInput() is null,
+ "Can only enable the hash look up before input has been set");//$NON-NLS-1$
+ if (enable) {
+ elementMap = newHashtable(CustomHashtable.DEFAULT_CAPACITY);
+ } else {
+ elementMap = null;
+ }
+ }
+
+ /**
+ * Sets the comparer to use for comparing elements, or null
+ * to use the default equals
and hashCode
+ * methods on the elements themselves.
+ *
+ * @param comparer
+ * the comparer to use for comparing elements or
+ * null
+ */
+ public void setComparer(IElementComparer comparer) {
+ this.comparer = comparer;
+ if (elementMap !is null) {
+ elementMap = new CustomHashtable(elementMap, comparer);
+ }
+ }
+
+ /**
+ * Hook for testing.
+ * @param element
+ * @return Widget
+ */
+ public Widget testFindItem(Object element) {
+ return findItem(element);
+ }
+
+ /**
+ * Hook for testing.
+ * @param element
+ * @return Widget[]
+ * @since 3.2
+ */
+ public Widget[] testFindItems(Object element) {
+ return findItems(element);
+ }
+
+ /**
+ * Removes all elements from the map.
+ * + * This method is internal to the framework; subclassers should not call + * this method. + *
+ */ + protected void unmapAllElements() { + if (elementMap !is null) { + elementMap = newHashtable(CustomHashtable.DEFAULT_CAPACITY); + } + } + + /** + * Removes the given element from the internal element to widget map. Does + * nothing if mapping is disabled. If mapping is enabled, the given element + * must be present. + *+ * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param element + * the element + */ + protected void unmapElement(Object element) { + if (elementMap !is null) { + elementMap.remove(element); + } + } + + /** + * Removes the given association from the internal element to widget map. + * Does nothing if mapping is disabled, or if the given element does not map + * to the given item. + *+ * This method is internal to the framework; subclassers should not call + * this method. + *
+ * + * @param element + * the element + * @param item the item to unmap + * @since 2.0 + */ + protected void unmapElement(Object element, Widget item) { + // double-check that the element actually maps to the given item before + // unmapping it + if (elementMap !is null) { + Object widgetOrWidgets = elementMap.get(element); + if (widgetOrWidgets is null) { + // item was not mapped, return + return; + } else if ( auto w = cast(Widget) widgetOrWidgets ) { + if (item is widgetOrWidgets) { + elementMap.remove(element); + } + } else { + Widget[] widgets = ( cast(ArrayWrapperT!(Widget)) widgetOrWidgets).array; + int indexOfItem = -1; + foreach( idx, w; widgets ){ + if( w == item ){ + indexOfItem = idx; + break; + } + } + if (indexOfItem is -1) { + return; + } + int length = widgets.length; + if (indexOfItem is 0) { + if(length is 1) { + elementMap.remove(element); + } else { + Widget[] updatedWidgets = new Widget[length - 1]; + System.arraycopy(widgets, 1, updatedWidgets, 0, length -1 ); + elementMap.put(element, new ArrayWrapperObject( updatedWidgets)); + } + } else { + Widget[] updatedWidgets = new Widget[length - 1]; + System.arraycopy(widgets, 0, updatedWidgets, 0, indexOfItem); + System.arraycopy(widgets, indexOfItem + 1, updatedWidgets, indexOfItem, length - indexOfItem - 1); + elementMap.put(element, new ArrayWrapperObject(updatedWidgets)); + } + } + } + } + + /** + * Updates the given elements' presentation when one or more of their + * properties change. Only the given elements are updated. + *
+ * This does not handle structural changes (e.g. addition or removal of
+ * elements), and does not update any other related elements (e.g. child
+ * elements). To handle structural changes, use the refresh
+ * methods instead.
+ *
+ * This should be called when an element has changed in the model, in order + * to have the viewer accurately reflect the model. This method only affects + * the viewer, not the model. + *
+ *
+ * Specifying which properties are affected may allow the viewer to optimize
+ * the update. For example, if the label provider is not affected by changes
+ * to any of these properties, an update may not actually be required.
+ * Specifying properties
as null
forces a full
+ * update of the given elements.
+ *
+ * If the viewer has a sorter which is affected by a change to one of the
+ * properties, the elements' positions are updated to maintain the sort
+ * order. Note that resorting does not happen if properties
+ * is null
.
+ *
+ * If the viewer has a filter which is affected by a change to one of the + * properties, elements may appear or disappear if the change affects + * whether or not they are filtered out. + *
+ * + * @param elements + * the elements + * @param properties + * the properties that have changed, ornull
to
+ * indicate unknown
+ */
+ public void update(Object[] elements, String[] properties) {
+ for (int i = 0; i < elements.length; ++i) {
+ update(elements[i], properties);
+ }
+ }
+
+ /**
+ * Updates the given element's presentation when one or more of its
+ * properties changes. Only the given element is updated.
+ *
+ * This does not handle structural changes (e.g. addition or removal of
+ * elements), and does not update any other related elements (e.g. child
+ * elements). To handle structural changes, use the refresh
+ * methods instead.
+ *
+ * This should be called when an element has changed in the model, in order + * to have the viewer accurately reflect the model. This method only affects + * the viewer, not the model. + *
+ *
+ * Specifying which properties are affected may allow the viewer to optimize
+ * the update. For example, if the label provider is not affected by changes
+ * to any of these properties, an update may not actually be required.
+ * Specifying properties
as null
forces a full
+ * update of the element.
+ *
+ * If the viewer has a sorter which is affected by a change to one of the
+ * properties, the element's position is updated to maintain the sort order.
+ * Note that resorting does not happen if properties
is
+ * null
.
+ *
+ * If the viewer has a filter which is affected by a change to one of the + * properties, the element may appear or disappear if the change affects + * whether or not the element is filtered out. + *
+ * + * @param element + * the element + * @param properties + * the properties that have changed, ornull
to
+ * indicate unknown
+ */
+ public void update(Object element, String[] properties) {
+ Assert.isNotNull(element);
+ Widget[] items = findItems(element);
+
+ for (int i = 0; i < items.length; i++) {
+ internalUpdate(items[i], element, properties);
+ }
+ }
+
+ /**
+ * Updates the given element's presentation when one or more of its
+ * properties changes. Only the given element is updated.
+ * + * EXPERIMENTAL. Not to be used except by JDT. + * This method was added to support JDT's explorations + * into grouping by working sets, which requires viewers to support multiple + * equal elements. See bug 76482 for more details. This support will + * likely be removed in Eclipse 3.3 in favor of proper support for + * multiple equal elements (which was implemented for AbtractTreeViewer in 3.2). + *
+ * @param widget + * the widget for the element + * @param element + * the element + * @param properties + * the properties that have changed, ornull
to
+ * indicate unknown
+ */
+ protected void internalUpdate(Widget widget, Object element, String[] properties) {
+ bool needsRefilter_ = false;
+ if (properties !is null) {
+ for (int i = 0; i < properties.length; ++i) {
+ needsRefilter_ = needsRefilter(element, properties[i]);
+ if (needsRefilter_) {
+ break;
+ }
+ }
+ }
+ if (needsRefilter_) {
+ preservingSelection(new class Runnable {
+ public void run() {
+ internalRefresh(getRoot());
+ }
+ });
+ return;
+ }
+
+ bool needsUpdate;
+ if (properties is null) {
+ needsUpdate = true;
+ } else {
+ needsUpdate = false;
+ IBaseLabelProvider labelProvider = getLabelProvider();
+ for (int i = 0; i < properties.length; ++i) {
+ needsUpdate = labelProvider.isLabelProperty(element, properties[i]);
+ if (needsUpdate) {
+ break;
+ }
+ }
+ }
+ if (needsUpdate) {
+ updateItem(widget, element);
+ }
+ }
+
+ /**
+ * Copies attributes of the given element into the given widget.
+ *
+ * This method is internal to the framework; subclassers should not call
+ * this method. Calls doUpdateItem(widget, element, true)
.
+ *
+ * This framework method should be called when the selection in the viewer + * widget changes. + *
+ *
+ * The default implementation of this method notifies all selection change
+ * listeners recorded in an internal state variable. Overriding this method
+ * is generally not required; however, if overriding in a subclass,
+ * super.updateSelection
must be invoked.
+ *
null
if none
+ */
+ protected void updateSelection(ISelection selection) {
+ SelectionChangedEvent event = new SelectionChangedEvent(this, selection);
+ fireSelectionChanged(event);
+ }
+
+ /**
+ * Returns whether this structured viewer is configured to use an internal
+ * map to speed up the mapping between elements and DWT items.
+ * + * The default implementation of this framework method checks whether the + * internal map has been initialized. + *
+ * + * @returntrue
if the element map is enabled, and
+ * false
if disabled
+ */
+ protected bool usingElementMap() {
+ return elementMap !is null;
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.ContentViewer#setLabelProvider(dwtx.jface.viewers.IBaseLabelProvider)
+ */
+ public void setLabelProvider(IBaseLabelProvider labelProvider) {
+ if ( null !is cast(IColorProvider)labelProvider || null !is cast(IFontProvider)labelProvider ) {
+ colorAndFontCollector = new ColorAndFontCollectorWithProviders(labelProvider);
+ } else {
+ colorAndFontCollector = new ColorAndFontCollector();
+ }
+ super.setLabelProvider(labelProvider);
+
+ }
+
+ /**
+ * Build a label up for the element using the supplied label provider.
+ * @param updateLabel The ViewerLabel to collect the result in
+ * @param element The element being decorated.
+ */
+ protected void buildLabel(ViewerLabel updateLabel, Object element){
+
+ if ( auto vlp = cast(IViewerLabelProvider)getLabelProvider() ) {
+ IViewerLabelProvider itemProvider = cast(IViewerLabelProvider) getLabelProvider();
+ itemProvider.updateLabel(updateLabel, element);
+
+ colorAndFontCollector.setUsedDecorators();
+
+ if(updateLabel.hasNewBackground()) {
+ colorAndFontCollector.setBackground(updateLabel.getBackground());
+ }
+
+ if(updateLabel.hasNewForeground()) {
+ colorAndFontCollector.setForeground(updateLabel.getForeground());
+ }
+
+ if(updateLabel.hasNewFont()) {
+ colorAndFontCollector.setFont(updateLabel.getFont());
+ }
+ return;
+
+ }
+
+ if( cast(ILabelProvider) getLabelProvider() ){
+ ILabelProvider labelProvider = cast(ILabelProvider) getLabelProvider();
+ updateLabel.setText(labelProvider.getText(element));
+ updateLabel.setImage(labelProvider.getImage(element));
+ }
+
+ }
+
+ /**
+ * Build a label up for the element using the supplied label provider.
+ * @param updateLabel The ViewerLabel to collect the result in
+ * @param element The element being decorated.
+ * @param labelProvider ILabelProvider the labelProvider for the receiver.
+ */
+ void buildLabel(ViewerLabel updateLabel, Object element, IViewerLabelProvider labelProvider){
+
+ labelProvider.updateLabel(updateLabel, element);
+
+ colorAndFontCollector.setUsedDecorators();
+
+ if(updateLabel.hasNewBackground()) {
+ colorAndFontCollector.setBackground(updateLabel.getBackground());
+ }
+
+ if(updateLabel.hasNewForeground()) {
+ colorAndFontCollector.setForeground(updateLabel.getForeground());
+ }
+
+ if(updateLabel.hasNewFont()) {
+ colorAndFontCollector.setFont(updateLabel.getFont());
+ }
+
+ }
+
+ /**
+ * Build a label up for the element using the supplied label provider.
+ * @param updateLabel The ViewerLabel to collect the result in
+ * @param elementPath The path of the element being decorated.
+ * @param labelProvider ILabelProvider the labelProvider for the receiver.
+ */
+ void buildLabel(ViewerLabel updateLabel, TreePath elementPath,ITreePathLabelProvider labelProvider){
+
+ labelProvider.updateLabel(updateLabel, elementPath);
+
+ colorAndFontCollector.setUsedDecorators();
+
+ if(updateLabel.hasNewBackground()) {
+ colorAndFontCollector.setBackground(updateLabel.getBackground());
+ }
+
+ if(updateLabel.hasNewForeground()) {
+ colorAndFontCollector.setForeground(updateLabel.getForeground());
+ }
+
+ if(updateLabel.hasNewFont()) {
+ colorAndFontCollector.setFont(updateLabel.getFont());
+ }
+
+ }
+
+ /**
+ * Build a label up for the element using the supplied label provider.
+ * @param updateLabel The ViewerLabel to collect the result in
+ * @param element The element being decorated.
+ * @param labelProvider ILabelProvider the labelProvider for the receiver.
+ */
+ void buildLabel(ViewerLabel updateLabel, Object element,ILabelProvider labelProvider){
+ updateLabel.setText(labelProvider.getText(element));
+ updateLabel.setImage(labelProvider.getImage(element));
+ }
+
+ /**
+ * Get the ColorAndFontCollector for the receiver.
+ * @return ColorAndFontCollector
+ * @since 3.1
+ */
+ protected ColorAndFontCollector getColorAndFontCollector() {
+ return colorAndFontCollector;
+ }
+
+ protected void handleDispose(DisposeEvent event) {
+ super.handleDispose(event);
+ sorter = null;
+ comparer = null;
+ if (filters !is null)
+ filters.clear();
+ elementMap = newHashtable(1);
+ openListeners.clear();
+ doubleClickListeners.clear();
+ colorAndFontCollector.clear();
+ postSelectionChangedListeners.clear();
+ }
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TableColumnViewerLabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TableColumnViewerLabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Shindl addColumnData
to add columns.
+ * The TableLayout {@link ColumnLayoutData} is only valid until the table
+ * is resized. To keep the proportions constant when the table is resized
+ * see {@link TableColumnLayout}
+ */
+public class TableLayout : Layout {
+
+ /**
+ * The number of extra pixels taken as horizontal trim by the table column.
+ * To ensure there are N pixels available for the content of the column,
+ * assign N+COLUMN_TRIM for the column width.
+ *
+ * @since 3.1
+ */
+ private static const int COLUMN_TRIM;
+ static this(){
+ COLUMN_TRIM = "carbon".equals(DWT.getPlatform()) ? 24 : 3; //$NON-NLS-1$
+ }
+
+ /**
+ * The list of column layout data (element type:
+ * ColumnLayoutData
).
+ */
+ private Seq!(ColumnLayoutData) columns;
+
+ /**
+ * Indicates whether layout
has yet to be called.
+ */
+ private bool firstTime = true;
+
+ /**
+ * Creates a new table layout.
+ */
+ public this() {
+ columns = new ArraySeq!(ColumnLayoutData);
+ }
+
+ /**
+ * Adds a new column of data to this table layout.
+ *
+ * @param data
+ * the column layout data
+ */
+ public void addColumnData(ColumnLayoutData data) {
+ columns.append(data);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Layout.
+ */
+ public Point computeSize(Composite c, int wHint, int hHint, bool flush) {
+ if (wHint !is DWT.DEFAULT && hHint !is DWT.DEFAULT) {
+ return new Point(wHint, hHint);
+ }
+
+ Table table = cast(Table) c;
+ // To avoid recursions.
+ table.setLayout(null);
+ // Use native layout algorithm
+ Point result = table.computeSize(wHint, hHint, flush);
+ table.setLayout(this);
+
+ int width = 0;
+ int size = columns.size();
+ foreach( layoutData; columns ){
+ if ( auto col = cast(ColumnPixelData) layoutData ) {
+ width += col.width;
+ if (col.addTrim) {
+ width += COLUMN_TRIM;
+ }
+ } else if ( auto col = cast(ColumnWeightData) layoutData ) {
+ width += col.minimumWidth;
+ } else {
+ Assert.isTrue(false, "Unknown column layout data");//$NON-NLS-1$
+ }
+ }
+ if (width > result.x) {
+ result.x = width;
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Layout.
+ */
+ public void layout(Composite c, bool flush) {
+ // Only do initial layout. Trying to maintain proportions when resizing
+ // is too hard,
+ // causes lots of widget flicker, causes scroll bars to appear and
+ // occasionally stick around (on Windows),
+ // requires hooking column resizing as well, and may not be what the
+ // user wants anyway.
+ if (!firstTime) {
+ return;
+ }
+
+ int width = c.getClientArea().width;
+
+ // XXX: Layout is being called with an invalid value the first time
+ // it is being called on Linux. This method resets the
+ // Layout to null so we make sure we run it only when
+ // the value is OK.
+ if (width <= 1) {
+ return;
+ }
+
+ Item[] tableColumns = getColumns(c);
+ int size = Math.min(columns.size(), tableColumns.length);
+ int[] widths = new int[size];
+ int fixedWidth = 0;
+ int numberOfWeightColumns = 0;
+ int totalWeight = 0;
+
+ // First calc space occupied by fixed columns
+ for (int i = 0; i < size; i++) {
+ ColumnLayoutData col = /+cast(ColumnLayoutData)+/ columns.get(i);
+ if ( auto cpd = cast(ColumnPixelData) col ) {
+ int pixels = cpd.width;
+ if (cpd.addTrim) {
+ pixels += COLUMN_TRIM;
+ }
+ widths[i] = pixels;
+ fixedWidth += pixels;
+ } else if ( auto cw = cast(ColumnWeightData) col ) {
+ numberOfWeightColumns++;
+ // first time, use the weight specified by the column data,
+ // otherwise use the actual width as the weight
+ // int weight = firstTime ? cw.weight :
+ // tableColumns[i].getWidth();
+ int weight = cw.weight;
+ totalWeight += weight;
+ } else {
+ Assert.isTrue(false, "Unknown column layout data");//$NON-NLS-1$
+ }
+ }
+
+ // Do we have columns that have a weight
+ if (numberOfWeightColumns > 0) {
+ // Now distribute the rest to the columns with weight.
+ int rest = width - fixedWidth;
+ int totalDistributed = 0;
+ for (int i = 0; i < size; ++i) {
+ ColumnLayoutData col = /+cast(ColumnLayoutData)+/ columns.get(i);
+ if (auto cw = cast(ColumnWeightData) col ) {
+ // calculate weight as above
+ // int weight = firstTime ? cw.weight :
+ // tableColumns[i].getWidth();
+ int weight = cw.weight;
+ int pixels = totalWeight is 0 ? 0 : weight * rest
+ / totalWeight;
+ if (pixels < cw.minimumWidth) {
+ pixels = cw.minimumWidth;
+ }
+ totalDistributed += pixels;
+ widths[i] = pixels;
+ }
+ }
+
+ // Distribute any remaining pixels to columns with weight.
+ int diff = rest - totalDistributed;
+ for (int i = 0; diff > 0; ++i) {
+ if (i is size) {
+ i = 0;
+ }
+ ColumnLayoutData col = /+cast(ColumnLayoutData)+/ columns.get(i);
+ if (cast(ColumnWeightData)col ) {
+ ++widths[i];
+ --diff;
+ }
+ }
+ }
+
+ firstTime = false;
+
+ for (int i = 0; i < size; i++) {
+ setWidth(tableColumns[i], widths[i]);
+ }
+ }
+
+ /**
+ * Set the width of the item.
+ *
+ * @param item
+ * @param width
+ */
+ private void setWidth(Item item, int width) {
+ if ( cast(TreeColumn)item ) {
+ (cast(TreeColumn) item).setWidth(width);
+ } else {
+ (cast(TableColumn) item).setWidth(width);
+ }
+
+ }
+
+ /**
+ * Return the columns for the receiver.
+ *
+ * @param composite
+ * @return Item[]
+ */
+ private Item[] getColumns(Composite composite) {
+ if (cast(Tree)composite ) {
+ return (cast(Tree) composite).getColumns();
+ }
+ return (cast(Table) composite).getColumns();
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TableTreeViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TableTreeViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,882 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl TableTree
control.
+ * + * This class is not intended to be subclassed outside the viewer framework. It + * is designed to be instantiated with a pre-existing DWT table tree control and + * configured with a domain-specific content provider, label provider, element + * filter (optional), and element sorter (optional). + *
+ *
+ * Content providers for table tree viewers must implement the
+ * ITreeContentProvider
interface.
+ *
+ * Label providers for table tree viewers must implement either the
+ * ITableLabelProvider
or the ILabelProvider
+ * interface (see TableTreeViewer.setLabelProvider
for more
+ * details).
+ *
TableViewerImpl
viewer
+ *
+ * @return the viewer
+ */
+ public ColumnViewer getViewer() {
+ return viewer;
+ }
+
+ private void activateCellEditor() {
+ if( cellEditors !is null ) {
+ if( cellEditors[columnNumber] !is null && cellModifier !is null ) {
+ Object element = tableItem.getData();
+ String property = columnProperties[columnNumber];
+
+ if( cellModifier.canModify(element, property) ) {
+ cellEditor = cellEditors[columnNumber];
+
+ cellEditor.addListener(cellEditorListener);
+
+ Object value = cellModifier.getValue(element, property);
+ cellEditor.setValue(value);
+ // Tricky flow of control here:
+ // activate() can trigger callback to cellEditorListener
+ // which will clear cellEditor
+ // so must get control first, but must still call activate()
+ // even if there is no control.
+ final Control control = cellEditor.getControl();
+ cellEditor.activate();
+ if (control is null) {
+ return;
+ }
+ setLayoutData(cellEditor.getLayoutData());
+ setEditor(control, tableItem, columnNumber);
+ cellEditor.setFocus();
+ if (focusListener is null) {
+ focusListener = new class FocusAdapter {
+ public void focusLost(FocusEvent e) {
+ applyEditorValue();
+ }
+ };
+ }
+ control.addFocusListener(focusListener);
+ mouseListener = new class MouseAdapter {
+ Control control_;
+ this(){
+ control_=control;
+ }
+ public void mouseDown(MouseEvent e) {
+ // time wrap?
+ // check for expiration of doubleClickTime
+ if (e.time <= doubleClickExpirationTime) {
+ control_.removeMouseListener(mouseListener);
+ cancelEditing();
+ handleDoubleClickEvent();
+ } else if (mouseListener !is null) {
+ control_.removeMouseListener(mouseListener);
+ }
+ }
+ };
+ control.addMouseListener(mouseListener);
+ }
+ }
+ }
+ }
+
+ /**
+ * Activate a cell editor for the given mouse position.
+ */
+ private void activateCellEditor(MouseEvent event) {
+ if (tableItem is null || tableItem.isDisposed()) {
+ // item no longer exists
+ return;
+ }
+ int columnToEdit;
+ int columns = getColumnCount();
+ if (columns is 0) {
+ // If no TableColumn, Table acts as if it has a single column
+ // which takes the whole width.
+ columnToEdit = 0;
+ } else {
+ columnToEdit = -1;
+ for (int i = 0; i < columns; i++) {
+ Rectangle bounds = getBounds(tableItem, i);
+ if (bounds.contains(event.x, event.y)) {
+ columnToEdit = i;
+ break;
+ }
+ }
+ if (columnToEdit is -1) {
+ return;
+ }
+ }
+
+ columnNumber = columnToEdit;
+ activateCellEditor();
+ }
+
+ /**
+ * Deactivates the currently active cell editor.
+ */
+ public void applyEditorValue() {
+ CellEditor c = this.cellEditor;
+ if (c !is null) {
+ // null out cell editor before calling save
+ // in case save results in applyEditorValue being re-entered
+ // see 1GAHI8Z: ITPUI:ALL - How to code event notification when
+ // using cell editor ?
+ this.cellEditor = null;
+ Item t = this.tableItem;
+ // don't null out table item -- same item is still selected
+ if (t !is null && !t.isDisposed()) {
+ saveEditorValue(c, t);
+ }
+ setEditor(null, null, 0);
+ c.removeListener(cellEditorListener);
+ Control control = c.getControl();
+ if (control !is null) {
+ if (mouseListener !is null) {
+ control.removeMouseListener(mouseListener);
+ }
+ if (focusListener !is null) {
+ control.removeFocusListener(focusListener);
+ }
+ }
+ c.deactivate();
+ }
+ }
+
+ /**
+ * Cancels the active cell editor, without saving the value back to the
+ * domain model.
+ */
+ public void cancelEditing() {
+ if (cellEditor !is null) {
+ setEditor(null, null, 0);
+ cellEditor.removeListener(cellEditorListener);
+ CellEditor oldEditor = cellEditor;
+ cellEditor = null;
+ oldEditor.deactivate();
+ }
+ }
+
+ /**
+ * Start editing the given element.
+ *
+ * @param element
+ * @param column
+ */
+ public void editElement(Object element, int column) {
+ if (cellEditor !is null) {
+ applyEditorValue();
+ }
+
+ setSelection(new StructuredSelection(element), true);
+ Item[] selection = getSelection();
+ if (selection.length !is 1) {
+ return;
+ }
+
+ tableItem = selection[0];
+
+ // Make sure selection is visible
+ showSelection();
+ columnNumber = column;
+ activateCellEditor();
+
+ }
+
+ /**
+ * Return the array of CellEditors used in the viewer
+ *
+ * @return the cell editors
+ */
+ public CellEditor[] getCellEditors() {
+ return cellEditors;
+ }
+
+ /**
+ * Get the cell modifier
+ *
+ * @return the cell modifier
+ */
+ public ICellModifier getCellModifier() {
+ return cellModifier;
+ }
+
+ /**
+ * Return the properties for the column
+ *
+ * @return the array of column properties
+ */
+ public Object[] getColumnProperties() {
+ Object[] res;
+ foreach( str; columnProperties ){
+ res ~= new ArrayWrapperString( str );
+ }
+ return res;
+ }
+
+ /**
+ * Handles the mouse down event; activates the cell editor.
+ *
+ * @param event
+ * the mouse event that should be handled
+ */
+ public void handleMouseDown(MouseEvent event) {
+ if (event.button !is 1) {
+ return;
+ }
+
+ if (cellEditor !is null) {
+ applyEditorValue();
+ }
+
+ // activate the cell editor immediately. If a second mouseDown
+ // is received prior to the expiration of the doubleClick time then
+ // the cell editor will be deactivated and a doubleClick event will
+ // be processed.
+ //
+ doubleClickExpirationTime = event.time
+ + Display.getCurrent().getDoubleClickTime();
+
+ Item[] items = getSelection();
+ // Do not edit if more than one row is selected.
+ if (items.length !is 1) {
+ tableItem = null;
+ return;
+ }
+ tableItem = items[0];
+
+ activateCellEditor(event);
+ }
+
+ private void initCellEditorListener() {
+ cellEditorListener = new class ICellEditorListener {
+ public void editorValueChanged(bool oldValidState,
+ bool newValidState) {
+ // Ignore.
+ }
+
+ public void cancelEditor() {
+ this.outer.cancelEditing();
+ }
+
+ public void applyEditorValue() {
+ this.outer.applyEditorValue();
+ }
+ };
+ }
+
+ /**
+ * Return whether there is an active cell editor.
+ *
+ * @return true
if there is an active cell editor;
+ * otherwise false
is returned.
+ */
+ public bool isCellEditorActive() {
+ return cellEditor !is null;
+ }
+
+ /**
+ * Saves the value of the currently active cell editor, by delegating to
+ * the cell modifier.
+ */
+ private void saveEditorValue(CellEditor cellEditor, Item tableItem) {
+ if( cellModifier !is null ) {
+ if( ! cellEditor.isValueValid() ) {
+ // Do what????
+ }
+ }
+ String property = null;
+
+ if( columnProperties !is null && columnNumber < columnProperties.length ) {
+ property = columnProperties[columnNumber];
+ }
+ cellModifier.modify(tableItem, property, cellEditor.getValue());
+ }
+
+ /**
+ * Set the cell editors
+ *
+ * @param editors
+ */
+ public void setCellEditors(CellEditor[] editors) {
+ this.cellEditors = editors;
+ }
+
+ /**
+ * Set the cell modifier
+ *
+ * @param modifier
+ */
+ public void setCellModifier(ICellModifier modifier) {
+ this.cellModifier = modifier;
+ }
+
+ /**
+ * Set the column properties
+ *
+ * @param columnProperties
+ */
+ public void setColumnProperties(String[] columnProperties) {
+ this.columnProperties = columnProperties;
+ }
+
+ Rectangle getBounds(Item item, int columnNumber) {
+ return (cast(TableTreeItem) item).getBounds(columnNumber);
+ }
+
+ int getColumnCount() {
+ // getColumnCount() should be a API in TableTree.
+ return getTableTree().getTable().getColumnCount();
+ }
+
+ Item[] getSelection() {
+ return getTableTree().getSelection();
+ }
+
+ void setEditor(Control w, Item item, int columnNumber) {
+ tableTreeEditor.setEditor(w, cast(TableTreeItem) item, columnNumber);
+ }
+
+ void setSelection(StructuredSelection selection, bool b) {
+ this.outer.setSelection(selection, b);
+ }
+
+ void showSelection() {
+ getTableTree().showSelection();
+ }
+
+ void setLayoutData(CellEditor.LayoutData layoutData) {
+ tableTreeEditor.horizontalAlignment = layoutData.horizontalAlignment;
+ tableTreeEditor.grabHorizontal = layoutData.grabHorizontal;
+ tableTreeEditor.minimumWidth = layoutData.minimumWidth;
+ }
+
+ void handleDoubleClickEvent() {
+ Viewer viewer = getViewer();
+ fireDoubleClick(new DoubleClickEvent(viewer, viewer.getSelection()));
+ fireOpen(new OpenEvent(viewer, viewer.getSelection()));
+ }
+ }
+
+ /**
+ * Creates a table tree viewer on the given table tree control. The viewer
+ * has no input, no content provider, a default label provider, no sorter,
+ * and no filters.
+ *
+ * @param tree
+ * the table tree control
+ */
+ public this(TableTree tree) {
+ super();
+ tableTree = tree;
+ hookControl(tree);
+ tableTreeEditor = new TableTreeEditor(tableTree);
+ tableEditorImpl = new TableTreeEditorImpl(this);
+ }
+
+ /**
+ * Creates a table tree viewer on a newly-created table tree control under
+ * the given parent. The table tree control is created using the DWT style
+ * bits MULTI, H_SCROLL, V_SCROLL, and BORDER
. The viewer
+ * has no input, no content provider, a default label provider, no sorter,
+ * and no filters.
+ *
+ * @param parent
+ * the parent control
+ */
+ public this(Composite parent) {
+ this(parent, DWT.MULTI | DWT.H_SCROLL | DWT.V_SCROLL | DWT.BORDER);
+ }
+
+ /**
+ * Creates a table tree viewer on a newly-created table tree control under
+ * the given parent. The table tree control is created using the given DWT
+ * style bits. The viewer has no input, no content provider, a default label
+ * provider, no sorter, and no filters.
+ *
+ * @param parent
+ * the parent control
+ * @param style
+ * the DWT style bits
+ */
+ public this(Composite parent, int style) {
+ this(new TableTree(parent, style));
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected void addTreeListener(Control c, TreeListener listener) {
+ (cast(TableTree) c).addTreeListener(listener);
+ }
+
+ /**
+ * Cancels a currently active cell editor. All changes already done in the
+ * cell editor are lost.
+ */
+ public void cancelEditing() {
+ tableEditorImpl.cancelEditing();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected void doUpdateItem(Item item, Object element) {
+ // update icon and label
+ // Similar code in TableTreeViewer.doUpdateItem()
+ IBaseLabelProvider prov = getLabelProvider();
+ ITableLabelProvider tprov = null;
+
+ if ( auto t = cast(ITableLabelProvider) prov ) {
+ tprov = t;
+ }
+
+ int columnCount = tableTree.getTable().getColumnCount();
+ TableTreeItem ti = cast(TableTreeItem) item;
+ // Also enter loop if no columns added. See 1G9WWGZ: JFUIF:WINNT -
+ // TableViewer with 0 columns does not work
+ for (int column = 0; column < columnCount || column is 0; column++) {
+ String text = "";//$NON-NLS-1$
+ Image image = null;
+ if (tprov !is null) {
+ text = tprov.getColumnText(element, column);
+ image = tprov.getColumnImage(element, column);
+ } else {
+ if (column is 0) {
+ ViewerLabel updateLabel = new ViewerLabel(item.getText(),
+ item.getImage());
+ buildLabel(updateLabel, element);
+
+ // As it is possible for user code to run the event
+ // loop check here.
+ if (item.isDisposed()) {
+ unmapElement(element, item);
+ return;
+ }
+
+ text = updateLabel.getText();
+ image = updateLabel.getImage();
+ }
+ }
+
+ // Avoid setting text to null
+ if (text is null) {
+ text = ""; //$NON-NLS-1$
+ }
+
+ ti.setText(column, text);
+ // Apparently a problem to setImage to null if already null
+ if (ti.getImage(column) !is image) {
+ ti.setImage(column, image);
+ }
+
+ getColorAndFontCollector().setFontsAndColors(element);
+ getColorAndFontCollector().applyFontsAndColors(ti);
+ }
+
+ }
+
+ /**
+ * Starts editing the given element.
+ *
+ * @param element
+ * the element
+ * @param column
+ * the column number
+ */
+ public void editElement(Object element, int column) {
+ tableEditorImpl.editElement(element, column);
+ }
+
+ /**
+ * Returns the cell editors of this viewer.
+ *
+ * @return the list of cell editors
+ */
+ public CellEditor[] getCellEditors() {
+ return tableEditorImpl.getCellEditors();
+ }
+
+ /**
+ * Returns the cell modifier of this viewer.
+ *
+ * @return the cell modifier
+ */
+ public ICellModifier getCellModifier() {
+ return tableEditorImpl.getCellModifier();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected Item[] getChildren(Widget o) {
+ if (auto i = cast(TableTreeItem) o ) {
+ return i.getItems();
+ }
+ if (auto i = cast(TableTree) o ) {
+ return i.getItems();
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.AbstractTreeViewer#getChild(dwt.widgets.Widget,
+ * int)
+ */
+ protected Item getChild(Widget widget, int index) {
+ if (auto w = cast(TableTreeItem) widget ) {
+ return w.getItem(index);
+ }
+ if (auto w = cast(TableTree) widget ) {
+ return w.getItem(index);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the column properties of this viewer. The properties must
+ * correspond with the columns of the table control. They are used to
+ * identify the column in a cell modifier.
+ *
+ * @return the list of column properties
+ */
+ public Object[] getColumnProperties() {
+ return tableEditorImpl.getColumnProperties();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Viewer.
+ */
+ public Control getControl() {
+ return tableTree;
+ }
+
+ /**
+ * Returns the element with the given index from this viewer. Returns
+ * null
if the index is out of range.
+ * + * This method is internal to the framework. + *
+ * + * @param index + * the zero-based index + * @return the element at the given index, ornull
if the
+ * index is out of range
+ */
+ public Object getElementAt(int index) {
+ // XXX: Workaround for 1GBCSB1: DWT:WIN2000 - TableTree should have
+ // getItem(int index)
+ TableTreeItem i = tableTree.getItems()[index];
+ if (i !is null) {
+ return i.getData();
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected bool getExpanded(Item item) {
+ return (cast(TableTreeItem) item).getExpanded();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.ColumnViewer#getItemAt(dwt.graphics.Point)
+ */
+ protected Item getItemAt(Point p) {
+ return getTableTree().getTable().getItem(p);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected int getItemCount(Control widget) {
+ return (cast(TableTree) widget).getItemCount();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected int getItemCount(Item item) {
+ return (cast(TableTreeItem) item).getItemCount();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected dwt.widgets.Item.Item[] getItems(
+ dwt.widgets.Item.Item item) {
+ return (cast(TableTreeItem) item).getItems();
+ }
+
+ /**
+ * The table tree viewer implementation of this Viewer
+ * framework method returns the label provider, which in the case of table
+ * tree viewers will be an instance of either
+ * ITableLabelProvider
or ILabelProvider
. If
+ * it is an ITableLabelProvider
, then it provides a separate
+ * label text and image for each column. If it is an
+ * ILabelProvider
, then it provides only the label text and
+ * image for the first column, and any remaining columns are blank.
+ */
+ public IBaseLabelProvider getLabelProvider() {
+ return super.getLabelProvider();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected Item getParentItem(Item item) {
+ return (cast(TableTreeItem) item).getParentItem();
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected Item[] getSelection(Control widget) {
+ return (cast(TableTree) widget).getSelection();
+ }
+
+ /**
+ * Returns this table tree viewer's table tree control.
+ *
+ * @return the table tree control
+ */
+ public TableTree getTableTree() {
+ return tableTree;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on AbstractTreeViewer.
+ */
+ protected void hookControl(Control control) {
+ super.hookControl(control);
+ tableTree.getTable().addMouseListener(new class MouseAdapter {
+ public void mouseDown(MouseEvent e) {
+ /*
+ * If user clicked on the [+] or [-], do not activate
+ * CellEditor.
+ */
+ // XXX: This code should not be here. DWT should either have
+ // support to see
+ // if the user clicked on the [+]/[-] or manage the table editor
+ // activation
+ dwt.widgets.TableItem.TableItem[] items = tableTree
+ .getTable().getItems();
+ for (int i = 0; i < items.length; i++) {
+ Rectangle rect = items[i].getImageBounds(0);
+ if (rect.contains(e.x, e.y)) {
+ return;
+ }
+ }
+
+ tableEditorImpl.handleMouseDown(e);
+ }
+ });
+ }
+
+ /**
+ * Returns whether there is an active cell editor.
+ *
+ * @return true
if there is an active cell editor, and
+ * false
otherwise
+ */
+ public bool isCellEditorActive() {
+ return tableEditorImpl.isCellEditorActive();
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected Item newItem(Widget parent, int flags, int ix) {
+ TableTreeItem item;
+ if (ix >= 0) {
+ if (cast(TableTreeItem) parent ) {
+ item = new TableTreeItem(cast(TableTreeItem) parent, flags, ix);
+ } else {
+ item = new TableTreeItem(cast(TableTree) parent, flags, ix);
+ }
+ } else {
+ if (cast(TableTreeItem)parent ) {
+ item = new TableTreeItem(cast(TableTreeItem) parent, flags);
+ } else {
+ item = new TableTreeItem(cast(TableTree) parent, flags);
+ }
+ }
+ return item;
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void removeAll(Control widget) {
+ (cast(TableTree) widget).removeAll();
+ }
+
+ /**
+ * Sets the cell editors of this table viewer.
+ *
+ * @param editors
+ * the list of cell editors
+ */
+ public void setCellEditors(CellEditor[] editors) {
+ tableEditorImpl.setCellEditors(editors);
+ }
+
+ /**
+ * Sets the cell modifier of this table viewer.
+ *
+ * @param modifier
+ * the cell modifier
+ */
+ public void setCellModifier(ICellModifier modifier) {
+ tableEditorImpl.setCellModifier(modifier);
+ }
+
+ /**
+ * Sets the column properties of this table viewer. The properties must
+ * correspond with the columns of the table control. They are used to
+ * identify the column in a cell modifier.
+ *
+ * @param columnProperties
+ * the list of column properties
+ */
+ public void setColumnProperties(String[] columnProperties) {
+ tableEditorImpl.setColumnProperties(columnProperties);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void setExpanded(Item node, bool expand) {
+ (cast(TableTreeItem) node).setExpanded(expand);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void setSelection(SeqView!(Item) items) {
+ getTableTree().setSelection(cast(TableTreeItem[]) items.toArray);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void showItem(Item item) {
+ getTableTree().showItem(cast(TableTreeItem) item);
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TableViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TableViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl Table
control.
+ * + * This class is not intended to be subclassed outside the viewer framework. It + * is designed to be instantiated with a pre-existing DWT table control and + * configured with a domain-specific content provider, table label provider, + * element filter (optional), and element sorter (optional). + *
+ *
+ * Label providers for table viewers must implement either the
+ * ITableLabelProvider
or the ILabelProvider
+ * interface (see TableViewer.setLabelProvider
for more details).
+ *
+ * As of 3.1 the TableViewer now supports the DWT.VIRTUAL flag. If the + * underlying table is DWT.VIRTUAL, the content provider may implement + * {@link ILazyContentProvider} instead of {@link IStructuredContentProvider}. + * Note that in this case, the viewer does not support sorting or filtering. + * Also note that in this case, the Widget based APIs may return null if the + * element is not specified or not created yet. + *
+ *+ * Users of DWT.VIRTUAL should also avoid using getItems() from the Table within + * the TreeViewer as this does not necessarily generate a callback for the + * TreeViewer to populate the items. It also has the side effect of creating all + * of the items thereby eliminating the performance improvements of DWT.VIRTUAL. + *
+ * + * @see DWT#VIRTUAL + * @see #doFindItem(Object) + * @see #internalRefresh(Object, bool) + */ +public class TableViewer : AbstractTableViewer { + + public alias AbstractTableViewer.preservingSelection preservingSelection; + + /** + * This viewer's table control. + */ + private Table table; + + /** + * The cached row which is reused all over + */ + private TableViewerRow cachedRow; + + /** + * Creates a table viewer on a newly-created table control under the given + * parent. The table control is created using the DWT style bits + *MULTI, H_SCROLL, V_SCROLL,
and BORDER
. The
+ * viewer has no input, no content provider, a default label provider, no
+ * sorter, and no filters. The table has no columns.
+ *
+ * @param parent
+ * the parent control
+ */
+ public this(Composite parent) {
+ this(parent, DWT.MULTI | DWT.H_SCROLL | DWT.V_SCROLL | DWT.BORDER);
+ }
+
+ /**
+ * Creates a table viewer on a newly-created table control under the given
+ * parent. The table control is created using the given style bits. The
+ * viewer has no input, no content provider, a default label provider, no
+ * sorter, and no filters. The table has no columns.
+ *
+ * @param parent
+ * the parent control
+ * @param style
+ * DWT style bits
+ */
+ public this(Composite parent, int style) {
+ this(new Table(parent, style));
+ }
+
+ /**
+ * Creates a table viewer on the given table control. The viewer has no
+ * input, no content provider, a default label provider, no sorter, and no
+ * filters.
+ *
+ * @param table
+ * the table control
+ */
+ public this(Table table) {
+ this.table = table;
+ hookControl(table);
+ }
+
+ public Control getControl() {
+ return table;
+ }
+
+ /**
+ * Returns this table viewer's table control.
+ *
+ * @return the table control
+ */
+ public Table getTable() {
+ return table;
+ }
+
+ protected ColumnViewerEditor createViewerEditor() {
+ return new TableViewerEditor(this,null,new ColumnViewerEditorActivationStrategy(this),ColumnViewerEditor.DEFAULT);
+ }
+
+ /**
+ * + * Sets a new selection for this viewer and optionally makes it visible. The + * TableViewer implementation of this method is inefficient for the + * ILazyContentProvider as lookup is done by indices rather than elements + * and may require population of the entire table in worse case. + *
+ *+ * Use Table#setSelection(int[] indices) and Table#showSelection() if you + * wish to set selection more efficiently when using a ILazyContentProvider. + *
+ * + * @param selection + * the new selection + * @param reveal + *true
if the selection is to be made visible,
+ * and false
otherwise
+ * @see Table#setSelection(int[])
+ * @see Table#showSelection()
+ */
+ public void setSelection(ISelection selection, bool reveal) {
+ super.setSelection(selection, reveal);
+ }
+
+ protected ViewerRow getViewerRowFromItem(Widget item) {
+ if( cachedRow is null ) {
+ cachedRow = new TableViewerRow(cast(TableItem) item);
+ } else {
+ cachedRow.setItem(cast(TableItem) item);
+ }
+
+ return cachedRow;
+ }
+
+ /**
+ * Create a new row with style at index
+ *
+ * @param style
+ * @param rowIndex
+ * @return ViewerRow
+ * @since 3.3
+ */
+ protected ViewerRow internalCreateNewRowPart(int style, int rowIndex) {
+ TableItem item;
+
+ if (rowIndex >= 0) {
+ item = new TableItem(table, style, rowIndex);
+ } else {
+ item = new TableItem(table, style);
+ }
+
+ return getViewerRowFromItem(item);
+ }
+
+ protected Item getItemAt(Point p) {
+ TableItem[] selection = table.getSelection();
+
+ if( selection.length is 1 ) {
+ int columnCount = table.getColumnCount();
+
+ for( int i = 0; i < columnCount; i++ ) {
+ if( selection[0].getBounds(i).contains(p) ) {
+ return selection[0];
+ }
+ }
+ }
+
+ return table.getItem(p);
+ }
+
+ // Methods to provide widget independency
+
+ protected int doGetItemCount() {
+ return table.getItemCount();
+ }
+
+ protected int doIndexOf(Item item) {
+ return table.indexOf(cast(TableItem)item);
+ }
+
+ protected void doSetItemCount(int count) {
+ table.setItemCount(count);
+ }
+
+ protected Item[] doGetItems() {
+ return table.getItems();
+ }
+
+ protected int doGetColumnCount() {
+ return table.getColumnCount();
+ }
+
+ protected Widget doGetColumn(int index) {
+ return table.getColumn(index);
+ }
+
+ protected Item doGetItem(int index) {
+ return table.getItem(index);
+ }
+
+ protected Item[] doGetSelection() {
+ return table.getSelection();
+ }
+
+ protected int[] doGetSelectionIndices() {
+ return table.getSelectionIndices();
+ }
+
+ protected void doClearAll() {
+ table.clearAll();
+ }
+
+ protected void doResetItem(Item item) {
+ TableItem tableItem = cast(TableItem) item;
+ int columnCount = Math.max(1, table.getColumnCount());
+ for (int i = 0; i < columnCount; i++) {
+ tableItem.setText(i, ""); //$NON-NLS-1$
+ if (tableItem.getImage(i) !is null) {
+ tableItem.setImage(i, null);
+ }
+ }
+ }
+
+ protected void doRemove(int start, int end) {
+ table.remove(start, end);
+ }
+
+ protected void doRemoveAll() {
+ table.removeAll();
+ }
+
+ protected void doRemove(int[] indices) {
+ table.remove(indices);
+ }
+
+ protected void doShowItem(Item item) {
+ table.showItem(cast(TableItem)item);
+ }
+
+ protected void doDeselectAll() {
+ table.deselectAll();
+ }
+
+ protected void doSetSelection(Item[] items) {
+// Assert.isNotNull(items, "Items-Array can not be null"); //$NON-NLS-1$
+
+ TableItem[] t = new TableItem[items.length];
+ System.arraycopy(items, 0, t, 0, t.length);
+
+ table.setSelection(t);
+ }
+
+ protected void doShowSelection() {
+ table.showSelection();
+ }
+
+ protected void doSetSelection(int[] indices) {
+ table.setSelection(indices);
+ }
+
+ protected void doClear(int index) {
+ table.clear(index);
+ }
+
+ protected void doSelect(int[] indices) {
+ table.select(indices);
+ }
+
+ /**
+ * Refreshes this viewer starting with the given element. Labels are updated
+ * as described in refresh(bool updateLabels)
. The
+ * methods attempts to preserve the selection.
+ *
+ * Unlike the update
methods, this handles structural changes
+ * to the given element (e.g. addition or removal of children). If only the
+ * given element needs updating, it is more efficient to use the
+ * update
methods.
+ *
+ * Subclasses who can provide this feature can open this method for the + * public + *
+ * + * @param element + * the element + * @param updateLabels + *true
to update labels for existing elements,
+ * false
to only update labels as needed, assuming
+ * that labels for existing elements are unchanged.
+ * @param reveal
+ * true
to make the preserved selection visible
+ * afterwards
+ *
+ * @since 3.3
+ */
+ public void refresh(Object element, bool updateLabels,
+ bool reveal) {
+ if (isBusy())
+ return;
+
+ if( isCellEditorActive() ) {
+ cancelEditing();
+ }
+
+ preservingSelection(new class Runnable {
+ Object element_;
+ bool updateLabels_;
+ this(){
+ element_ = element;
+ updateLabels_ = updateLabels;
+ }
+ public void run() {
+ internalRefresh(element_, updateLabels_);
+ }
+ }, reveal);
+ }
+
+ /**
+ * Refreshes this viewer with information freshly obtained from this
+ * viewer's model. If updateLabels
is true
+ * then labels for otherwise unaffected elements are updated as well.
+ * Otherwise, it assumes labels for existing elements are unchanged, and
+ * labels are only obtained as needed (for example, for new elements).
+ *
+ * Calling refresh(true)
has the same effect as
+ * refresh()
.
+ *
+ * Note that the implementation may still obtain labels for existing
+ * elements even if
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ * This default implementation always returns
+ *
+ * Subclasses may override
+ *
+ * The
+ * A content provider that expects every element to be a
+ * This class and all of its methods may be overridden or extended.
+ *
+ * Clients may instantiate this class. Not intended to be subclassed.
+ *
+ * By default, the this method calls
+ * {@link ViewerSorter#category(Object)}. Subclasses may override.
+ *
+ * @param parentPath
+ * the parent path for the element
+ * @param element
+ * the element
+ * @return the category of the element
+ */
+ public int category(TreePath parentPath, Object element) {
+ return category(element);
+ }
+
+ /**
+ * Compare the given elements that will have the given parent
+ * path when they are added to the viewer. The provided path is
+ * relative to the viewer input. The parent path will
+ * be
+ * By default, the this method calls
+ * {@link ViewerSorter#sort(Viewer, Object[])}. Subclasses may override.
+ * @param viewer the viewer
+ * @param parentPath the parent path for the two elements
+ * @param e1 the first element
+ * @param e2 the second element
+ * @return a negative number if the first element is less than the
+ * second element; the value
+ * The default implementation of this method calls
+ * {@link ViewerSorter#isSorterProperty(Object, String)}.
+ * Subclasses may reimplement.
+ * @param parentPath the parent path of the element
+ * @param element the element
+ * @param property the property
+ * @return
+ * The default implementation of this method uses the
+ * java.util.Arrays#sort algorithm on the given array,
+ * calling {@link #compare(Viewer, TreePath, Object, Object)} to compare elements.
+ *
+ * Subclasses may reimplement this method to provide a more optimized implementation.
+ *
+ * This class is not intended to be subclassed.
+ *
+ * Note that TreeSelection.EMPTY is not equals() to StructuredViewer.EMPTY.
+ *
+ * This class is not intended to be subclassed outside the viewer framework. It
+ * is designed to be instantiated with a pre-existing DWT tree control and
+ * configured with a domain-specific content provider, label provider, element
+ * filter (optional), and element sorter (optional).
+ *
+ * Content providers for tree viewers must implement either the
+ * {@link ITreeContentProvider} interface, (as of 3.2) the
+ * {@link ILazyTreeContentProvider} interface, or (as of 3.3) the
+ * {@link ILazyTreePathContentProvider}. If the content provider is an
+ *
+ * This method should be called by implementers of ILazyTreeContentProvider
+ * to populate this viewer.
+ *
+ * Currently the
+ * A viewer can be created as an adapter on a pre-existing control (e.g.,
+ * creating a
+ * Implementing a concrete viewer typically involves the following steps:
+ * updateLabels
is false. The intent is
+ * simply to allow optimization where possible.
+ *
+ * @param updateLabels
+ * true
to update labels for existing elements,
+ * false
to only update labels as needed, assuming
+ * that labels for existing elements are unchanged.
+ * @param reveal
+ * true
to make the preserved selection visible
+ * afterwards
+ *
+ * @since 3.3
+ */
+ public void refresh(bool updateLabels, bool reveal) {
+ refresh(getRoot(), updateLabels, reveal);
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TableViewerColumn.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TableViewerColumn.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Tom Schindl 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:
+ * Tom Schindl - initial API and implementation
+ * Boris Bokowski (IBM Corporation) - Javadoc improvements
+ * Port to the D programming language:
+ * Frank Benoit null
+ * @param editorActivationStrategy
+ * the strategy used to decide about the editor activation
+ * @param feature
+ * the feature mask
+ */
+ this(TableViewer viewer, SWTFocusCellManager focusCellManager,
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,
+ int feature) {
+ super(viewer, editorActivationStrategy, feature);
+ tableEditor = new TableEditor(viewer.getTable());
+ this.focusCellManager = focusCellManager;
+ }
+
+ /**
+ * Create a customized editor with focusable cells
+ *
+ * @param viewer
+ * the viewer the editor is created for
+ * @param focusCellManager
+ * the cell focus manager if one needed else null
+ * @param editorActivationStrategy
+ * activation strategy to control if an editor activated
+ * @param feature
+ * bit mask controlling the editor
+ *
+ *
+ * @see #create(TableViewer, ColumnViewerEditorActivationStrategy, int)
+ */
+ public static void create(TableViewer viewer,
+ SWTFocusCellManager focusCellManager,
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,
+ int feature) {
+ TableViewerEditor editor = new TableViewerEditor(viewer,
+ focusCellManager, editorActivationStrategy, feature);
+ viewer.setColumnViewerEditor(editor);
+ if (focusCellManager !is null) {
+ focusCellManager.init();
+ }
+ }
+
+ /**
+ * Create a customized editor whose activation process is customized
+ *
+ * @param viewer
+ * the viewer the editor is created for
+ * @param editorActivationStrategy
+ * activation strategy to control if an editor activated
+ * @param feature
+ * bit mask controlling the editor
+ *
+ *
+ */
+ public static void create(TableViewer viewer,
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,
+ int feature) {
+ create(viewer, null, editorActivationStrategy, feature);
+ }
+
+ protected void setEditor(Control w, Item item, int columnNumber) {
+ tableEditor.setEditor(w, cast(TableItem) item, columnNumber);
+ }
+
+ protected void setLayoutData(CellEditor.LayoutData layoutData) {
+ tableEditor.grabHorizontal = layoutData.grabHorizontal;
+ tableEditor.horizontalAlignment = layoutData.horizontalAlignment;
+ tableEditor.minimumWidth = layoutData.minimumWidth;
+ }
+
+ public ViewerCell getFocusCell() {
+ if (focusCellManager !is null) {
+ return focusCellManager.getFocusCell();
+ }
+
+ return super.getFocusCell();
+ }
+
+ protected void updateFocusCell(ViewerCell focusCell,
+ ColumnViewerEditorActivationEvent event) {
+ // Update the focus cell when we activated the editor with these 2
+ // events
+ if (event.eventType is ColumnViewerEditorActivationEvent.PROGRAMMATIC
+ || event.eventType is ColumnViewerEditorActivationEvent.TRAVERSAL) {
+
+ auto l = getViewer().getSelectionFromWidget_package();
+
+ if (focusCellManager !is null) {
+ focusCellManager.setFocusCell(focusCell);
+ }
+
+ if (!l.contains(focusCell.getElement())) {
+ getViewer().setSelection(
+ new StructuredSelection(focusCell.getElement()),true);
+ }
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TableViewerFocusCellManager.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TableViewerFocusCellManager.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
.
+ */
+ protected Text text;
+
+ private ModifyListener modifyListener;
+
+ /**
+ * State information for updating action enablement
+ */
+ private bool isSelection = false;
+
+ private bool isDeleteable = false;
+
+ private bool isSelectable = false;
+
+ /**
+ * Default TextCellEditor style
+ * specify no borders on text widget as cell outline in table already
+ * provides the look of a border.
+ */
+ private static const int defaultStyle = DWT.SINGLE;
+
+ /**
+ * Creates a new text string cell editor with no control
+ * The cell editor value is the string itself, which is initially the empty
+ * string. Initially, the cell editor has no cell validator.
+ *
+ * @since 2.1
+ */
+ public this() {
+ setStyle(defaultStyle);
+ }
+
+ /**
+ * Creates a new text string cell editor parented under the given control.
+ * The cell editor value is the string itself, which is initially the empty string.
+ * Initially, the cell editor has no cell validator.
+ *
+ * @param parent the parent control
+ */
+ public this(Composite parent) {
+ this(parent, defaultStyle);
+ }
+
+ /**
+ * Creates a new text string cell editor parented under the given control.
+ * The cell editor value is the string itself, which is initially the empty string.
+ * Initially, the cell editor has no cell validator.
+ *
+ * @param parent the parent control
+ * @param style the style bits
+ * @since 2.1
+ */
+ public this(Composite parent, int style) {
+ super(parent, style);
+ }
+
+ /**
+ * Checks to see if the "deletable" state (can delete/
+ * nothing to delete) has changed and if so fire an
+ * enablement changed notification.
+ */
+ private void checkDeleteable() {
+ bool oldIsDeleteable = isDeleteable;
+ isDeleteable = isDeleteEnabled();
+ if (oldIsDeleteable !is isDeleteable) {
+ fireEnablementChanged(DELETE);
+ }
+ }
+
+ /**
+ * Checks to see if the "selectable" state (can select)
+ * has changed and if so fire an enablement changed notification.
+ */
+ private void checkSelectable() {
+ bool oldIsSelectable = isSelectable;
+ isSelectable = isSelectAllEnabled();
+ if (oldIsSelectable !is isSelectable) {
+ fireEnablementChanged(SELECT_ALL);
+ }
+ }
+
+ /**
+ * Checks to see if the selection state (selection /
+ * no selection) has changed and if so fire an
+ * enablement changed notification.
+ */
+ private void checkSelection() {
+ bool oldIsSelection = isSelection;
+ isSelection = text.getSelectionCount() > 0;
+ if (oldIsSelection !is isSelection) {
+ fireEnablementChanged(COPY);
+ fireEnablementChanged(CUT);
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on CellEditor.
+ */
+ protected Control createControl(Composite parent) {
+ text = new Text(parent, getStyle());
+ text.addSelectionListener(new class SelectionAdapter {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ handleDefaultSelection(e);
+ }
+ });
+ text.addKeyListener(new class KeyAdapter {
+ // hook key pressed - see PR 14201
+ public void keyPressed(KeyEvent e) {
+ keyReleaseOccured(e);
+
+ // as a result of processing the above call, clients may have
+ // disposed this cell editor
+ if ((getControl() is null) || getControl().isDisposed()) {
+ return;
+ }
+ checkSelection(); // see explanation below
+ checkDeleteable();
+ checkSelectable();
+ }
+ });
+ text.addTraverseListener(new class TraverseListener {
+ public void keyTraversed(TraverseEvent e) {
+ if (e.detail is DWT.TRAVERSE_ESCAPE
+ || e.detail is DWT.TRAVERSE_RETURN) {
+ e.doit = false;
+ }
+ }
+ });
+ // We really want a selection listener but it is not supported so we
+ // use a key listener and a mouse listener to know when selection changes
+ // may have occurred
+ text.addMouseListener(new class MouseAdapter {
+ public void mouseUp(MouseEvent e) {
+ checkSelection();
+ checkDeleteable();
+ checkSelectable();
+ }
+ });
+ text.addFocusListener(new class FocusAdapter {
+ public void focusLost(FocusEvent e) {
+ this.outer.focusLost();
+ }
+ });
+ text.setFont(parent.getFont());
+ text.setBackground(parent.getBackground());
+ text.setText("");//$NON-NLS-1$
+ text.addModifyListener(getModifyListener());
+ return text;
+ }
+
+ /**
+ * The TextCellEditor
implementation of
+ * this CellEditor
framework method returns
+ * the text string.
+ *
+ * @return the text string
+ */
+ protected Object doGetValue() {
+ return new ArrayWrapperString(text.getText());
+ }
+
+ /* (non-Javadoc)
+ * Method declared on CellEditor.
+ */
+ protected void doSetFocus() {
+ if (text !is null) {
+ text.selectAll();
+ text.setFocus();
+ checkSelection();
+ checkDeleteable();
+ checkSelectable();
+ }
+ }
+
+ /**
+ * The TextCellEditor
implementation of
+ * this CellEditor
framework method accepts
+ * a text string (type String
).
+ *
+ * @param value a text string (type String
)
+ */
+ protected void doSetValue(Object value) {
+ Assert.isTrue(text !is null && ( cast(ArrayWrapperString)value ));
+ text.removeModifyListener(getModifyListener());
+ text.setText((cast(ArrayWrapperString)value).array);
+ text.addModifyListener(getModifyListener());
+ }
+
+ /**
+ * Processes a modify event that occurred in this text cell editor.
+ * This framework method performs validation and sets the error message
+ * accordingly, and then reports a change via fireEditorValueChanged
.
+ * Subclasses should call this method at appropriate times. Subclasses
+ * may extend or reimplement.
+ *
+ * @param e the DWT modify event
+ */
+ protected void editOccured(ModifyEvent e) {
+ String value = text.getText();
+ if (value is null) {
+ value = "";//$NON-NLS-1$
+ }
+ Object typedValue = new ArrayWrapperString(value);
+ bool oldValidState = isValueValid();
+ bool newValidState = isCorrect(typedValue);
+ if (typedValue is null && newValidState) {
+ Assert.isTrue(false,
+ "Validator isn't limiting the cell editor's type range");//$NON-NLS-1$
+ }
+ if (!newValidState) {
+ // try to insert the current value into the error message.
+ setErrorMessage(Format(getErrorMessage(), value ));
+ }
+ valueChanged(oldValidState, newValidState);
+ }
+
+ /**
+ * Since a text editor field is scrollable we don't
+ * set a minimumSize.
+ */
+ public LayoutData getLayoutData() {
+ return new LayoutData();
+ }
+
+ /**
+ * Return the modify listener.
+ */
+ private ModifyListener getModifyListener() {
+ if (modifyListener is null) {
+ modifyListener = new class ModifyListener {
+ public void modifyText(ModifyEvent e) {
+ editOccured(e);
+ }
+ };
+ }
+ return modifyListener;
+ }
+
+ /**
+ * Handles a default selection event from the text control by applying the editor
+ * value and deactivating this cell editor.
+ *
+ * @param event the selection event
+ *
+ * @since 3.0
+ */
+ protected void handleDefaultSelection(SelectionEvent event) {
+ // same with enter-key handling code in keyReleaseOccured(e);
+ fireApplyEditorValue();
+ deactivate();
+ }
+
+ /**
+ * The TextCellEditor
implementation of this
+ * CellEditor
method returns true
if
+ * the current selection is not empty.
+ */
+ public bool isCopyEnabled() {
+ if (text is null || text.isDisposed()) {
+ return false;
+ }
+ return text.getSelectionCount() > 0;
+ }
+
+ /**
+ * The TextCellEditor
implementation of this
+ * CellEditor
method returns true
if
+ * the current selection is not empty.
+ */
+ public bool isCutEnabled() {
+ if (text is null || text.isDisposed()) {
+ return false;
+ }
+ return text.getSelectionCount() > 0;
+ }
+
+ /**
+ * The TextCellEditor
implementation of this
+ * CellEditor
method returns true
+ * if there is a selection or if the caret is not positioned
+ * at the end of the text.
+ */
+ public bool isDeleteEnabled() {
+ if (text is null || text.isDisposed()) {
+ return false;
+ }
+ return text.getSelectionCount() > 0
+ || text.getCaretPosition() < text.getCharCount();
+ }
+
+ /**
+ * The TextCellEditor
implementation of this
+ * CellEditor
method always returns true
.
+ */
+ public bool isPasteEnabled() {
+ if (text is null || text.isDisposed()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check if save all is enabled
+ * @return true if it is
+ */
+ public bool isSaveAllEnabled() {
+ if (text is null || text.isDisposed()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns true
if this cell editor is
+ * able to perform the select all action.
+ * false
.
+ * true
if select all is possible,
+ * false
otherwise
+ */
+ public bool isSelectAllEnabled() {
+ if (text is null || text.isDisposed()) {
+ return false;
+ }
+ return text.getCharCount() > 0;
+ }
+
+ /**
+ * Processes a key release event that occurred in this cell editor.
+ * TextCellEditor
implementation of this framework method
+ * ignores when the RETURN key is pressed since this is handled in
+ * handleDefaultSelection
.
+ * An exception is made for Ctrl+Enter for multi-line texts, since
+ * a default selection event is not sent in this case.
+ * TextCellEditor
implementation of this
+ * CellEditor
method copies the
+ * current selection to the clipboard.
+ */
+ public void performCopy() {
+ text.copy();
+ }
+
+ /**
+ * The TextCellEditor
implementation of this
+ * CellEditor
method cuts the
+ * current selection to the clipboard.
+ */
+ public void performCut() {
+ text.cut();
+ checkSelection();
+ checkDeleteable();
+ checkSelectable();
+ }
+
+ /**
+ * The TextCellEditor
implementation of this
+ * CellEditor
method deletes the
+ * current selection or, if there is no selection,
+ * the character next character from the current position.
+ */
+ public void performDelete() {
+ if (text.getSelectionCount() > 0) {
+ // remove the contents of the current selection
+ text.insert(""); //$NON-NLS-1$
+ } else {
+ // remove the next character
+ int pos = text.getCaretPosition();
+ if (pos < text.getCharCount()) {
+ text.setSelection(pos, pos + 1);
+ text.insert(""); //$NON-NLS-1$
+ }
+ }
+ checkSelection();
+ checkDeleteable();
+ checkSelectable();
+ }
+
+ /**
+ * The TextCellEditor
implementation of this
+ * CellEditor
method pastes the
+ * the clipboard contents over the current selection.
+ */
+ public void performPaste() {
+ text.paste();
+ checkSelection();
+ checkDeleteable();
+ checkSelectable();
+ }
+
+ /**
+ * The TextCellEditor
implementation of this
+ * CellEditor
method selects all of the
+ * current text.
+ */
+ public void performSelectAll() {
+ text.selectAll();
+ checkSelection();
+ checkDeleteable();
+ }
+
+ bool dependsOnExternalFocusListener() {
+ return this.classinfo !is TextCellEditor.classinfo;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TreeColumnViewerLabelProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TreeColumnViewerLabelProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl null
. There should be no null
children in
+ * the array.
+ */
+ private TreeNode[] children;
+
+ /**
+ * The parent tree node for this tree node. This value may be
+ * null
if there is no parent.
+ */
+ private TreeNode parent;
+
+ /**
+ * The value contained in this node. This value may be anything.
+ */
+ protected Object value;
+
+ /**
+ * Constructs a new instance of TreeNode
.
+ *
+ * @param value
+ * The value held by this node; may be anything.
+ */
+ public this(Object value) {
+ this.value = value;
+ }
+
+ public override int opEquals(Object object) {
+ if ( auto tn = cast(TreeNode)object ) {
+ return Util.opEquals(this.value, tn.value);
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the child nodes. Empty arrays are converted to null
+ * before being returned.
+ *
+ * @return The child nodes; may be null
, but never empty.
+ * There should be no null
children in the array.
+ */
+ public TreeNode[] getChildren() {
+ if (children !is null && children.length is 0) {
+ return null;
+ }
+ return children;
+ }
+
+ /**
+ * Returns the parent node.
+ *
+ * @return The parent node; may be null
if there are no
+ * parent nodes.
+ */
+ public TreeNode getParent() {
+ return parent;
+ }
+
+ /**
+ * Returns the value held by this node.
+ *
+ * @return The value; may be anything.
+ */
+ public Object getValue() {
+ return value;
+ }
+
+ /**
+ * Returns whether the tree has any children.
+ *
+ * @return true
if its array of children is not
+ * null
and is non-empty; false
+ * otherwise.
+ */
+ public bool hasChildren() {
+ return children !is null && children.length > 0;
+ }
+
+ public override hash_t toHash() {
+ return Util.toHash(value);
+ }
+
+ /**
+ * Sets the children for this node.
+ *
+ * @param children
+ * The child nodes; may be null
or empty. There
+ * should be no null
children in the array.
+ */
+ public void setChildren(TreeNode[] children) {
+ this.children = children;
+ }
+
+ /**
+ * Sets the parent for this node.
+ *
+ * @param parent
+ * The parent node; may be null
.
+ */
+ public void setParent(TreeNode parent) {
+ this.parent = parent;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TreeNodeContentProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TreeNodeContentProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit TreeNode
.
+ * Most methods delegate to TreeNode
. dispose()
+ * and inputChanged(Viewer, Object, Object)
do nothing by
+ * default.
+ * null
if this
+ * path has no segments.
+ *
+ * @return the first element in this path
+ */
+ public Object getFirstSegment() {
+ if (segments.length is 0) {
+ return null;
+ }
+ return segments[0];
+ }
+
+ /**
+ * Returns the last element in this path, or null
if this
+ * path has no segments.
+ *
+ * @return the last element in this path
+ */
+ public Object getLastSegment() {
+ if (segments.length is 0) {
+ return null;
+ }
+ return segments[segments.length - 1];
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public override int opEquals(Object other) {
+ if (!(cast(TreePath)other )) {
+ return false;
+ }
+ return opEquals(cast(TreePath) other, null);
+ }
+
+ /**
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public override hash_t toHash() {
+ if (hash is 0) {
+ hash = toHash(null);
+ }
+ return hash;
+ }
+
+ /**
+ * Returns a hash code computed from the hash codes of the segments, using
+ * the given comparer to compute the hash codes of the segments.
+ *
+ * @param comparer
+ * comparer to use or null
if the segments' hash
+ * codes should be computed by calling their hashCode() methods.
+ * @return the computed hash code
+ */
+ public hash_t toHash(IElementComparer comparer) {
+ int result = 0;
+ for (int i = 0; i < segments.length; i++) {
+ if (comparer is null) {
+ result += segments[i].toHash();
+ } else {
+ result += comparer.toHash(segments[i]);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns whether this path is equivalent to the given path using the
+ * specified comparer to compare individual elements.
+ *
+ * @param otherPath
+ * tree path to compare to
+ * @param comparer
+ * comparator to use or null
if segments should be
+ * compared using equals()
+ * @return whether the paths are equal
+ */
+ public int opEquals(TreePath otherPath, IElementComparer comparer) {
+ if (otherPath is null) {
+ return false;
+ }
+ if (segments.length !is otherPath.segments.length) {
+ return false;
+ }
+ for (int i = 0; i < segments.length; i++) {
+ if (comparer is null) {
+ if (!segments[i].opEquals(otherPath.segments[i])) {
+ return false;
+ }
+ } else {
+ if (!comparer.opEquals(segments[i], otherPath.segments[i])) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether this path starts with the same segments as the given
+ * path, using the given comparer to compare segments.
+ *
+ * @param treePath
+ * path to compare to
+ * @param comparer
+ * the comparer to use, or null
if equals() should
+ * be used to compare segments
+ * @return whether the given path is a prefix of this path, or the same as
+ * this path
+ */
+ public bool startsWith(TreePath treePath, IElementComparer comparer) {
+ int thisSegmentCount = getSegmentCount();
+ int otherSegmentCount = treePath.getSegmentCount();
+ if (otherSegmentCount is thisSegmentCount) {
+ return opEquals(treePath, comparer) !is 0;
+ }
+ if (otherSegmentCount > thisSegmentCount) {
+ return false;
+ }
+ for (int i = 0; i < otherSegmentCount; i++) {
+ Object otherSegment = treePath.getSegment(i);
+ if (comparer is null) {
+ if (!otherSegment.opEquals(segments[i])) {
+ return false;
+ }
+ } else {
+ if (!comparer.opEquals(otherSegment, segments[i])) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns a copy of this tree path with one segment removed from the end,
+ * or null
if this tree path has no segments.
+ * @return a tree path
+ */
+ public TreePath getParentPath() {
+ int segmentCount = getSegmentCount();
+ if (segmentCount < 1) {
+ return null;
+ } else if (segmentCount is 1) {
+ return EMPTY;
+ }
+ Object[] parentSegments = new Object[segmentCount - 1];
+ System.arraycopy(segments, 0, parentSegments, 0, segmentCount - 1);
+ return new TreePath(parentSegments);
+ }
+
+ /**
+ * Returns a copy of this tree path with the given segment added at the end.
+ * @param newSegment
+ * @return a tree path
+ */
+ public TreePath createChildPath(Object newSegment) {
+ int segmentCount = getSegmentCount();
+ Object[] childSegments = new Object[segmentCount + 1];
+ if(segmentCount>0) {
+ System.arraycopy(segments, 0, childSegments, 0, segmentCount);
+ }
+ childSegments[segmentCount] = newSegment;
+ return new TreePath(childSegments);
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TreePathViewerSorter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TreePathViewerSorter.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
when the elements are root elements.
+ * null
when the elements are root elements.
+ * 0
if the first element is
+ * equal to the second element; and a positive
+ */
+ public int compare(Viewer viewer, TreePath parentPath, Object e1, Object e2) {
+ return compare(viewer, e1, e2);
+ }
+
+ /**
+ * Returns whether this viewer sorter would be affected
+ * by a change to the given property of the given element.
+ * The provided path is
+ * relative to the viewer input. The parent path will
+ * be null
when the elements are root elements.
+ * true
if the sorting would be affected,
+ * and false
if it would be unaffected
+ */
+ public bool isSorterProperty(TreePath parentPath, Object element, String property) {
+ return isSorterProperty(element, property);
+ }
+
+ /**
+ * Sorts the given elements in-place, modifying the given array.
+ * The provided path is
+ * relative to the viewer input. The parent path will
+ * be null
when the elements are root elements.
+ * ITreeSelection
interface,
+ * suitable for instantiating.
+ * null
.
+ */
+ public static const TreeSelection EMPTY;
+
+ private static const TreePath[] EMPTY_TREE_PATHS = null;
+ static this(){
+ EMPTY = new TreeSelection();
+ }
+
+ private static class InitializeData {
+ Seq!(Object) selection;
+ TreePath[] paths;
+ CustomHashtable element2TreePaths;
+
+ private this(TreePath[] paths, IElementComparer comparer) {
+ this.paths= new TreePath[paths.length];
+ System.arraycopy(paths, 0, this.paths, 0, paths.length);
+ element2TreePaths = new CustomHashtable(comparer);
+ int size = paths.length;
+ auto s = new ArraySeq!(Object);
+ s.capacity(size);
+ selection = s;
+ for (int i = 0; i < size; i++) {
+ Object lastSegment= paths[i].getLastSegment();
+ Object mapped= element2TreePaths.get(lastSegment);
+ if (mapped is null) {
+ selection.append(lastSegment);
+ element2TreePaths.put(lastSegment, paths[i]);
+ } else if ( cast(Seq!(Object))mapped ) {
+ (cast(Seq!(Object))mapped).append(paths[i]);
+ } else {
+ Seq!(Object) newMapped= new ArraySeq!(Object);
+ newMapped.append(mapped);
+ newMapped.append(paths[i]);
+ element2TreePaths.put(lastSegment, cast(Object) newMapped);
+ }
+ }
+ }
+ }
+
+ /**
+ * Constructs a selection based on the elements identified by the given tree
+ * paths.
+ *
+ * @param paths
+ * tree paths
+ */
+ public this(TreePath[] paths) {
+ this(new InitializeData(paths, null));
+ }
+
+ /**
+ * Constructs a selection based on the elements identified by the given tree
+ * paths.
+ *
+ * @param paths
+ * tree paths
+ * @param comparer
+ * the comparer, or null
if default equals is to be used
+ */
+ public this(TreePath[] paths, IElementComparer comparer) {
+ this(new InitializeData(paths, comparer));
+ }
+
+ /**
+ * Constructs a selection based on the elements identified by the given tree
+ * path.
+ *
+ * @param treePath
+ * tree path, or null
for an empty selection
+ */
+ public this(TreePath treePath) {
+ this(treePath !is null ? [ treePath ] : EMPTY_TREE_PATHS, null);
+ }
+
+ /**
+ * Constructs a selection based on the elements identified by the given tree
+ * path.
+ *
+ * @param treePath
+ * tree path, or null
for an empty selection
+ * @param comparer
+ * the comparer, or null
if default equals is to be used
+ */
+ public this(TreePath treePath, IElementComparer comparer) {
+ this(treePath !is null ? [ treePath ] : EMPTY_TREE_PATHS, comparer);
+ }
+
+ /**
+ * Creates a new tree selection based on the initialization data.
+ *
+ * @param data the data
+ */
+ private this(InitializeData data) {
+ super(data.selection);
+ paths= data.paths;
+ element2TreePaths= data.element2TreePaths;
+ }
+
+ /**
+ * Creates a new empty selection. See also the static field
+ * EMPTY
which contains an empty selection singleton.
+ * null
if no comparer has been
+ * provided.
+ *
+ * @return the element comparer or null
+ *
+ * @since 3.2
+ */
+ public IElementComparer getElementComparer() {
+ if (element2TreePaths is null)
+ return null;
+ return element2TreePaths.getComparer();
+ }
+
+ public override int opEquals(Object obj) {
+ if (!(cast(TreeSelection)obj)) {
+ // Fall back to super implementation, see bug 135837.
+ return super.equals(obj);
+ }
+ TreeSelection selection = cast(TreeSelection) obj;
+ int size = getPaths().length;
+ if (selection.getPaths().length is size) {
+ IElementComparer comparerOrNull = (getElementComparer() is selection
+ .getElementComparer()) ? getElementComparer() : null;
+ if (size > 0) {
+ for (int i = 0; i < paths.length; i++) {
+ if (!paths[i].opEquals(selection.paths[i], comparerOrNull)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public override hash_t toHash() {
+ int code = this.classinfo.toHash();
+ if (paths !is null) {
+ for (int i = 0; i < paths.length; i++) {
+ code = code * 17 + paths[i].toHash(getElementComparer());
+ }
+ }
+ return code;
+ }
+
+ public TreePath[] getPaths() {
+ return paths is null ? EMPTY_TREE_PATHS : paths.dup;
+ }
+
+ public TreePath[] getPathsFor(Object element) {
+ Object value= element2TreePaths is null ? null : element2TreePaths.get(element);
+ if (value is null) {
+ return EMPTY_TREE_PATHS;
+ } else if (cast(TreePath)value ) {
+ return [ cast(TreePath)value ];
+ } else if (cast(Seq!(Object))value ) {
+ auto l= cast(Seq!(Object))value;
+ return cast(TreePath[]) l.toArray();
+ } else {
+ // should not happen:
+ Assert.isTrue(false, "Unhandled case"); //$NON-NLS-1$
+ return null;
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TreeViewer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TreeViewer.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,1164 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl Tree
control.
+ * ILazyTreeContentProvider
or an
+ * ILazyTreePathContentProvider
, the underlying Tree must be
+ * created using the {@link DWT#VIRTUAL} style bit, and the tree viewer will not
+ * support sorting or filtering.
+ * MULTI, H_SCROLL, V_SCROLL,
and BORDER
. The
+ * viewer has no input, no content provider, a default label provider, no
+ * sorter, and no filters.
+ *
+ * @param parent
+ * the parent control
+ */
+ public this(Composite parent) {
+ this(parent, DWT.MULTI | DWT.H_SCROLL | DWT.V_SCROLL | DWT.BORDER);
+ }
+
+ /**
+ * Creates a tree viewer on a newly-created tree control under the given
+ * parent. The tree control is created using the given DWT style bits. The
+ * viewer has no input, no content provider, a default label provider, no
+ * sorter, and no filters.
+ *
+ * @param parent
+ * the parent control
+ * @param style
+ * the DWT style bits used to create the tree.
+ */
+ public this(Composite parent, int style) {
+ this(new Tree(parent, style));
+ }
+
+ /**
+ * Creates a tree viewer on the given tree control. The viewer has no input,
+ * no content provider, a default label provider, no sorter, and no filters.
+ *
+ * @param tree
+ * the tree control
+ */
+ public this(Tree tree) {
+ super();
+ this.tree = tree;
+ hookControl(tree);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void addTreeListener(Control c, TreeListener listener) {
+ (cast(Tree) c).addTreeListener(listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.ColumnViewer#getColumnViewerOwner(int)
+ */
+ protected Widget getColumnViewerOwner(int columnIndex) {
+ if (columnIndex < 0 || ( columnIndex > 0 && columnIndex >= getTree().getColumnCount() ) ) {
+ return null;
+ }
+
+ if (getTree().getColumnCount() is 0)// Hang it off the table if it
+ return getTree();
+
+ return getTree().getColumn(columnIndex);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected Item[] getChildren(Widget o) {
+ if (auto ti = cast(TreeItem)o ) {
+ return ti.getItems();
+ }
+ if (auto t = cast(Tree)o ) {
+ return t.getItems();
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc) Method declared in Viewer.
+ */
+ public Control getControl() {
+ return tree;
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected bool getExpanded(Item item) {
+ return (cast(TreeItem) item).getExpanded();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.ColumnViewer#getItemAt(dwt.graphics.Point)
+ */
+ protected Item getItemAt(Point p) {
+ TreeItem[] selection = tree.getSelection();
+
+ if( selection.length is 1 ) {
+ int columnCount = tree.getColumnCount();
+
+ for( int i = 0; i < columnCount; i++ ) {
+ if( selection[0].getBounds(i).contains(p) ) {
+ return selection[0];
+ }
+ }
+ }
+
+ return getTree().getItem(p);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected int getItemCount(Control widget) {
+ return (cast(Tree) widget).getItemCount();
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected int getItemCount(Item item) {
+ return (cast(TreeItem) item).getItemCount();
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected Item[] getItems(Item item) {
+ return (cast(TreeItem) item).getItems();
+ }
+
+ /**
+ * The tree viewer implementation of this Viewer
framework
+ * method ensures that the given label provider is an instance of either
+ * ITableLabelProvider
or ILabelProvider
. If
+ * it is an ITableLabelProvider
, then it provides a separate
+ * label text and image for each column. If it is an
+ * ILabelProvider
, then it provides only the label text and
+ * image for the first column, and any remaining columns are blank.
+ */
+ public IBaseLabelProvider getLabelProvider() {
+ return super.getLabelProvider();
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected Item getParentItem(Item item) {
+ return (cast(TreeItem) item).getParentItem();
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected Item[] getSelection(Control widget) {
+ return (cast(Tree) widget).getSelection();
+ }
+
+ /**
+ * Returns this tree viewer's tree control.
+ *
+ * @return the tree control
+ */
+ public Tree getTree() {
+ return tree;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.AbstractTreeViewer#hookControl(dwt.widgets.Control)
+ */
+ protected void hookControl(Control control) {
+ super.hookControl(control);
+ Tree treeControl = cast(Tree) control;
+
+ if ((treeControl.getStyle() & DWT.VIRTUAL) !is 0) {
+ treeControl.addDisposeListener(new class DisposeListener {
+ public void widgetDisposed(DisposeEvent e) {
+ treeIsDisposed = true;
+ unmapAllElements();
+ }
+ });
+ treeControl.addListener(DWT.SetData, new class Listener {
+
+ public void handleEvent(Event event) {
+ if (contentProviderIsLazy) {
+ TreeItem item = cast(TreeItem) event.item;
+ TreeItem parentItem = item.getParentItem();
+ int index = event.index;
+ virtualLazyUpdateWidget(
+ parentItem is null ? cast(Widget) getTree()
+ : parentItem, index);
+ }
+ }
+
+ });
+ }
+ }
+
+ protected ColumnViewerEditor createViewerEditor() {
+ return new TreeViewerEditor(this,null,new ColumnViewerEditorActivationStrategy(this),ColumnViewerEditor.DEFAULT);
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected Item newItem(Widget parent, int flags, int ix) {
+ TreeItem item;
+
+ if ( cast(TreeItem)parent ) {
+ item = cast(TreeItem) createNewRowPart(getViewerRowFromItem(parent),
+ flags, ix).getItem();
+ } else {
+ item = cast(TreeItem) createNewRowPart(null, flags, ix).getItem();
+ }
+
+ return item;
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void removeAll(Control widget) {
+ (cast(Tree) widget).removeAll();
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void setExpanded(Item node, bool expand) {
+ (cast(TreeItem) node).setExpanded(expand);
+ if (contentProviderIsLazy) {
+ // force repaints to happen
+ getControl().update();
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void setSelection(SeqView!(Item) items) {
+
+ Item[] current = getSelection(getTree());
+
+ // Don't bother resetting the same selection
+ if (isSameSelection(items, current)) {
+ return;
+ }
+
+ getTree().setSelection( cast(TreeItem[]) items.toArray());
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void showItem(Item item) {
+ getTree().showItem(cast(TreeItem) item);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.AbstractTreeViewer#getChild(dwt.widgets.Widget,
+ * int)
+ */
+ protected Item getChild(Widget widget, int index) {
+ if (auto ti = cast(TreeItem)widget ) {
+ return ti.getItem(index);
+ }
+ if (auto t = cast(Tree)widget ) {
+ return t.getItem(index);
+ }
+ return null;
+ }
+
+ protected void assertContentProviderType(IContentProvider provider) {
+ if ( null !is cast(ILazyTreeContentProvider)provider
+ || null !is cast(ILazyTreePathContentProvider)provider ) {
+ return;
+ }
+ super.assertContentProviderType(provider);
+ }
+
+ protected Object[] getRawChildren(Object parent) {
+ if (contentProviderIsLazy) {
+ return new Object[0];
+ }
+ return super.getRawChildren(parent);
+ }
+
+ void preservingSelection(Runnable updateCode, bool reveal) {
+ if (preservingSelection_){
+ // avoid preserving the selection if called reentrantly,
+ // see bug 172640
+ updateCode.run();
+ return;
+ }
+ preservingSelection_ = true;
+ try {
+ super.preservingSelection(updateCode, reveal);
+ } finally {
+ preservingSelection_ = false;
+ }
+ }
+
+ /**
+ * For a TreeViewer with a tree with the VIRTUAL style bit set, set the
+ * number of children of the given element or tree path. To set the number
+ * of children of the invisible root of the tree, you can pass the input
+ * object or an empty tree path.
+ *
+ * @param elementOrTreePath
+ * the element, or tree path
+ * @param count
+ *
+ * @since 3.2
+ */
+ public void setChildCount(Object elementOrTreePath, int count) {
+ if (isBusy())
+ return;
+ preservingSelection(new class Runnable {
+ Object elementOrTreePath_;
+ int count_;
+ this(){
+ elementOrTreePath_=elementOrTreePath;
+ count_=count;
+ }
+ public void run() {
+ if (internalIsInputOrEmptyPath(elementOrTreePath_)) {
+ getTree().setItemCount(count_);
+ return;
+ }
+ Widget[] items = internalFindItems(elementOrTreePath_);
+ for (int i = 0; i < items.length; i++) {
+ TreeItem treeItem = cast(TreeItem) items[i];
+ treeItem.setItemCount(count_);
+ }
+ }
+ });
+ }
+
+ /**
+ * For a TreeViewer with a tree with the VIRTUAL style bit set, replace the
+ * given parent's child at index with the given element. If the given parent
+ * is this viewer's input or an empty tree path, this will replace the root
+ * element at the given index.
+ * null
if the widget is the tree
+ * @param widget
+ * @param element
+ * @param index the index of the widget in the children array of its parent, or 0 if the widget is the tree
+ */
+ private void virtualRefreshExpandedItems(Widget parent, Widget widget, Object element, int index) {
+ if ( cast(Tree)widget ) {
+ if (element is null) {
+ (cast(Tree) widget).setItemCount(0);
+ return;
+ }
+ virtualLazyUpdateChildCount(widget, getChildren(widget).length);
+ } else if ((cast(TreeItem) widget).getExpanded()) {
+ // prevent SetData callback
+ (cast(TreeItem)widget).setText(" "); //$NON-NLS-1$
+ virtualLazyUpdateWidget(parent, index);
+ } else {
+ return;
+ }
+ Item[] items = getChildren(widget);
+ for (int i = 0; i < items.length; i++) {
+ Item item = items[i];
+ Object data = item.getData();
+ virtualRefreshExpandedItems(widget, item, data, i);
+ }
+ }
+
+ /*
+ * To unmap elements correctly, we need to register a dispose listener with
+ * the item if the tree is virtual.
+ */
+ protected void mapElement(Object element, Widget item) {
+ super.mapElement(element, item);
+ // make sure to unmap elements if the tree is virtual
+ if ((getTree().getStyle() & DWT.VIRTUAL) !is 0) {
+ // only add a dispose listener if item hasn't already on assigned
+ // because it is reused
+ if (item.getData(VIRTUAL_DISPOSE_KEY) is null) {
+ item.setData(VIRTUAL_DISPOSE_KEY, new ValueWrapperBool(true));
+ item.addDisposeListener(new class DisposeListener {
+ Widget item_;
+ this(){
+ item_=item;
+ }
+ public void widgetDisposed(DisposeEvent e) {
+ if (!treeIsDisposed) {
+ Object data = item_.getData();
+ if (usingElementMap() && data !is null) {
+ unmapElement(data, item_);
+ }
+ }
+ }
+ });
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.ColumnViewer#getRowPartFromItem(dwt.widgets.Widget)
+ */
+ protected ViewerRow getViewerRowFromItem(Widget item) {
+ if( cachedRow is null ) {
+ cachedRow = new TreeViewerRow(cast(TreeItem) item);
+ } else {
+ cachedRow.setItem(cast(TreeItem) item);
+ }
+
+ return cachedRow;
+ }
+
+ /**
+ * Create a new ViewerRow at rowIndex
+ *
+ * @param parent
+ * @param style
+ * @param rowIndex
+ * @return ViewerRow
+ */
+ private ViewerRow createNewRowPart(ViewerRow parent, int style, int rowIndex) {
+ if (parent is null) {
+ if (rowIndex >= 0) {
+ return getViewerRowFromItem(new TreeItem(tree, style, rowIndex));
+ }
+ return getViewerRowFromItem(new TreeItem(tree, style));
+ }
+
+ if (rowIndex >= 0) {
+ return getViewerRowFromItem(new TreeItem(cast(TreeItem) parent.getItem(),
+ DWT.NONE, rowIndex));
+ }
+
+ return getViewerRowFromItem(new TreeItem(cast(TreeItem) parent.getItem(),
+ DWT.NONE));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.AbstractTreeViewer#internalInitializeTree(dwt.widgets.Control)
+ */
+ protected void internalInitializeTree(Control widget) {
+ if (contentProviderIsLazy) {
+ if (cast(Tree)widget && widget.getData() !is null) {
+ virtualLazyUpdateChildCount(widget, 0);
+ return;
+ }
+ }
+ super.internalInitializeTree(tree);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.viewers.AbstractTreeViewer#updatePlus(dwt.widgets.Item,
+ * java.lang.Object)
+ */
+ protected void updatePlus(Item item, Object element) {
+ if (contentProviderIsLazy) {
+ Object data = item.getData();
+ int itemCount = 0;
+ if (data !is null) {
+ // item is already materialized
+ itemCount = (cast(TreeItem) item).getItemCount();
+ }
+ virtualLazyUpdateHasChildren(item, itemCount);
+ } else {
+ super.updatePlus(item, element);
+ }
+ }
+
+ /**
+ * Removes the element at the specified index of the parent. The selection is updated if required.
+ *
+ * @param parentOrTreePath the parent element, the input element, or a tree path to the parent element
+ * @param index child index
+ * @since 3.3
+ */
+ public void remove(Object parentOrTreePath_, int index_) {
+ if (isBusy())
+ return;
+ preservingSelection(new class Runnable {
+ Seq!(TreePath) oldSelection;
+ Object parentOrTreePath;
+ int index;
+ this(){
+ parentOrTreePath=parentOrTreePath_;
+ index=index_;
+ oldSelection = new LinkSeq!(TreePath);
+ foreach( p; (cast(TreeSelection) getSelection()).getPaths()){
+ oldSelection.append( p );
+ }
+ }
+ public void run() {
+ TreePath removedPath = null;
+ if (internalIsInputOrEmptyPath(parentOrTreePath)) {
+ Tree tree = cast(Tree) getControl();
+ if (index < tree.getItemCount()) {
+ TreeItem item = tree.getItem(index);
+ if (item.getData() !is null) {
+ removedPath = getTreePathFromItem(item);
+ disassociate(item);
+ }
+ item.dispose();
+ }
+ } else {
+ Widget[] parentItems = internalFindItems(parentOrTreePath);
+ for (int i = 0; i < parentItems.length; i++) {
+ TreeItem parentItem = cast(TreeItem) parentItems[i];
+ if (index < parentItem.getItemCount()) {
+ TreeItem item = parentItem.getItem(index);
+ if (item.getData() !is null) {
+ removedPath = getTreePathFromItem(item);
+ disassociate(item);
+ }
+ item.dispose();
+ }
+ }
+ }
+ if (removedPath !is null) {
+ bool removed = false;
+ int delIdx = 0;
+ foreach ( path; oldSelection.dup ) {
+ if (path.startsWith(removedPath, getComparer())) {
+ oldSelection.removeAt(delIdx);
+ removed = true;
+ }
+ delIdx++;
+ }
+ if (removed) {
+ setSelection(new TreeSelection(
+ oldSelection.toArray(), getComparer()),
+ false);
+ }
+
+ }
+ }
+ });
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractTreeViewer#handleTreeExpand(dwt.events.TreeEvent)
+ */
+ protected void handleTreeExpand(TreeEvent event) {
+ if (contentProviderIsLazy) {
+ if (event.item.getData() !is null) {
+ Item[] children = getChildren(event.item);
+ if (children.length is 1 && children[0].getData() is null) {
+ // we have a dummy child node, ask for an updated child
+ // count
+ virtualLazyUpdateChildCount(event.item, children.length);
+ }
+ fireTreeExpanded(new TreeExpansionEvent(this, event.item
+ .getData()));
+ }
+ return;
+ }
+ super.handleTreeExpand(event);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.AbstractTreeViewer#setContentProvider(dwtx.jface.viewers.IContentProvider)
+ */
+ public void setContentProvider(IContentProvider provider) {
+ contentProviderIsLazy = (cast(ILazyTreeContentProvider)provider )
+ || (cast(ILazyTreePathContentProvider)provider );
+ contentProviderIsTreeBased = null !is cast(ILazyTreePathContentProvider)provider ;
+ super.setContentProvider(provider);
+ }
+
+ /**
+ * For a TreeViewer with a tree with the VIRTUAL style bit set, inform the
+ * viewer about whether the given element or tree path has children. Avoid
+ * calling this method if the number of children has already been set.
+ *
+ * @param elementOrTreePath
+ * the element, or tree path
+ * @param hasChildren
+ *
+ * @since 3.3
+ */
+ public void setHasChildren(Object elementOrTreePath_, bool hasChildren_) {
+ if (isBusy())
+ return;
+ preservingSelection(new class Runnable {
+ Object elementOrTreePath;
+ bool hasChildren;
+ this(){
+ elementOrTreePath=elementOrTreePath_;
+ hasChildren=hasChildren_;
+ }
+ public void run() {
+ if (internalIsInputOrEmptyPath(elementOrTreePath)) {
+ if (hasChildren) {
+ virtualLazyUpdateChildCount(getTree(),
+ getChildren(getTree()).length);
+ } else {
+ setChildCount(elementOrTreePath, 0);
+ }
+ return;
+ }
+ Widget[] items = internalFindItems(elementOrTreePath);
+ for (int i = 0; i < items.length; i++) {
+ TreeItem item = cast(TreeItem) items[i];
+ if (!hasChildren) {
+ item.setItemCount(0);
+ } else {
+ if (!item.getExpanded()) {
+ item.setItemCount(1);
+ TreeItem child = item.getItem(0);
+ if (child.getData() !is null) {
+ disassociate(child);
+ }
+ item.clear(0, true);
+ } else {
+ virtualLazyUpdateChildCount(item, item.getItemCount());
+ }
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Update the widget at index.
+ * @param widget
+ * @param index
+ */
+ private void virtualLazyUpdateWidget(Widget widget, int index) {
+ bool oldBusy = busy;
+ busy = false;
+ try {
+ if (contentProviderIsTreeBased) {
+ TreePath treePath;
+ if ( auto i = cast(Item)widget ) {
+ if (widget.getData() is null) {
+ // we need to materialize the parent first
+ // see bug 167668
+ // however, that would be too risky
+ // see bug 182782 and bug 182598
+ // so we just ignore this call altogether
+ // and don't do this: virtualMaterializeItem((TreeItem) widget);
+ return;
+ }
+ treePath = getTreePathFromItem(i);
+ } else {
+ treePath = TreePath.EMPTY;
+ }
+ (cast(ILazyTreePathContentProvider) getContentProvider())
+ .updateElement(treePath, index);
+ } else {
+ (cast(ILazyTreeContentProvider) getContentProvider()).updateElement(
+ widget.getData(), index);
+ }
+ } finally {
+ busy = oldBusy;
+ }
+ }
+
+ /**
+ * Update the child count
+ * @param widget
+ * @param currentChildCount
+ */
+ private void virtualLazyUpdateChildCount(Widget widget, int currentChildCount) {
+ bool oldBusy = busy;
+ busy = false;
+ try {
+ if (contentProviderIsTreeBased) {
+ TreePath treePath;
+ if (cast(Item)widget ) {
+ treePath = getTreePathFromItem(cast(Item) widget);
+ } else {
+ treePath = TreePath.EMPTY;
+ }
+ (cast(ILazyTreePathContentProvider) getContentProvider())
+ .updateChildCount(treePath, currentChildCount);
+ } else {
+ (cast(ILazyTreeContentProvider) getContentProvider()).updateChildCount(widget.getData(), currentChildCount);
+ }
+ } finally {
+ busy = oldBusy;
+ }
+ }
+
+ /**
+ * Update the item with the current child count.
+ * @param item
+ * @param currentChildCount
+ */
+ private void virtualLazyUpdateHasChildren(Item item, int currentChildCount) {
+ bool oldBusy = busy;
+ busy = false;
+ try {
+ if (contentProviderIsTreeBased) {
+ TreePath treePath;
+ treePath = getTreePathFromItem(item);
+ if (currentChildCount is 0) {
+ // item is not expanded (but may have a plus currently)
+ (cast(ILazyTreePathContentProvider) getContentProvider())
+ .updateHasChildren(treePath);
+ } else {
+ (cast(ILazyTreePathContentProvider) getContentProvider())
+ .updateChildCount(treePath, currentChildCount);
+ }
+ } else {
+ (cast(ILazyTreeContentProvider) getContentProvider()).updateChildCount(item.getData(), currentChildCount);
+ }
+ } finally {
+ busy = oldBusy;
+ }
+ }
+
+ protected void disassociate(Item item) {
+ if (contentProviderIsLazy) {
+ // avoid causing a callback:
+ item.setText(" "); //$NON-NLS-1$
+ }
+ super.disassociate(item);
+ }
+
+ protected int doGetColumnCount() {
+ return tree.getColumnCount();
+ }
+
+ /**
+ * Sets a new selection for this viewer and optionally makes it visible.
+ * reveal
parameter is not honored because
+ * {@link Tree} does not provide an API to only select an item without
+ * scrolling it into view
+ * true
if the selection is to be made visible,
+ * and false
otherwise
+ */
+ public void setSelection(ISelection selection, bool reveal) {
+ super.setSelection(selection, reveal);
+ }
+
+ public void editElement(Object element, int column) {
+ if( cast(TreePath)element ) {
+ setSelection(new TreeSelection(cast(TreePath) element));
+ TreeItem[] items = tree.getSelection();
+
+ if( items.length is 1 ) {
+ ViewerRow row = getViewerRowFromItem(items[0]);
+
+ if (row !is null) {
+ ViewerCell cell = row.getCell(column);
+ if (cell !is null) {
+ getControl().setRedraw(false);
+ try {
+ triggerEditorActivationEvent(new ColumnViewerEditorActivationEvent(cell));
+ } finally {
+ getControl().setRedraw(true);
+ }
+ }
+ }
+ }
+ } else {
+ super.editElement(element, column);
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TreeViewerColumn.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TreeViewerColumn.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Tom Schindl 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:
+ * Tom Schindl - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit null
+ * @param editorActivationStrategy
+ * the strategy used to decide about the editor activation
+ * @param feature
+ * the feature mask
+ */
+ this(TreeViewer viewer, SWTFocusCellManager focusCellManager,
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,
+ int feature) {
+ super(viewer, editorActivationStrategy, feature);
+ treeEditor = new TreeEditor(viewer.getTree());
+ this.focusCellManager = focusCellManager;
+ }
+
+ /**
+ * Create a customized editor with focusable cells
+ *
+ * @param viewer
+ * the viewer the editor is created for
+ * @param focusCellManager
+ * the cell focus manager if one needed else null
+ * @param editorActivationStrategy
+ * activation strategy to control if an editor activated
+ * @param feature
+ * bit mask controlling the editor
+ *
+ *
+ * @see #create(TreeViewer, ColumnViewerEditorActivationStrategy, int)
+ */
+ public static void create(TreeViewer viewer,
+ SWTFocusCellManager focusCellManager,
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,
+ int feature) {
+ TreeViewerEditor editor = new TreeViewerEditor(viewer,
+ focusCellManager, editorActivationStrategy, feature);
+ viewer.setColumnViewerEditor(editor);
+ if (focusCellManager !is null) {
+ focusCellManager.init();
+ }
+ }
+
+ /**
+ * Create a customized editor whose activation process is customized
+ *
+ * @param viewer
+ * the viewer the editor is created for
+ * @param editorActivationStrategy
+ * activation strategy to control if an editor activated
+ * @param feature
+ * bit mask controlling the editor
+ *
+ *
+ */
+ public static void create(TreeViewer viewer,
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,
+ int feature) {
+ create(viewer, null, editorActivationStrategy, feature);
+ }
+
+ protected void setEditor(Control w, Item item, int fColumnNumber) {
+ treeEditor.setEditor(w, cast(TreeItem) item, fColumnNumber);
+ }
+
+ protected void setLayoutData(CellEditor.LayoutData layoutData) {
+ treeEditor.grabHorizontal = layoutData.grabHorizontal;
+ treeEditor.horizontalAlignment = layoutData.horizontalAlignment;
+ treeEditor.minimumWidth = layoutData.minimumWidth;
+ }
+
+ public ViewerCell getFocusCell() {
+ if (focusCellManager !is null) {
+ return focusCellManager.getFocusCell();
+ }
+
+ return super.getFocusCell();
+ }
+
+ protected void updateFocusCell(ViewerCell focusCell,
+ ColumnViewerEditorActivationEvent event) {
+ // Update the focus cell when we activated the editor with these 2
+ // events
+ if (event.eventType is ColumnViewerEditorActivationEvent.PROGRAMMATIC
+ || event.eventType is ColumnViewerEditorActivationEvent.TRAVERSAL) {
+
+ auto l = getViewer().getSelectionFromWidget_package();
+
+ if (focusCellManager !is null) {
+ focusCellManager.setFocusCell(focusCell);
+ }
+
+ if (!l.contains(focusCell.getElement())) {
+ getViewer().setSelection(
+ new TreeSelection(focusCell.getViewerRow()
+ .getTreePath()),true);
+ }
+ }
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/TreeViewerFocusCellManager.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TreeViewerFocusCellManager.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit ListViewer
on an existing List
control).
+ * All viewers also provide a convenience constructor for creating the control.
+ *
+ *
+ * setSelection
, getSelection
)
+ *
ISelectionChangedListener
).
+ *
+ * @see #fireSelectionChanged
+ */
+ private ListenerList selectionChangedListeners;
+
+ /**
+ * List of help request listeners (element type: dwt.events.HelpListener
).
+ * Help request listeners.
+ *
+ * @see #handleHelpRequest
+ */
+ private ListenerList helpListeners;
+
+ /**
+ * The names of this viewer's properties.
+ * null
if this viewer has no properties.
+ *
+ * @see #setData
+ */
+ private String[] keys;
+
+ /**
+ * The values of this viewer's properties.
+ * null
if this viewer has no properties.
+ * This array parallels the value of the keys
field.
+ *
+ * @see #setData
+ */
+ private Object[] values;
+
+ /**
+ * Remembers whether we've hooked the help listener on the control or not.
+ */
+ private bool helpHooked = false;
+
+ /**
+ * Help listener for the control, created lazily when client's first help listener is added.
+ */
+ private HelpListener helpListener = null;
+
+ /**
+ * Unique key for associating element data with widgets.
+ * @see dwt.widgets.Widget#setData(String, Object)
+ */
+ protected static const String WIDGET_DATA_KEY = "dwtx.jface.viewers.WIDGET_DATA";//$NON-NLS-1$
+
+ /**
+ * Creates a new viewer.
+ */
+ protected this() {
+ selectionChangedListeners = new ListenerList();
+ helpListeners = new ListenerList();
+ }
+
+ /**
+ * Adds a listener for help requests in this viewer.
+ * Has no effect if an identical listener is already registered.
+ *
+ * @param listener a help listener
+ */
+ public void addHelpListener(HelpListener listener) {
+ helpListeners.add(cast(Object)listener);
+ if (!helpHooked) {
+ Control control = getControl();
+ if (control !is null && !control.isDisposed()) {
+ if (this.helpListener is null) {
+ this.helpListener = new class HelpListener {
+ public void helpRequested(HelpEvent event) {
+ handleHelpRequest(event);
+ }
+ };
+ }
+ control.addHelpListener(this.helpListener);
+ helpHooked = true;
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ISelectionProvider.
+ */
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ selectionChangedListeners.add(cast(Object)listener);
+ }
+
+ /**
+ * Notifies any help listeners that help has been requested.
+ * Only listeners registered at the time this method is called are notified.
+ *
+ * @param event a help event
+ *
+ * @see HelpListener#helpRequested(dwt.events.HelpEvent)
+ */
+ protected void fireHelpRequested(HelpEvent event) {
+ Object[] listeners = helpListeners.getListeners();
+ for (int i = 0; i < listeners.length; ++i) {
+ (cast(HelpListener) listeners[i]).helpRequested(event);
+ }
+ }
+
+ /**
+ * Notifies any selection changed listeners that the viewer's selection has changed.
+ * Only listeners registered at the time this method is called are notified.
+ *
+ * @param event a selection changed event
+ *
+ * @see ISelectionChangedListener#selectionChanged
+ */
+ protected void fireSelectionChanged(SelectionChangedEvent event) {
+ Object[] listeners = selectionChangedListeners.getListeners();
+ for (int i = 0; i < listeners.length; ++i) {
+ SafeRunnable.run(new class SafeRunnable {
+ ISelectionChangedListener l;
+ SelectionChangedEvent event_;
+ this(){
+ event_=event;
+ l = cast(ISelectionChangedListener) listeners[i];
+ }
+ public void run() {
+ l.selectionChanged(event_);
+ }
+ });
+ }
+ }
+
+ /**
+ * Returns the primary control associated with this viewer.
+ *
+ * @return the DWT control which displays this viewer's content
+ */
+ public abstract Control getControl();
+
+ /**
+ * Returns the value of the property with the given name,
+ * or null
if the property is not found.
+ *
+ * The default implementation performs a (linear) search of
+ * an internal table. Overriding this method is generally not
+ * required if the number of different keys is small. If a more
+ * efficient representation of a viewer's properties is required,
+ * override both getData
and setData
.
+ *
null
if
+ * the property is not found
+ */
+ public Object getData(String key) {
+ Assert.isNotNull(key);
+ if (keys is null) {
+ return null;
+ }
+ for (int i = 0; i < keys.length; i++) {
+ if (keys[i].equals(key)) {
+ return values[i];
+ }
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * Copy-down of method declared on IInputProvider
.
+ */
+ public abstract Object getInput();
+
+ /* (non-Javadoc)
+ * Copy-down of method declared on ISelectionProvider
.
+ */
+ public abstract ISelection getSelection();
+
+ /**
+ * Handles a help request from the underlying DWT control.
+ * The default behavior is to fire a help request,
+ * with the event's data modified to hold this viewer.
+ * @param event the event
+ *
+ */
+ protected void handleHelpRequest(HelpEvent event) {
+ Object oldData = event.data;
+ event.data = this;
+ fireHelpRequested(event);
+ event.data = oldData;
+ }
+
+ /**
+ * Internal hook method called when the input to this viewer is
+ * initially set or subsequently changed.
+ * + * The default implementation does nothing. Subclassers may override + * this method to do something when a viewer's input is set. + * A typical use is populate the viewer. + *
+ * + * @param input the new input of this viewer, ornull
if none
+ * @param oldInput the old input element or null
if there
+ * was previously no input
+ */
+ protected void inputChanged(Object input, Object oldInput) {
+ }
+
+ /**
+ * Refreshes this viewer completely with information freshly obtained from this
+ * viewer's model.
+ */
+ public abstract void refresh();
+
+ /**
+ * Removes the given help listener from this viewer.
+ * Has no affect if an identical listener is not registered.
+ *
+ * @param listener a help listener
+ */
+ public void removeHelpListener(HelpListener listener) {
+ helpListeners.remove(cast(Object)listener);
+ if (helpListeners.size() is 0) {
+ Control control = getControl();
+ if (control !is null && !control.isDisposed()) {
+ control.removeHelpListener(this.helpListener);
+ helpHooked = false;
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on ISelectionProvider.
+ */
+ public void removeSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ selectionChangedListeners.remove(cast(Object)listener);
+ }
+
+ /**
+ * Scrolls the viewer's control down by one item from the given
+ * display-relative coordinates. Returns the newly revealed Item,
+ * or null
if no scrolling occurred or if the viewer
+ * doesn't represent an item-based widget.
+ *
+ * @param x horizontal coordinate
+ * @param y vertical coordinate
+ * @return the item scrolled down to
+ */
+ public Item scrollDown(int x, int y) {
+ return null;
+ }
+
+ /**
+ * Scrolls the viewer's control up by one item from the given
+ * display-relative coordinates. Returns the newly revealed Item,
+ * or null
if no scrolling occurred or if the viewer
+ * doesn't represent an item-based widget.
+ *
+ * @param x horizontal coordinate
+ * @param y vertical coordinate
+ * @return the item scrolled up to
+ */
+ public Item scrollUp(int x, int y) {
+ return null;
+ }
+
+ /**
+ * Sets the value of the property with the given name to the
+ * given value, or to null
if the property is to be
+ * removed. If this viewer has such a property, its value is
+ * replaced; otherwise a new property is added.
+ *
+ * The default implementation records properties in an internal
+ * table which is searched linearly. Overriding this method is generally not
+ * required if the number of different keys is small. If a more
+ * efficient representation of a viewer's properties is required,
+ * override both getData
and setData
.
+ *
null
if
+ * the property is not found
+ */
+ public void setData(String key, Object value) {
+ Assert.isNotNull(key);
+ /* Remove the key/value pair */
+ if (value is null) {
+ if (keys is null) {
+ return;
+ }
+ int index = 0;
+ while (index < keys.length && !keys[index].equals(key)) {
+ index++;
+ }
+ if (index is keys.length) {
+ return;
+ }
+ if (keys.length is 1) {
+ keys = null;
+ values = null;
+ } else {
+ String[] newKeys = new String[keys.length - 1];
+ Object[] newValues = new Object[values.length - 1];
+ System.arraycopy(keys, 0, newKeys, 0, index);
+ System.arraycopy(keys, index + 1, newKeys, index,
+ newKeys.length - index);
+ System.arraycopy(values, 0, newValues, 0, index);
+ System.arraycopy(values, index + 1, newValues, index,
+ newValues.length - index);
+ keys = newKeys;
+ values = newValues;
+ }
+ return;
+ }
+
+ /* Add the key/value pair */
+ if (keys is null) {
+ keys = [ key ];
+ values = [ value ];
+ return;
+ }
+ for (int i = 0; i < keys.length; i++) {
+ if (keys[i].equals(key)) {
+ values[i] = value;
+ return;
+ }
+ }
+ String[] newKeys = new String[](keys.length + 1);
+ Object[] newValues = new Object[](values.length + 1);
+ System.arraycopy(keys, 0, newKeys, 0, keys.length);
+ System.arraycopy(values, 0, newValues, 0, values.length);
+ newKeys[keys.length] = key;
+ newValues[values.length] = value;
+ keys = newKeys;
+ values = newValues;
+ }
+
+ /**
+ * Sets or clears the input for this viewer.
+ *
+ * @param input the input of this viewer, or null
if none
+ */
+ public abstract void setInput(Object input);
+
+ /**
+ * The viewer implementation of this ISelectionProvider
+ * method make the new selection for this viewer without making it visible.
+ *
+ * This method is equivalent to setSelection(selection,false)
.
+ *
+ * Note that some implementations may not be able to set the selection + * without also revealing it, for example (as of 3.3) TreeViewer. + *
+ */ + public void setSelection(ISelection selection) { + setSelection(selection, false); + } + + /** + * Sets a new selection for this viewer and optionally makes it visible. + *+ * Subclasses must implement this method. + *
+ * + * @param selection the new selection + * @param revealtrue
if the selection is to be made
+ * visible, and false
otherwise
+ */
+ public abstract void setSelection(ISelection selection, bool reveal);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ViewerCell.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ViewerCell.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,294 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Shindl null
+ */
+ public Image getImage() {
+ return row.getImage(columnIndex);
+ }
+
+ /**
+ * Set the background color of the cell.
+ *
+ * @param background
+ */
+ public void setBackground(Color background) {
+ row.setBackground(columnIndex, background);
+
+ }
+
+ /**
+ * Set the foreground color of the cell.
+ *
+ * @param foreground
+ */
+ public void setForeground(Color foreground) {
+ row.setForeground(columnIndex, foreground);
+
+ }
+
+ /**
+ * Set the font of the cell.
+ *
+ * @param font
+ */
+ public void setFont(Font font) {
+ row.setFont(columnIndex, font);
+
+ }
+
+ /**
+ * Set the text for the cell.
+ *
+ * @param text
+ */
+ public void setText(String text) {
+ row.setText(columnIndex, text);
+
+ }
+
+ /**
+ * Set the Image for the cell.
+ *
+ * @param image
+ */
+ public void setImage(Image image) {
+ row.setImage(columnIndex, image);
+
+ }
+
+ /**
+ * Set the columnIndex.
+ *
+ * @param column
+ */
+ void setColumn(int column) {
+ columnIndex = column;
+
+ }
+
+ /**
+ * Set the row to rowItem and the columnIndex to column.
+ *
+ * @param rowItem
+ * @param column
+ */
+ void update(ViewerRow rowItem, int column, Object element) {
+ row = rowItem;
+ columnIndex = column;
+ this.element = element;
+ }
+
+ /**
+ * Return the item for the receiver.
+ *
+ * @return {@link Item}
+ */
+ public Widget getItem() {
+ return row.getItem();
+ }
+
+ /**
+ * Get the control for this cell.
+ *
+ * @return {@link Control}
+ */
+ public Control getControl() {
+ return row.getControl();
+ }
+
+ /**
+ * Returns the specified neighbor of this cell, or null
if no
+ * neighbor exists in the given direction. Direction constants can be
+ * combined by bitwise OR; for example, this method will return the cell to
+ * the upper-left of the current cell by passing {@link #ABOVE} |
+ * {@link #LEFT}. If sameLevel
is true
, only
+ * cells in sibling rows (under the same parent) will be considered.
+ *
+ * @param directionMask
+ * the direction mask used to identify the requested neighbor
+ * cell
+ * @param sameLevel
+ * if true
, only consider cells from sibling rows
+ * @return the requested neighbor cell, or null
if not found
+ */
+ public ViewerCell getNeighbor(int directionMask, bool sameLevel) {
+ ViewerRow row;
+ int columnIndex;
+
+ if ((directionMask & ABOVE) is ABOVE) {
+ row = this.row.getNeighbor(ViewerRow.ABOVE, sameLevel);
+ } else if ((directionMask & BELOW) is BELOW) {
+ row = this.row.getNeighbor(ViewerRow.BELOW, sameLevel);
+ } else {
+ row = this.row;
+ }
+
+ if (row !is null) {
+ if ((directionMask & LEFT) is LEFT) {
+ columnIndex = getColumnIndex() - 1;
+ } else if ((directionMask & RIGHT) is RIGHT) {
+ columnIndex = getColumnIndex() + 1;
+ } else {
+ columnIndex = getColumnIndex();
+ }
+
+ if (columnIndex >= 0 && columnIndex < row.getColumnCount()) {
+ return row.getCell(columnIndex);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return the row
+ */
+ public ViewerRow getViewerRow() {
+ return row;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public override hash_t toHash() {
+ const int prime = 31;
+ int result = 1;
+ result = prime * result + columnIndex;
+ result = prime * result + ((row is null) ? 0 : row.toHash());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public override int opEquals(Object obj) {
+ if (this is obj)
+ return true;
+ if (obj is null)
+ return false;
+ if (this.classinfo !is obj.classinfo )
+ return false;
+ ViewerCell other = cast(ViewerCell) obj;
+ if (columnIndex !is other.columnIndex)
+ return false;
+ if (row is null) {
+ if (other.row !is null)
+ return false;
+ } else if (!row.opEquals(other.row))
+ return false;
+ return true;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ViewerColumn.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ViewerColumn.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Shindl
+ * The default compare
method compares elements using two steps.
+ * The first step uses the values returned from category
.
+ * By default, all elements are in the same category.
+ * The second level is based on a case insensitive compare of the strings obtained
+ * from the content viewer's label provider via ILabelProvider.getText
.
+ *
+ * Subclasses may implement the isSorterProperty
method;
+ * they may reimplement the category
method to provide
+ * categorization; and they may override the compare
methods
+ * to provide a totally different way of sorting elements.
+ *
+ * The default implementation of this framework method returns
+ * 0
. Subclasses may reimplement this method to provide
+ * non-trivial categorization.
+ *
+ * The default implementation of this method is based on
+ * comparing the elements' categories as computed by the category
+ * framework method. Elements within the same category are further
+ * subjected to a case insensitive compare of their label strings, either
+ * as computed by the content viewer's label provider, or their
+ * toString
values in other cases. Subclasses may override.
+ *
0
if the first element is
+ * equal to the second element; and a positive number if the first
+ * element is greater than the second element
+ */
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ int cat1 = category(e1);
+ int cat2 = category(e2);
+
+ if (cat1 !is cat2) {
+ return cat1 - cat2;
+ }
+
+ String name1;
+ String name2;
+
+ if (viewer is null || !(cast(ContentViewer)viewer )) {
+ name1 = e1.toString();
+ name2 = e2.toString();
+ } else {
+ IBaseLabelProvider prov = (cast(ContentViewer) viewer)
+ .getLabelProvider();
+ if (auto lprov = cast(ILabelProvider)prov ) {
+ name1 = lprov.getText(e1);
+ name2 = lprov.getText(e2);
+ } else {
+ name1 = e1.toString();
+ name2 = e2.toString();
+ }
+ }
+ if (name1 is null) {
+ name1 = "";//$NON-NLS-1$
+ }
+ if (name2 is null) {
+ name2 = "";//$NON-NLS-1$
+ }
+
+ // use the comparator to compare the strings
+ return getComparator().compare( new ArrayWrapperString(name1), new ArrayWrapperString(name2));
+ }
+
+ /**
+ * Returns whether this viewer sorter would be affected
+ * by a change to the given property of the given element.
+ *
+ * The default implementation of this method returns false
.
+ * Subclasses may reimplement.
+ *
true
if the sorting would be affected,
+ * and false
if it would be unaffected
+ */
+ public bool isSorterProperty(Object element, String property) {
+ return false;
+ }
+
+ /**
+ * Sorts the given elements in-place, modifying the given array.
+ *
+ * The default implementation of this method uses the
+ * java.util.Arrays#sort algorithm on the given array,
+ * calling compare
to compare elements.
+ *
+ * Subclasses may reimplement this method to provide a more optimized implementation. + *
+ * + * @param viewer the viewer + * @param elements the elements to sort + */ + public void sort(Viewer viewer, Object[] elements) { + tango.core.Array.sort(elements, delegate int(Object a, Object b) { + return compare(viewer, a, b); + } + ); + } +} diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ViewerDropAdapter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/viewers/ViewerDropAdapter.d Mon Mar 31 00:47:19 2008 +0200 @@ -0,0 +1,463 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit+ * Subclasses must implement the following methods: + *
validateDrop
- identifies valid drop targets in viewerperformDrop
- carries out a drop into a viewersetFeedbackEnabled
method can be called to turn on and off
+ * visual insertion feedback (on by default).
+ *
+ */
+public abstract class ViewerDropAdapter : DropTargetAdapter {
+
+ /**
+ * Constant describing the position of the cursor relative
+ * to the target object. This means the mouse is positioned
+ * slightly before the target.
+ * @see #getCurrentLocation()
+ */
+ public static const int LOCATION_BEFORE = 1;
+
+ /**
+ * Constant describing the position of the cursor relative
+ * to the target object. This means the mouse is positioned
+ * slightly after the target.
+ * @see #getCurrentLocation()
+ */
+ public static const int LOCATION_AFTER = 2;
+
+ /**
+ * Constant describing the position of the cursor relative
+ * to the target object. This means the mouse is positioned
+ * directly on the target.
+ * @see #getCurrentLocation()
+ */
+ public static const int LOCATION_ON = 3;
+
+ /**
+ * Constant describing the position of the cursor relative
+ * to the target object. This means the mouse is not positioned
+ * over or near any valid target.
+ * @see #getCurrentLocation()
+ */
+ public static const int LOCATION_NONE = 4;
+
+ /**
+ * The viewer to which this drop support has been added.
+ */
+ private Viewer viewer;
+
+ /**
+ * The current operation.
+ */
+ private int currentOperation = DND.DROP_NONE;
+
+ /**
+ * The last valid operation.
+ */
+ private int lastValidOperation = DND.DROP_NONE;
+
+ /**
+ * The data item currently under the mouse.
+ */
+ private Object currentTarget;
+
+ /**
+ * Information about the position of the mouse relative to the
+ * target (before, on, or after the target. Location is one of
+ * the LOCATION_*
constants defined in this type.
+ */
+ private int currentLocation;
+
+ /**
+ * A flag that allows adapter users to turn the insertion
+ * feedback on or off. Default is true
.
+ */
+ private bool feedbackEnabled = true;
+
+ /**
+ * A flag that allows adapter users to turn auto scrolling
+ * and expanding on or off. Default is true
.
+ */
+ private bool scrollExpandEnabled = true;
+
+ /**
+ * A flag that allows adapter users to turn selection feedback
+ * on or off. Default is true
.
+ */
+ private bool selectFeedbackEnabled = true;
+
+ /**
+ * Creates a new drop adapter for the given viewer.
+ *
+ * @param viewer the viewer
+ */
+ protected this(Viewer viewer) {
+ this.viewer = viewer;
+ }
+
+ /**
+ * Returns the position of the given event's coordinates relative to its target.
+ * The position is determined to be before, after, or on the item, based on
+ * some threshold value.
+ *
+ * @param event the event
+ * @return one of the LOCATION_*
constants defined in this class
+ */
+ protected int determineLocation(DropTargetEvent event) {
+ if (!( cast(Item)event.item )) {
+ return LOCATION_NONE;
+ }
+ Item item = cast(Item) event.item;
+ Point coordinates = new Point(event.x, event.y);
+ coordinates = viewer.getControl().toControl(coordinates);
+ if (item !is null) {
+ Rectangle bounds = getBounds(item);
+ if (bounds is null) {
+ return LOCATION_NONE;
+ }
+ if ((coordinates.y - bounds.y) < 5) {
+ return LOCATION_BEFORE;
+ }
+ if ((bounds.y + bounds.height - coordinates.y) < 5) {
+ return LOCATION_AFTER;
+ }
+ }
+ return LOCATION_ON;
+ }
+
+ /**
+ * Returns the target item of the given drop event.
+ *
+ * @param event the event
+ * @return The target of the drop, may be null
.
+ */
+ protected Object determineTarget(DropTargetEvent event) {
+ return event.item is null ? null : event.item.getData();
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DropTargetAdapter.
+ * The mouse has moved over the drop target. If the
+ * target item has changed, notify the action and check
+ * that it is still enabled.
+ */
+ private void doDropValidation(DropTargetEvent event) {
+ //update last valid operation
+ if (event.detail !is DND.DROP_NONE) {
+ lastValidOperation = event.detail;
+ }
+ //valid drop and set event detail accordingly
+ if (validateDrop(currentTarget, event.detail, event.currentDataType)) {
+ currentOperation = lastValidOperation;
+ } else {
+ currentOperation = DND.DROP_NONE;
+ }
+ event.detail = currentOperation;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DropTargetAdapter.
+ * The drag has entered this widget's region. See
+ * if the drop should be allowed.
+ */
+ public void dragEnter(DropTargetEvent event) {
+ currentTarget = determineTarget(event);
+ doDropValidation(event);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DropTargetAdapter.
+ * The drop operation has changed, see if the action
+ * should still be enabled.
+ */
+ public void dragOperationChanged(DropTargetEvent event) {
+ currentTarget = determineTarget(event);
+ doDropValidation(event);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DropTargetAdapter.
+ * The mouse has moved over the drop target. If the
+ * target item has changed, notify the action and check
+ * that it is still enabled.
+ */
+ public void dragOver(DropTargetEvent event) {
+ //use newly revealed item as target if scrolling occurs
+ Object target = determineTarget(event);
+
+ //set the location feedback
+ int oldLocation = currentLocation;
+ currentLocation = determineLocation(event);
+ setFeedback(event, currentLocation);
+
+ //see if anything has really changed before doing validation.
+ if (target !is currentTarget || currentLocation !is oldLocation) {
+ currentTarget = target;
+ doDropValidation(event);
+ }
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DropTargetAdapter.
+ * The user has dropped something on the desktop viewer.
+ */
+ public void drop(DropTargetEvent event) {
+ currentLocation = determineLocation(event);
+
+ //perform the drop behavior
+ if (!performDrop(event.data)) {
+ event.detail = DND.DROP_NONE;
+ }
+ currentOperation = event.detail;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on DropTargetAdapter.
+ * Last chance for the action to disable itself
+ */
+ public void dropAccept(DropTargetEvent event) {
+ if (!validateDrop(currentTarget, event.detail, event.currentDataType)) {
+ event.detail = DND.DROP_NONE;
+ }
+ }
+
+ /**
+ * Returns the bounds of the given DWT tree or table item.
+ *
+ * @param item the DWT Item
+ * @return the bounds, or null
if it is not a known type of item
+ */
+ protected Rectangle getBounds(Item item) {
+ if ( auto i = cast(TreeItem)item ) {
+ return i.getBounds();
+ }
+ if (auto i = cast(TableItem)item ) {
+ return i.getBounds(0);
+ }
+ return null;
+ }
+
+ /**
+ * Returns a constant describing the position of the mouse relative to the
+ * target (before, on, or after the target.
+ *
+ * @return one of the LOCATION_*
constants defined in this type
+ */
+ protected int getCurrentLocation() {
+ return currentLocation;
+ }
+
+ /**
+ * Returns the current operation.
+ *
+ * @return a DROP_*
constant from class DND
+ *
+ * @see DND#DROP_COPY
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_LINK
+ * @see DND#DROP_NONE
+ */
+ protected int getCurrentOperation() {
+ return currentOperation;
+ }
+
+ /**
+ * Returns the target object currently under the mouse.
+ *
+ * @return the current target object
+ */
+ protected Object getCurrentTarget() {
+ return currentTarget;
+ }
+
+ /**
+ * Returns whether visible insertion feedback should be presented to the user.
+ * + * Typical insertion feedback is the horizontal insertion bars that appear + * between adjacent items while dragging. + *
+ * + * @returntrue
if visual feedback is desired, and false
if not
+ */
+ public bool getFeedbackEnabled() {
+ return feedbackEnabled;
+ }
+
+ /**
+ * Returns the object currently selected by the viewer.
+ *
+ * @return the selected object, or null
if either no object or
+ * multiple objects are selected
+ */
+ protected Object getSelectedObject() {
+ ISelection selection = viewer.getSelection();
+ if ( null !is cast(IStructuredSelection) selection && !selection.isEmpty()) {
+ IStructuredSelection structured = cast(IStructuredSelection) selection;
+ return structured.getFirstElement();
+ }
+ return null;
+ }
+
+ /**
+ * @return the viewer to which this drop support has been added.
+ */
+ protected Viewer getViewer() {
+ return viewer;
+ }
+
+ /**
+ * @deprecated this method should not be used. Exception handling has been
+ * removed from DropTargetAdapter methods overridden by this class.
+ * Handles any exception that occurs during callback, including
+ * rethrowing behavior.
+ * + * [Issue: Implementation prints stack trace and eats exception to avoid + * crashing VA/J. + * Consider conditionalizing the implementation to do one thing in VAJ + * and something more reasonable in other operating environments. + * ] + *
+ * + * @param exception the exception + * @param event the event + */ + protected void handleException(Exception exception, DropTargetEvent event) { + // Currently we never rethrow because VA/Java crashes if an DWT + // callback throws anything. Generally catching Throwable is bad, but in + // this cases it's better than hanging the image. + ExceptionPrintStackTrace( exception ); + event.detail = DND.DROP_NONE; + } + + /** + * Performs any work associated with the drop. + *+ * Subclasses must implement this method to provide drop behavior. + *
+ * + * @param data the drop data + * @returntrue
if the drop was successful, and
+ * false
otherwise
+ */
+ public abstract bool performDrop(Object data);
+
+ /* (non-Javadoc)
+ * Method declared on DropTargetAdapter.
+ * The mouse has moved over the drop target. If the
+ * target item has changed, notify the action and check
+ * that it is still enabled.
+ */
+ private void setFeedback(DropTargetEvent event, int location) {
+ if (feedbackEnabled) {
+ switch (location) {
+ case LOCATION_BEFORE:
+ event.feedback = DND.FEEDBACK_INSERT_BEFORE;
+ break;
+ case LOCATION_AFTER:
+ event.feedback = DND.FEEDBACK_INSERT_AFTER;
+ break;
+ case LOCATION_ON:
+ default:
+ event.feedback = DND.FEEDBACK_SELECT;
+ break;
+ }
+ }
+
+ // Explicitly inhibit SELECT feedback if desired
+ if (!selectFeedbackEnabled) {
+ event.feedback &= ~DND.FEEDBACK_SELECT;
+ }
+
+ if (scrollExpandEnabled) {
+ event.feedback |= DND.FEEDBACK_EXPAND | DND.FEEDBACK_SCROLL;
+ }
+ }
+
+ /**
+ * Sets whether visible insertion feedback should be presented to the user.
+ * + * Typical insertion feedback is the horizontal insertion bars that appear + * between adjacent items while dragging. + *
+ * + * @param value + *true
if visual feedback is desired, and
+ * false
if not
+ */
+ public void setFeedbackEnabled(bool value) {
+ feedbackEnabled = value;
+ }
+
+ /**
+ * Sets whether selection feedback should be provided during dragging.
+ *
+ * @param value true
if selection feedback is desired, and
+ * false
if not
+ *
+ * @since 3.2
+ */
+ public void setSelectionFeedbackEnabled(bool value) {
+ selectFeedbackEnabled = value;
+ }
+
+ /**
+ * Sets whether auto scrolling and expanding should be provided during dragging.
+ *
+ * @param value true
if scrolling and expanding is desired, and
+ * false
if not
+ * @since 2.0
+ */
+ public void setScrollExpandEnabled(bool value) {
+ scrollExpandEnabled = value;
+ }
+
+ /**
+ * Validates dropping on the given object. This method is called whenever some
+ * aspect of the drop operation changes.
+ * + * Subclasses must implement this method to define which drops make sense. + *
+ * + * @param target the object that the mouse is currently hovering over, or + *null
if the mouse is hovering over empty space
+ * @param operation the current drag operation (copy, move, etc.)
+ * @param transferType the current transfer type
+ * @return true
if the drop is valid, and false
+ * otherwise
+ */
+ public abstract bool validateDrop(Object target, int operation,
+ TransferData transferType);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ViewerFilter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ViewerFilter.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit
+ * Subclasses must implement the select
method
+ * and may implement the isFilterProperty
method.
+ *
+ * The default implementation of this method calls
+ * select
on each element in the array,
+ * and returns only those elements for which select
+ * returns true
.
+ *
+ * The default implementation of this method calls + * {@link #filter(Viewer, Object, Object[])} with the + * parent from the path. Subclasses may override + *
+ * @param viewer the viewer + * @param parentPath the path of the parent element + * @param elements the elements to filter + * @return the filtered elements + * @since 3.2 + */ + public Object[] filter(Viewer viewer, TreePath parentPath, Object[] elements) { + return filter(viewer, parentPath.getLastSegment(), elements); + } + + /** + * Returns whether this viewer filter would be affected + * by a change to the given property of the given element. + *
+ * The default implementation of this method returns false
.
+ * Subclasses should reimplement.
+ *
true
if the filtering would be affected,
+ * and false
if it would be unaffected
+ */
+ public bool isFilterProperty(Object element, String property) {
+ return false;
+ }
+
+ /**
+ * Returns whether the given element makes it through this filter.
+ *
+ * @param viewer the viewer
+ * @param parentElement the parent element
+ * @param element the element
+ * @return true
if element is included in the
+ * filtered set, and false
if excluded
+ */
+ public abstract bool select(Viewer viewer, Object parentElement,
+ Object element);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ViewerLabel.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ViewerLabel.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,418 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Schindl null
if there was no initial text and
+ * nothing was updated.
+ */
+ public final String getText() {
+ if (textUpdated) {
+ return newText;
+ }
+ return startText;
+ }
+
+ /**
+ * Set the text for the receiver.
+ *
+ * @param text
+ * String The label to set. This value should not be
+ * null
.
+ * @see #hasNewText()
+ */
+ public final void setText(String text) {
+ newText = text;
+ textUpdated = true;
+ }
+
+ /**
+ * Return whether or not the image has been set.
+ *
+ * @return bool. true
if the image has been set to
+ * something new.
+ *
+ * @since 3.1
+ */
+ public bool hasNewImage() {
+
+ // If we started with null any change is an update
+ if (startImage is null) {
+ return newImage !is null;
+ }
+
+ if (imageUpdated) {
+ return !(startImage.opEquals(newImage));
+ }
+ return false;
+ }
+
+ /**
+ * Return whether or not the text has been set.
+ *
+ * @return bool. true
if the text has been set to
+ * something new.
+ */
+ public bool hasNewText() {
+
+ // If we started with null any change is an update
+ if (startText is null) {
+ return newText !is null;
+ }
+
+ if (textUpdated) {
+ return !(startText.equals(newText));
+ }
+
+ return false;
+ }
+
+ /**
+ * Return whether or not the background color has been set.
+ *
+ * @return bool. true
if the value has been set.
+ */
+ public bool hasNewBackground() {
+ return background !is null;
+ }
+
+ /**
+ * Return whether or not the foreground color has been set.
+ *
+ * @return bool. true
if the value has been set.
+ *
+ * @since 3.1
+ */
+ public bool hasNewForeground() {
+ return foreground !is null;
+ }
+
+ /**
+ * Return whether or not the font has been set.
+ *
+ * @return bool. true
if the value has been set.
+ *
+ * @since 3.1
+ */
+ public bool hasNewFont() {
+ return font !is null;
+ }
+
+ /**
+ * Get the background Color.
+ *
+ * @return Color or null
if no new value was set.
+ *
+ * @since 3.1
+ */
+ public Color getBackground() {
+ return background;
+ }
+
+ /**
+ * Set the background Color.
+ *
+ * @param background
+ * Color. This value should not be null
.
+ *
+ * @since 3.1
+ */
+ public void setBackground(Color background) {
+ this.background = background;
+ }
+
+ /**
+ * Get the font.
+ *
+ * @return Font or null
if no new value was set.
+ *
+ * @since 3.1
+ */
+ public Font getFont() {
+ return font;
+ }
+
+ /**
+ * Set the font.
+ *
+ * @param font
+ * Font This value should not be null
.
+ *
+ * @since 3.1
+ */
+ public void setFont(Font font) {
+ this.font = font;
+ }
+
+ /**
+ * Get the foreground Color.
+ *
+ * @return Color or null
if no new value was set.
+ *
+ * @since 3.1
+ */
+ public Color getForeground() {
+ return foreground;
+ }
+
+ /**
+ * Set the foreground Color.
+ *
+ * @param foreground
+ * Color This value should not be null
.
+ *
+ * @since 3.1
+ */
+ public void setForeground(Color foreground) {
+ this.foreground = foreground;
+ }
+
+ /**
+ * Set whether or not there are any decorations pending.
+ *
+ * @param hasPendingDecorations
+ */
+ void setHasPendingDecorations(bool hasPendingDecorations_) {
+ this.hasPendingDecorations_ = hasPendingDecorations_;
+ }
+
+ /**
+ * @return bool
. true
if there are any
+ * decorations pending.
+ */
+ bool hasPendingDecorations() {
+ return hasPendingDecorations_;
+ }
+
+ /**
+ * Returns the tooltipText.
+ *
+ * @return {@link String} or null
if the tool tip text was
+ * never set.
+ *
+ * @since 3.3
+ */
+ public String getTooltipText() {
+ return tooltipText;
+ }
+
+ /**
+ * Set the tool tip text.
+ *
+ * @param tooltipText
+ * The tooltipText {@link String} to set. This value should not
+ * be null
.
+ *
+ * @since 3.3
+ */
+ public void setTooltipText(String tooltipText) {
+ this.tooltipText = tooltipText;
+ }
+
+ /**
+ * Return whether or not the tool tip text has been set.
+ *
+ * @return bool
. true
if the tool tip text
+ * has been set.
+ *
+ * @since 3.3
+ */
+ public bool hasNewTooltipText() {
+ return this.tooltipText !is null;
+ }
+
+ /**
+ * Return the tool tip background color.
+ *
+ * @return {@link Color} or null
if the tool tip background
+ * color has not been set.
+ *
+ * @since 3.3
+ */
+ public Color getTooltipBackgroundColor() {
+ return tooltipBackgroundColor;
+ }
+
+ /**
+ * Set the background {@link Color} for tool tip.
+ *
+ * @param tooltipBackgroundColor
+ * The {@link Color} to set. This value should not be
+ * null
.
+ *
+ * @since 3.3
+ */
+ public void setTooltipBackgroundColor(Color tooltipBackgroundColor) {
+ this.tooltipBackgroundColor = tooltipBackgroundColor;
+ }
+
+ /**
+ * Return whether or not the tool tip background color has been set.
+ *
+ * @return bool
. true
if the tool tip text
+ * has been set.
+ *
+ * @since 3.3
+ */
+ public bool hasNewTooltipBackgroundColor() {
+ return tooltipBackgroundColor !is null;
+ }
+
+ /**
+ * Return the foreground {@link Color}.
+ *
+ * @return Returns {@link Color} or null
if the tool tip
+ * foreground color has not been set.
+ *
+ * @since 3.3
+ */
+ public Color getTooltipForegroundColor() {
+ return tooltipForegroundColor;
+ }
+
+ /**
+ * Set the foreground {@link Color} for tool tip.
+ *
+ * @param tooltipForegroundColor
+ * The tooltipForegroundColor to set.
+ *
+ * @since 3.3
+ */
+ public void setTooltipForegroundColor(Color tooltipForegroundColor) {
+ this.tooltipForegroundColor = tooltipForegroundColor;
+ }
+
+ /**
+ *
+ * Return whether or not the tool tip foreground color has been set.
+ *
+ * @return bool
. true
if the tool tip foreground
+ * has been set.
+ *
+ * @since 3.3
+ */
+ public bool hasNewTooltipForegroundColor() {
+ return tooltipForegroundColor !is null;
+ }
+
+ /**
+ * @return Returns the tooltipShift.
+ * @since 3.3
+ */
+ public Point getTooltipShift() {
+ return tooltipShift;
+ }
+
+ /**
+ * @param tooltipShift
+ * The tooltipShift to set.
+ * @since 3.3
+ */
+ public void setTooltipShift(Point tooltipShift) {
+ this.tooltipShift = tooltipShift;
+ }
+
+ /**
+ * @return Return whether or not the tool tip shift has been set.
+ * @since 3.3
+ */
+ public bool hasTooltipShift() {
+ return this.tooltipShift !is null;
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ViewerRow.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ViewerRow.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Tom Shindl null
+ */
+ public abstract Image getImage(int columnIndex);
+
+ /**
+ * Set the image at the columnIndex
+ *
+ * @param columnIndex
+ * @param image
+ */
+ public abstract void setImage(int columnIndex, Image image);
+
+ /**
+ * Get the text at the columnIndex.
+ *
+ * @param columnIndex
+ * @return {@link String}
+ */
+ public abstract String getText(int columnIndex);
+
+ /**
+ * Set the text at the columnIndex
+ *
+ * @param columnIndex
+ * @param text
+ */
+ public abstract void setText(int columnIndex, String text);
+
+ /**
+ * Get the background at the columnIndex,
+ *
+ * @param columnIndex
+ * @return {@link Color} or null
+ */
+ public abstract Color getBackground(int columnIndex);
+
+ /**
+ * Set the background at the columnIndex.
+ *
+ * @param columnIndex
+ * @param color
+ */
+ public abstract void setBackground(int columnIndex, Color color);
+
+ /**
+ * Get the foreground at the columnIndex.
+ *
+ * @param columnIndex
+ * @return {@link Color} or null
+ */
+ public abstract Color getForeground(int columnIndex);
+
+ /**
+ * Set the foreground at the columnIndex.
+ *
+ * @param columnIndex
+ * @param color
+ */
+ public abstract void setForeground(int columnIndex, Color color);
+
+ /**
+ * Get the font at the columnIndex.
+ *
+ * @param columnIndex
+ * @return {@link Font} or null
+ */
+ public abstract Font getFont(int columnIndex);
+
+ /**
+ * Set the {@link Font} at the columnIndex.
+ *
+ * @param columnIndex
+ * @param font
+ */
+ public abstract void setFont(int columnIndex, Font font);
+
+ /**
+ * Get the ViewerCell at point.
+ *
+ * @param point
+ * @return {@link ViewerCell}
+ */
+ public ViewerCell getCell(Point point) {
+ int index = getColumnIndex(point);
+ return getCell(index);
+ }
+
+ /**
+ * Get the columnIndex of the point.
+ *
+ * @param point
+ * @return int or -1 if it cannot be found.
+ */
+ public int getColumnIndex(Point point) {
+ int count = getColumnCount();
+
+ // If there are no columns the column-index is 0
+ if (count is 0) {
+ return 0;
+ }
+
+ for (int i = 0; i < count; i++) {
+ if (getBounds(i).contains(point)) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Get a ViewerCell for the column at index.
+ *
+ * @param column
+ * @return {@link ViewerCell} or null
if the index is
+ * negative.
+ */
+ public ViewerCell getCell(int column) {
+ if (column >= 0)
+ return new ViewerCell(cast(ViewerRow) clone(), column, getElement());
+
+ return null;
+ }
+
+ /**
+ * Get the Control for the receiver.
+ *
+ * @return {@link Control}
+ */
+ public abstract Control getControl();
+
+ /**
+ * Returns a neighboring row, or null
if no neighbor exists
+ * in the given direction. If sameLevel
is true
,
+ * only sibling rows (under the same parent) will be considered.
+ *
+ * @param direction
+ * the direction {@link #BELOW} or {@link #ABOVE}
+ *
+ * @param sameLevel
+ * if true
, search only within sibling rows
+ * @return the row above/below, or null
if not found
+ */
+ public abstract ViewerRow getNeighbor(int direction, bool sameLevel);
+
+ /**
+ * The tree path used to identify an element by the unique path
+ *
+ * @return the path
+ */
+ public abstract TreePath getTreePath();
+
+ public abstract Object clone();
+
+ /**
+ * @return the model element
+ */
+ public abstract Object getElement();
+
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((getItem() is null) ? 0 : getItem().toHash());
+ return result;
+ }
+
+ public bool equals(Object obj) {
+ if (this is obj)
+ return true;
+ if (obj is null)
+ return false;
+ if (this.classinfo !is obj.classinfo)
+ return false;
+ ViewerRow other = cast(ViewerRow) obj;
+ if (getItem() is null) {
+ if (other.getItem() !is null)
+ return false;
+ } else if (!getItem().opEquals(other.getItem()))
+ return false;
+ return true;
+ }
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/ViewerSorter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/ViewerSorter.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit
+ * The default compare
method compares elements using two steps.
+ * The first step uses the values returned from category
.
+ * By default, all elements are in the same category.
+ * The second level is based on a case insensitive compare of the strings obtained
+ * from the content viewer's label provider via ILabelProvider.getText
.
+ *
+ * Subclasses may implement the isSorterProperty
method;
+ * they may reimplement the category
method to provide
+ * categorization; and they may override the compare
methods
+ * to provide a totally different way of sorting elements.
+ *
+ * It is recommended to use ViewerComparator
instead.
+ *
+ * For example, if DWT starts to support virtual Lists in the future, it should be possible
+ * to create an adapter from AbstractVirtualTable
to ListViewer
in
+ * order to reuse the existing algorithms for deferred updates.
+ *
+ * This is package visiblity by design. It would only need to be made public if there was
+ * a demand to use the deferred content provider algorithms like
+ * BackgroundContentProvider
with non-JFace viewers.
+ *
DeferredContentProvider
.
+ * However, this class will work with anything that implements AbstractVirtualTable
+ * rather than being tied to a TableViewer
.
+ *
+ * + * This is package visiblity since it currently only needs to be used in one place, + * but it could potentially be made public if there was a need to use the same background + * sorting algorithm for something other than a TableViewer. + *
+ * + *+ * Information flow is like this: + *
+ *
+ * Internally, sorting is done using a LazySortedCollection
. This data structure
+ * allows the content provider to locate and sort the visible range without fully sorting
+ * all elements in the table. It also supports fast cancellation, allowing the visible range
+ * to change in the middle of a sort without discarding partially-sorted information from
+ * the previous range.
+ *
ADD
, REMOVE
, SET
, or UPDATE
.
+ * @param elements the elements affected by the change.
+ *
+ * @since 3.1
+ */
+ public this(int type, Object[] elements) {
+ this.type = type;
+ this.elements = elements;
+ }
+
+ /**
+ * Get the type of change.
+ * @return one of ADD
, REMOVE
, SET
, or UPDATE
.
+ *
+ * @since 3.1
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Return the elements associated with the change.
+ * @return the elements affected by the change.
+ *
+ * @since 3.1
+ */
+ public Object[] getElements() {
+ return elements;
+ }
+ }
+
+ private LinkSeq!(Change) queue;
+ private int workload = 0;
+
+ public this(){
+ queue = new LinkSeq!(Change);
+ }
+
+ /**
+ * Create a change of the given type and elements and enqueue it.
+ *
+ * @param type the type of change to be created
+ * @param elements the elements affected by the change
+ */
+ public synchronized void enqueue(int type, Object[] elements) {
+ enqueue(new Change(type, elements));
+ }
+
+ /**
+ * Add the specified change to the queue
+ * @param toQueue the change to be added
+ */
+ public synchronized void enqueue(Change toQueue) {
+ // A SET event makes all previous adds, removes, and sets redundant... so remove
+ // them from the queue
+ if (toQueue.type is SET) {
+ workload = 0;
+ LinkSeq!(Change) newQueue = new LinkSeq!(Change);
+ foreach( next; queue ){
+
+ if (next.getType() is ADD || next.getType() is REMOVE || next.getType() is SET) {
+ continue;
+ }
+
+ newQueue.append(next);
+ workload += next.elements.length;
+ }
+ queue = newQueue;
+ }
+
+ queue.append(toQueue);
+ workload += toQueue.elements.length;
+ }
+
+ /**
+ * Remove the first change from the queue.
+ * @return the first change
+ */
+ public synchronized Change dequeue() {
+ Change result = queue.head;
+ queue.removeHead();
+
+ workload -= result.elements.length;
+ return result;
+ }
+
+ /**
+ * Return whether the queue is empty
+ * @return true
if empty, false
otherwise
+ */
+ public synchronized bool isEmpty() {
+ return queue.drained();
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/ConcurrentTableUpdator.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/deferred/ConcurrentTableUpdator.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit AbstractVirtualTable
interface.
+ *
+ * @since 3.1
+ */
+/* package */ final class ConcurrentTableUpdator {
+ /**
+ * Wrapper for the real table. May only be accessed in the UI thread.
+ */
+ private AbstractVirtualTable table;
+
+ /**
+ * The array of objects that have been sent to the UI. Elements are null
+ * if they either haven't been sent yet or have been scheduled for clear.
+ * Maps indices onto elements.
+ */
+ private Object[] sentObjects;
+
+ /**
+ * Map of elements to object indices (inverse of the knownObjects array)
+ */
+ private IntHashMap knownIndices;
+
+ /**
+ * Contains all known objects that have been sent here from the background
+ * thread.
+ */
+ private Object[] knownObjects;
+
+ // Minimum length for the pendingFlushes stack
+ private static const int MIN_FLUSHLENGTH = 64;
+
+ /**
+ * Array of element indices. Contains elements scheduled to be
+ * cleared. Only the beginning of the array is used. The number
+ * of used elements is stored in lastClear
+ */
+ private int[] pendingClears;
+
+ /**
+ * Number of pending clears in the pendingClears array (this is normally
+ * used instead of pendingClears.length since the
+ * pendingClears array is usually larger than the actual number of pending
+ * clears)
+ */
+ private int lastClear = 0;
+
+ /**
+ * Last known visible range
+ */
+ private /+volatile+/ Range lastRange;
+
+ /**
+ * True iff a UI update has been scheduled
+ */
+ private /+volatile+/ bool updateScheduled;
+
+ /**
+ * True iff this object has been disposed
+ */
+ private /+volatile+/ bool disposed = false;
+
+ /**
+ * Object that holds a start index and length. Allows
+ * the visible range to be returned as an atomic operation.
+ */
+ public final static class Range {
+ int start = 0;
+ int length = 0;
+
+ /**
+ * @param s
+ * @param l
+ */
+ public this(int s, int l) {
+ start = s;
+ length = l;
+ }
+ }
+
+ /**
+ * Runnable that can be posted with an asyncExec to schedule
+ * an update to the real table.
+ */
+ Runnable uiRunnable;
+ private void init_uiRunnable(){
+ uiRunnable = new class Runnable {
+ public void run() {
+ updateScheduled = false;
+ if(!table.getControl().isDisposed()) {
+ updateTable();
+ }
+ }
+ };
+ }
+
+ /**
+ * Creates a new table updator
+ *
+ * @param table real table to update
+ */
+ public this(AbstractVirtualTable table) {
+ init_uiRunnable();
+ knownIndices = new IntHashMap();
+ pendingClears = new int[MIN_FLUSHLENGTH];
+ lastRange = new Range(0,0);
+ this.table = table;
+ }
+
+ /**
+ * Cleans up the updator object (but not the table itself).
+ */
+ public void dispose() {
+ disposed = true;
+ }
+
+ /**
+ * True iff this object has been disposed.
+ *
+ * @return true iff dispose() has been called
+ */
+ public bool isDisposed() {
+ return disposed;
+ }
+
+ /**
+ * Returns the currently visible range
+ *
+ * @return the currently visible range
+ */
+ public Range getVisibleRange() {
+ return lastRange;
+ }
+
+ /**
+ * Marks the given object as dirty. Will cause it to be cleared
+ * in the table.
+ *
+ * @param toFlush
+ */
+ public void clear(Object toFlush) {
+ synchronized(this) {
+ int currentIdx = knownIndices.get(toFlush, -1);
+
+ // If we've never heard of this object, bail out.
+ if (currentIdx is -1) {
+ return;
+ }
+
+ pushClear(currentIdx);
+ }
+
+ }
+
+ /**
+ * Sets the size of the table. Called from a background thread.
+ *
+ * @param newTotal
+ */
+ public void setTotalItems(int newTotal) {
+ synchronized (this) {
+ if (newTotal !is knownObjects.length) {
+ if (newTotal < knownObjects.length) {
+ // Flush any objects that are being removed as a result of the resize
+ for (int i = newTotal; i < knownObjects.length; i++) {
+ Object toFlush = knownObjects[i];
+
+ if (toFlush !is null) {
+ knownIndices.remove(toFlush);
+ }
+ }
+ }
+
+ int minSize = Math.min(knownObjects.length, newTotal);
+
+ Object[] newKnownObjects = new Object[newTotal];
+ System.arraycopy(knownObjects, 0, newKnownObjects, 0, minSize);
+ knownObjects = newKnownObjects;
+
+ scheduleUIUpdate();
+ }
+ }
+ }
+
+ /**
+ * Pushes an index onto the clear stack
+ *
+ * @param toClear row to clear
+ */
+ private void pushClear(int toClear) {
+
+ // If beyond the end of the table
+ if (toClear >= sentObjects.length) {
+ return;
+ }
+
+ // If already flushed or never sent
+ if (sentObjects[toClear] is null) {
+ return;
+ }
+
+ // Mark as flushed
+ sentObjects[toClear] = null;
+
+ if (lastClear >= pendingClears.length) {
+ int newCapacity = Math.min(MIN_FLUSHLENGTH, lastClear * 2);
+ int[] newPendingClears = new int[newCapacity];
+ System.arraycopy(pendingClears, 0, newPendingClears, 0, lastClear);
+ pendingClears = newPendingClears;
+ }
+
+ pendingClears[lastClear++] = toClear;
+ }
+
+ /**
+ * Sets the item on the given row to the given value. May be called from a background
+ * thread. Schedules a UI update if necessary
+ *
+ * @param idx row to change
+ * @param value new value for the given row
+ */
+ public void replace(Object value, int idx) {
+ // Keep the synchronized block as small as possible, since the UI may
+ // be waiting on it.
+ synchronized(this) {
+ Object oldObject = knownObjects[idx];
+
+ if (oldObject !is value) {
+ if (oldObject !is null) {
+ knownIndices.remove(oldObject);
+ }
+
+ knownObjects[idx] = value;
+
+ if (value !is null) {
+ int oldIndex = knownIndices.get(value, -1);
+ if (oldIndex !is -1) {
+ knownObjects[oldIndex] = null;
+ pushClear(oldIndex);
+ }
+
+ knownIndices.put(value, idx);
+ }
+
+ pushClear(idx);
+
+ scheduleUIUpdate();
+ }
+ }
+ }
+
+ /**
+ * Schedules a UI update. Has no effect if an update has already been
+ * scheduled.
+ */
+ private void scheduleUIUpdate() {
+ synchronized(this) {
+ if (!updateScheduled) {
+ updateScheduled = true;
+ if(!table.getControl().isDisposed()) {
+ table.getControl().getDisplay().asyncExec(uiRunnable);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Called in the UI thread by a SetData callback. Refreshes the
+ * table if necessary. Returns true iff a refresh is needed.
+ * @param includeIndex the index that should be included in the visible range.
+ */
+ public void checkVisibleRange(int includeIndex) {
+ int start = Math.min(table.getTopIndex() - 1, includeIndex);
+ int length = Math.max(table.getVisibleItemCount(), includeIndex - start);
+ Range r = lastRange;
+
+ if (start !is r.start || length !is r.length) {
+ updateTable();
+ }
+ }
+
+ /**
+ * Updates the table. Sends any unsent items in the visible range to the table,
+ * and clears any previously-visible items that have not yet been sent to the table.
+ * Must be called from the UI thread.
+ */
+ private void updateTable() {
+
+ synchronized(this) {
+
+ // Resize the table if necessary
+ if (sentObjects.length !is knownObjects.length) {
+ Object[] newSentObjects = new Object[knownObjects.length];
+ System.arraycopy(newSentObjects, 0, sentObjects, 0,
+ Math.min(newSentObjects.length, sentObjects.length));
+ sentObjects = newSentObjects;
+ table.setItemCount(newSentObjects.length);
+ }
+
+ // Compute the currently visible range
+ int start = Math.min(table.getTopIndex(), knownObjects.length);
+ int length = Math.min(table.getVisibleItemCount(), knownObjects.length - start);
+ int itemCount = table.getItemCount();
+
+ int oldStart = lastRange.start;
+ int oldLen = lastRange.length;
+
+ // Store the visible range. Do it BEFORE sending any table.clear calls,
+ // since clearing a visible row will result in a SetData callback which
+ // cause another table update if the visible range is different from
+ // the stored values -- this could cause infinite recursion.
+ lastRange = new Range(start, length);
+
+ // Re-clear any items in the old range that were never filled in
+ for(int idx = 0; idx < oldLen; idx++) {
+ int row = idx + oldStart;
+
+ // If this item is no longer visible
+ if (row < itemCount && (row < start || row >= start + length)) {
+
+ // Note: if we wanted to be really aggressive about clearing
+ // items that are no longer visible, we could clear here unconditionally.
+ // The current way of doing things won't clear a row if its contents are
+ // up-to-date.
+ if (sentObjects[row] is null) {
+ table.clear(row);
+ }
+ }
+ }
+
+ // Process any pending clears
+ if (lastClear > 0) {
+ for (int i = 0; i < lastClear; i++) {
+ int row = pendingClears[i];
+
+ if (row < sentObjects.length) {
+ table.clear(row);
+ }
+ }
+
+ if (pendingClears.length > MIN_FLUSHLENGTH) {
+ pendingClears = new int[MIN_FLUSHLENGTH];
+ }
+ lastClear = 0;
+ }
+
+ // Send any unsent items in the visible range
+ for (int idx = 0; idx < length; idx++) {
+ int row = idx + start;
+
+ Object obj = knownObjects[row];
+ if (obj !is null && obj !is sentObjects[idx]) {
+ table.replace(obj, row);
+ sentObjects[idx] = obj;
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Return the array of all known objects that have been sent here from the background
+ * thread.
+ * @return the array of all known objects
+ */
+ public Object[] getKnownObjects() {
+ return knownObjects;
+ }
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/DeferredContentProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/deferred/DeferredContentProvider.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit TableViewer
created with the DWT.VIRTUAL
+ * flag and an IConcurrentModel
as input.
+ * + * The sorter and filter must be set directly on the content provider. + * Any sorter or filter on the TableViewer will be ignored. + *
+ * + *
+ * The real implementation is in BackgroundContentProvider
. This
+ * object is a lightweight wrapper that adapts the algorithm to work with
+ * TableViewer
.
+ *
TableViewer
.
+ *
+ * @param sortOrder new sort order. The comparator must be able to support being
+ * used in a background thread.
+ */
+ public void setSortOrder(Comparator sortOrder) {
+ Assert.isNotNull(cast(Object)sortOrder);
+ this.sortOrder = sortOrder;
+ if (provider !is null) {
+ provider.setSortOrder(sortOrder);
+ }
+ }
+
+ /**
+ * Sets the filter for this content provider. This filter takes priority over
+ * anything that was supplied to the TableViewer
. The filter
+ * must be capable of being used in a background thread.
+ *
+ * @param toSet filter to set
+ */
+ public void setFilter(IFilter toSet) {
+ this.filter = toSet;
+ if (provider !is null) {
+ provider.setFilter(toSet);
+ }
+ }
+
+ /**
+ * Sets the maximum number of rows in the table. If the model contains more
+ * than this number of elements, only the top elements will be shown based on
+ * the current sort order.
+ *
+ * @param limit maximum number of rows to show or -1 if unbounded
+ */
+ public void setLimit(int limit) {
+ this.limit = limit;
+ if (provider !is null) {
+ provider.setLimit(limit);
+ }
+ }
+
+ /**
+ * Returns the current maximum number of rows or -1 if unbounded
+ *
+ * @return the current maximum number of rows or -1 if unbounded
+ */
+ public int getLimit() {
+ return limit;
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.ILazyContentProvider#updateElement(int)
+ */
+ public void updateElement(int element) {
+ if (provider !is null) {
+ provider.checkVisibleRange(element);
+ }
+ }
+
+ private void setProvider(BackgroundContentProvider newProvider) {
+ if (provider !is null) {
+ provider.dispose();
+ }
+
+ provider = newProvider;
+ }
+
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/FastProgressReporter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/deferred/FastProgressReporter.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if the monitor has been cancelled, false
otherwise.
+ */
+ public bool isCanceled() {
+ if (monitor is null) {
+ return canceled;
+ }
+
+ cancelCheck++;
+ if (cancelCheck > CANCEL_CHECK_PERIOD) {
+ canceled = monitor.isCanceled();
+ cancelCheck = 0;
+ }
+ return canceled;
+ }
+
+ /**
+ * Cancel the progress monitor.
+ */
+ public void cancel() {
+ canceled = true;
+
+ if (monitor is null) {
+ return;
+ }
+ monitor.setCanceled(true);
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/IConcurrentModel.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/deferred/IConcurrentModel.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * The model is allowed to send back notifications to its listeners in any thread, + * and the listeners must not assume that the notifications will arrive in the UI + * thread. + *
+ * + *
+ * Not intended to be implemented by clients. Clients should subclass
+ * AbstractConcurrentModel
instead.
+ *
+ * Has no effect if an update is already queued for an identical listener. + *
+ * + * @param listener listener whose setContents method should be called. The + * listener must have been previously registered with addListener. + */ + public void requestUpdate(IConcurrentModelListener listener); + + /** + * Adds a listener to this model. The listener should be given the model's + * current contents (either through setContents or a sequence of adds) at the + * receiver's earliest convenience. The receiver will notify the listener + * about any changes in state until the listener is removed. + * + *+ * Has no effect if an identical listener is already registered. + *
+ * + * @param listener listener to add + */ + public void addListener(IConcurrentModelListener listener); + + /** + * Removes a listener from this model. The receiver will stop sending + * notifications to the given listener as soon as possible (although + * some additional notifications may still if arrive if the receiver + * was in the process of sending notifications in another thread). + * Any pending updates for this listener will be cancelled. + *+ * Has no effect if the given listener is not known to this model. + *
+ * + * @param listener listener to remove + */ + public void removeListener(IConcurrentModelListener listener); +} diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/IConcurrentModelListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/viewers/deferred/IConcurrentModelListener.d Mon Mar 31 00:47:19 2008 +0200 @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2004, 2005 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank BenoitIConcurrentModel.requestUpdate
+ *
+ * @param newContents contents of the model
+ */
+ public void setContents(Object[] newContents);
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/IntHashMap.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/deferred/IntHashMap.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if this map contains the given key, false
otherwise
+ */
+ public bool containsKey(Object key) {
+ return map.containsKey(key);
+ }
+
+ /**
+ * @return the number of key/value pairs
+ */
+ public int size() {
+ return map.size();
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/LazySortedCollection.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/deferred/LazySortedCollection.d Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,1449 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * This is a modified binary search tree. Each subtree has a value, a left and right subtree, + * a count of the number of children, and a set of unsorted children. + * Insertion happens lazily. When a new node N is inserted into a subtree T, it is initially + * added to the set of unsorted children for T without actually comparing it with the value for T. + *
+ *+ * The unsorted children will remain in the unsorted set until some subsequent operation requires + * us to know the exact set of elements in one of the subtrees. At that time, we partition + * T by comparing all of its unsorted children with T's value and moving them into the left + * or right subtrees. + *
+ * + * @since 3.1 + */ +public class LazySortedCollection { + private const int MIN_CAPACITY = 8; + private Object[] contents; + private int[] leftSubTree; + private int[] rightSubTree; + private int[] nextUnsorted; + private int[] treeSize; + private int[] parentTree; + private int root = -1; + private int lastNode = 0; + private int firstUnusedNode = -1; + + private static const float loadFactor = 0.75f; + + private IntHashMap objectIndices; + private Comparator comparator; + private static int counter = 0; + + /** + * Disables randomization and enables additional runtime error checking. + * Severely degrades performance if set to true. Intended for use in test + * suites only. + */ + public bool enableDebug = false; + + // This object is inserted as the value into any node scheduled for lazy removal + private Object lazyRemovalFlag; + + private void init_instance(){ + contents = new Object[MIN_CAPACITY]; + leftSubTree = new int[MIN_CAPACITY]; + rightSubTree = new int[MIN_CAPACITY]; + nextUnsorted = new int[MIN_CAPACITY]; + treeSize = new int[MIN_CAPACITY]; + parentTree = new int[MIN_CAPACITY]; + lazyRemovalFlag = new class Object { + public String toString() { + return "Lazy removal flag"; //$NON-NLS-1$ + } + }; + } + + private const static int DIR_LEFT = 0; + private const static int DIR_RIGHT = 1; + private const static int DIR_UNSORTED = 2; + + // Direction constants indicating root nodes + private const static int DIR_ROOT = 3; + private const static int DIR_UNUSED = 4; + + private final class Edge { + private int startNode; + private int direction; + + private this() { + startNode = -1; + direction = -1; + } + + private this(int node, int dir) { + startNode = node; + direction = dir; + } + + private int getStart() { + return startNode; + } + + private int getTarget() { + if (startNode is -1) { + if (direction is DIR_UNSORTED) { + return firstUnusedNode; + } else if (direction is DIR_ROOT) { + return root; + } + return -1; + } + + if (direction is DIR_LEFT) { + return leftSubTree[startNode]; + } + if (direction is DIR_RIGHT) { + return rightSubTree[startNode]; + } + return nextUnsorted[startNode]; + } + + private bool isNull() { + return getTarget() is -1; + } + + /** + * Redirects this edge to a new node + * @param newNode + * @since 3.1 + */ + private void setTarget(int newNode) { + if (direction is DIR_LEFT) { + leftSubTree[startNode] = newNode; + } else if (direction is DIR_RIGHT) { + rightSubTree[startNode] = newNode; + } else if (direction is DIR_UNSORTED) { + nextUnsorted[startNode] = newNode; + } else if (direction is DIR_ROOT) { + root = newNode; + } else if (direction is DIR_UNUSED) { + firstUnusedNode = newNode; + } + + if (newNode !is -1) { + parentTree[newNode] = startNode; + } + } + + private void advance(int direction) { + startNode = getTarget(); + this.direction = direction; + } + } + + private void setRootNode(int node) { + root = node; + if (node !is -1) { + parentTree[node] = -1; + } + } + + /** + * Creates a new sorted collection using the given comparator to determine + * sort order. + * + * @param c comparator that determines the sort order + */ + public this(Comparator c) { + this.comparator = c; + init_instance(); + } + + /** + * Tests if this object's internal state is valid. Throws a runtime + * exception if the state is invalid, indicating a programming error + * in this class. This method is intended for use in test + * suites and should not be called by clients. + */ + public void testInvariants() { + if (!enableDebug) { + return; + } + + testInvariants(root); + } + + private void testInvariants(int node) { + if (node is -1) { + return; + } + + // Get the current tree size (we will later force the tree size + // to be recomputed from scratch -- if everything works properly, then + // there should be no change. + int treeSize = getSubtreeSize(node); + + int left = leftSubTree[node]; + int right = rightSubTree[node]; + int unsorted = nextUnsorted[node]; + + if (isUnsorted(node)) { + Assert.isTrue(left is -1, "unsorted nodes shouldn't have a left subtree"); //$NON-NLS-1$ + Assert.isTrue(right is -1, "unsorted nodes shouldn't have a right subtree"); //$NON-NLS-1$ + } + + if (left !is -1) { + testInvariants(left); + Assert.isTrue(parentTree[left] is node, "left node has invalid parent pointer"); //$NON-NLS-1$ + } + if (right !is -1) { + testInvariants(right); + Assert.isTrue(parentTree[right] is node, "right node has invalid parent pointer"); //$NON-NLS-1$ + } + + int previous = node; + while (unsorted !is -1) { + int oldTreeSize = this.treeSize[unsorted]; + recomputeTreeSize(unsorted); + + Assert.isTrue(this.treeSize[unsorted] is oldTreeSize, + "Invalid node size for unsorted node"); //$NON-NLS-1$ + Assert.isTrue(leftSubTree[unsorted] is -1, "unsorted nodes shouldn't have left subtrees"); //$NON-NLS-1$ + Assert.isTrue(rightSubTree[unsorted] is -1, "unsorted nodes shouldn't have right subtrees"); //$NON-NLS-1$ + Assert.isTrue(parentTree[unsorted] is previous, "unsorted node has invalid parent pointer"); //$NON-NLS-1$ + Assert.isTrue(contents[unsorted] !is lazyRemovalFlag, "unsorted nodes should not be lazily removed"); //$NON-NLS-1$ + previous = unsorted; + unsorted = nextUnsorted[unsorted]; + } + + // Note that we've already tested that the child sizes are correct... if our size is + // correct, then recomputing it now should not cause any change. + recomputeTreeSize(node); + + Assert.isTrue(treeSize is getSubtreeSize(node), "invalid tree size"); //$NON-NLS-1$ + } + + private bool isUnsorted(int node) { + int parent = parentTree[node]; + + if (parent !is -1) { + return nextUnsorted[parent] is node; + } + + return false; + } + + private final bool isLess(int element1, int element2) { + return comparator.compare(contents[element1], contents[element2]) < 0; + } + + /** + * Adds the given element to the given subtree. Returns the new + * root of the subtree. + * + * @param subTree index of the subtree to insert elementToAdd into. If -1, + * then a new subtree will be created for elementToAdd + * @param elementToAdd index of the element to add to the subtree. If -1, this method + * is a NOP. + * @since 3.1 + */ + private final int addUnsorted(int subTree, int elementToAdd) { + if (elementToAdd is -1) { + return subTree; + } + + if (subTree is -1) { + nextUnsorted[elementToAdd] = -1; + treeSize[elementToAdd] = 1; + return elementToAdd; + } + + // If the subTree is empty (ie: it only contains nodes flagged for lazy removal), + // chop it off. + if (treeSize[subTree] is 0) { + removeSubTree(subTree); + nextUnsorted[elementToAdd] = -1; + treeSize[elementToAdd] = 1; + return elementToAdd; + } + + // If neither subtree has any children, add a pseudorandom chance of the + // newly added element becoming the new pivot for this node. Note: instead + // of a real pseudorandom generator, we simply use a counter here. + if (!enableDebug && leftSubTree[subTree] is -1 && rightSubTree[subTree] is -1 + && leftSubTree[elementToAdd] is -1 && rightSubTree[elementToAdd] is -1) { + counter--; + + if (counter % treeSize[subTree] is 0) { + // Make the new node into the new pivot + nextUnsorted[elementToAdd] = subTree; + parentTree[elementToAdd] = parentTree[subTree]; + parentTree[subTree] = elementToAdd; + treeSize[elementToAdd] = treeSize[subTree] + 1; + return elementToAdd; + } + } + + int oldNextUnsorted = nextUnsorted[subTree]; + nextUnsorted[elementToAdd] = oldNextUnsorted; + + if (oldNextUnsorted is -1) { + treeSize[elementToAdd] = 1; + } else { + treeSize[elementToAdd] = treeSize[oldNextUnsorted] + 1; + parentTree[oldNextUnsorted] = elementToAdd; + } + + parentTree[elementToAdd] = subTree; + + nextUnsorted[subTree] = elementToAdd; + treeSize[subTree]++; + return subTree; + } + + /** + * Returns the number of elements in the collection + * + * @return the number of elements in the collection + */ + public int size() { + int result = getSubtreeSize(root); + + testInvariants(); + + return result; + } + + /** + * Given a tree and one of its unsorted children, this sorts the child by moving + * it into the left or right subtrees. Returns the next unsorted child or -1 if none + * + * @param subTree parent tree + * @param toMove child (unsorted) subtree + * @since 3.1 + */ + private final int partition(int subTree, int toMove) { + int result = nextUnsorted[toMove]; + + if (isLess(toMove, subTree)) { + int nextLeft = addUnsorted(leftSubTree[subTree], toMove); + leftSubTree[subTree] = nextLeft; + parentTree[nextLeft] = subTree; + } else { + int nextRight = addUnsorted(rightSubTree[subTree], toMove); + rightSubTree[subTree] = nextRight; + parentTree[nextRight] = subTree; + } + + return result; + } + + /** + * Partitions the given subtree. Moves all unsorted elements at the given node + * to either the left or right subtrees. If the node itself was scheduled for + * lazy removal, this will force the node to be removed immediately. Returns + * the new subTree. + * + * @param subTree + * @return the replacement node (this may be different from subTree if the subtree + * was replaced during the removal) + * @since 3.1 + */ + private final int partition(int subTree, FastProgressReporter mon) { + if (subTree is -1) { + return -1; + } + + if (contents[subTree] is lazyRemovalFlag) { + subTree = removeNode(subTree); + if (subTree is -1) { + return -1; + } + } + + for (int idx = nextUnsorted[subTree]; idx !is -1;) { + idx = partition(subTree, idx); + nextUnsorted[subTree] = idx; + if (idx !is -1) { + parentTree[idx] = subTree; + } + + if (mon.isCanceled()) { + throw new InterruptedException(); + } + } + + // At this point, there are no remaining unsorted nodes in this subtree + nextUnsorted[subTree] = -1; + + return subTree; + } + + private final int getSubtreeSize(int subTree) { + if (subTree is -1) { + return 0; + } + return treeSize[subTree]; + } + + /** + * Increases the capacity of this collection, if necessary, so that it can hold the + * given number of elements. This can be used prior to a sequence of additions to + * avoid memory reallocation. This cannot be used to reduce the amount + * of memory used by the collection. + * + * @param newSize capacity for this collection + */ + public final void setCapacity(int newSize) { + if (newSize > contents.length) { + setArraySize(newSize); + } + } + + /** + * Adjusts the capacity of the array. + * + * @param newCapacity + */ + private final void setArraySize(int newCapacity) { + Object[] newContents = new Object[newCapacity]; + System.arraycopy(contents, 0, newContents, 0, lastNode); + contents = newContents; + + int[] newLeftSubTree = new int[newCapacity]; + System.arraycopy(leftSubTree, 0, newLeftSubTree, 0, lastNode); + leftSubTree = newLeftSubTree; + + int[] newRightSubTree = new int[newCapacity]; + System.arraycopy(rightSubTree, 0, newRightSubTree, 0, lastNode); + rightSubTree = newRightSubTree; + + int[] newNextUnsorted = new int[newCapacity]; + System.arraycopy(nextUnsorted, 0, newNextUnsorted, 0, lastNode); + nextUnsorted = newNextUnsorted; + + int[] newTreeSize = new int[newCapacity]; + System.arraycopy(treeSize, 0, newTreeSize, 0, lastNode); + treeSize = newTreeSize; + + int[] newParentTree = new int[newCapacity]; + System.arraycopy(parentTree, 0, newParentTree, 0, lastNode); + parentTree = newParentTree; + } + + /** + * Creates a new node with the given value. Returns the index of the newly + * created node. + * + * @param value + * @return the index of the newly created node + * @since 3.1 + */ + private final int createNode(Object value) { + int result = -1; + + if (firstUnusedNode is -1) { + // If there are no unused nodes from prior removals, then + // we add a node at the end + result = lastNode; + + // If this would cause the array to overflow, reallocate the array + if (contents.length <= lastNode) { + setCapacity(lastNode * 2); + } + + lastNode++; + } else { + // Reuse a node from a prior removal + result = firstUnusedNode; + firstUnusedNode = nextUnsorted[result]; + } + + contents[result] = value; + treeSize[result] = 1; + + // Clear pointers + leftSubTree[result] = -1; + rightSubTree[result] = -1; + nextUnsorted[result] = -1; + + // As long as we have a hash table of values onto tree indices, incrementally + // update the hash table. Note: the table is only constructed as needed, and it + // is destroyed whenever the arrays are reallocated instead of reallocating it. + if (objectIndices !is null) { + objectIndices.put(value, result); + } + + return result; + } + + /** + * Returns the current tree index for the given object. + * + * @param value + * @return the current tree index + * @since 3.1 + */ + private int getObjectIndex(Object value) { + // If we don't have a map of values onto tree indices, build the map now. + if (objectIndices is null) { + int result = -1; + + objectIndices = new IntHashMap(cast(int)(contents.length / loadFactor) + 1, loadFactor); + + for (int i = 0; i < lastNode; i++) { + Object element = contents[i]; + + if (element !is null && element !is lazyRemovalFlag) { + objectIndices.put(element, i); + + if (value is element) { + result = i; + } + } + } + + return result; + } + + // If we have a map of values onto tree indices, return the result by looking it up in + // the map + return objectIndices.get(value, -1); + } + + /** + * Redirects any pointers from the original to the replacement. If the replacement + * causes a change in the number of elements in the parent tree, the changes are + * propogated toward the root. + * + * @param nodeToReplace + * @param replacementNode + * @since 3.1 + */ + private void replaceNode(int nodeToReplace, int replacementNode) { + int parent = parentTree[nodeToReplace]; + + if (parent is -1) { + if (root is nodeToReplace) { + setRootNode(replacementNode); + } + } else { + if (leftSubTree[parent] is nodeToReplace) { + leftSubTree[parent] = replacementNode; + } else if (rightSubTree[parent] is nodeToReplace) { + rightSubTree[parent] = replacementNode; + } else if (nextUnsorted[parent] is nodeToReplace) { + nextUnsorted[parent] = replacementNode; + } + if (replacementNode !is -1) { + parentTree[replacementNode] = parent; + } + } + } + + private void recomputeAncestorTreeSizes(int node) { + while (node !is -1) { + int oldSize = treeSize[node]; + + recomputeTreeSize(node); + + if (treeSize[node] is oldSize) { + break; + } + + node = parentTree[node]; + } + } + + /** + * Recomputes the tree size for the given node. + * + * @param node + * @since 3.1 + */ + private void recomputeTreeSize(int node) { + if (node is -1) { + return; + } + treeSize[node] = getSubtreeSize(leftSubTree[node]) + + getSubtreeSize(rightSubTree[node]) + + getSubtreeSize(nextUnsorted[node]) + + (contents[node] is lazyRemovalFlag ? 0 : 1); + } + + /** + * + * @param toRecompute + * @param whereToStop + * @since 3.1 + */ + private void forceRecomputeTreeSize(int toRecompute, int whereToStop) { + while (toRecompute !is -1 && toRecompute !is whereToStop) { + recomputeTreeSize(toRecompute); + + toRecompute = parentTree[toRecompute]; + } + } + + /** + * Destroy the node at the given index in the tree + * @param nodeToDestroy + * @since 3.1 + */ + private void destroyNode(int nodeToDestroy) { + // If we're maintaining a map of values onto tree indices, remove this entry from + // the map + if (objectIndices !is null) { + Object oldContents = contents[nodeToDestroy]; + if (oldContents !is lazyRemovalFlag) { + objectIndices.remove(oldContents); + } + } + + contents[nodeToDestroy] = null; + leftSubTree[nodeToDestroy] = -1; + rightSubTree[nodeToDestroy] = -1; + + if (firstUnusedNode is -1) { + treeSize[nodeToDestroy] = 1; + } else { + treeSize[nodeToDestroy] = treeSize[firstUnusedNode] + 1; + parentTree[firstUnusedNode] = nodeToDestroy; + } + + nextUnsorted[nodeToDestroy] = firstUnusedNode; + + firstUnusedNode = nodeToDestroy; + } + + /** + * Frees up memory by clearing the list of nodes that have been freed up through removals. + * + * @since 3.1 + */ + private final void pack() { + + // If there are no unused nodes, then there is nothing to do + if (firstUnusedNode is -1) { + return; + } + + int reusableNodes = getSubtreeSize(firstUnusedNode); + int nonPackableNodes = lastNode - reusableNodes; + + // Only pack the array if we're utilizing less than 1/4 of the array (note: + // this check is important, or it will change the time bounds for removals) + if (contents.length < MIN_CAPACITY || nonPackableNodes > contents.length / 4) { + return; + } + + // Rather than update the entire map, just null it out. If it is needed, + // it will be recreated lazily later. This will save some memory if the + // map isn't needed, and it takes a similar amount of time to recreate the + // map as to update all the indices. + objectIndices = null; + + // Maps old index -> new index + int[] mapNewIdxOntoOld = new int[contents.length]; + int[] mapOldIdxOntoNew = new int[contents.length]; + + int nextNewIdx = 0; + // Compute the mapping. Determine the new index for each element + for (int oldIdx = 0; oldIdx < lastNode; oldIdx++) { + if (contents[oldIdx] !is null) { + mapOldIdxOntoNew[oldIdx] = nextNewIdx; + mapNewIdxOntoOld[nextNewIdx] = oldIdx; + nextNewIdx++; + } else { + mapOldIdxOntoNew[oldIdx] = -1; + } + } + + // Make the actual array size double the number of nodes to allow + // for expansion. + int newNodes = nextNewIdx; + int newCapacity = Math.max(newNodes * 2, MIN_CAPACITY); + + // Allocate new arrays + Object[] newContents = new Object[newCapacity]; + int[] newTreeSize = new int[newCapacity]; + int[] newNextUnsorted = new int[newCapacity]; + int[] newLeftSubTree = new int[newCapacity]; + int[] newRightSubTree = new int[newCapacity]; + int[] newParentTree = new int[newCapacity]; + + for (int newIdx = 0; newIdx < newNodes; newIdx++) { + int oldIdx = mapNewIdxOntoOld[newIdx]; + newContents[newIdx] = contents[oldIdx]; + newTreeSize[newIdx] = treeSize[oldIdx]; + + int left = leftSubTree[oldIdx]; + if (left is -1) { + newLeftSubTree[newIdx] = -1; + } else { + newLeftSubTree[newIdx] = mapOldIdxOntoNew[left]; + } + + int right = rightSubTree[oldIdx]; + if (right is -1) { + newRightSubTree[newIdx] = -1; + } else { + newRightSubTree[newIdx] = mapOldIdxOntoNew[right]; + } + + int unsorted = nextUnsorted[oldIdx]; + if (unsorted is -1) { + newNextUnsorted[newIdx] = -1; + } else { + newNextUnsorted[newIdx] = mapOldIdxOntoNew[unsorted]; + } + + int parent = parentTree[oldIdx]; + if (parent is -1) { + newParentTree[newIdx] = -1; + } else { + newParentTree[newIdx] = mapOldIdxOntoNew[parent]; + } + } + + contents = newContents; + nextUnsorted = newNextUnsorted; + treeSize = newTreeSize; + leftSubTree = newLeftSubTree; + rightSubTree = newRightSubTree; + parentTree = newParentTree; + + if (root !is -1) { + root = mapOldIdxOntoNew[root]; + } + + // All unused nodes have been removed + firstUnusedNode = -1; + lastNode = newNodes; + } + + /** + * Adds the given object to the collection. Runs in O(1) amortized time. + * + * @param toAdd object to add + */ + public final void add(Object toAdd) { + Assert.isNotNull(toAdd); + // Create the new node + int newIdx = createNode(toAdd); + + // Insert the new node into the root tree + setRootNode(addUnsorted(root, newIdx)); + + testInvariants(); + } + + /** + * Adds all items from the given collection to this collection + * + * @param toAdd objects to add + */ + public final void addAll( View!(Object) toAdd) { + Assert.isNotNull(cast(Object)toAdd); + foreach( o; toAdd ){ + add( o ); + } + + testInvariants(); + } + + /** + * Adds all items from the given array to the collection + * + * @param toAdd objects to add + */ + public final void addAll(Object[] toAdd) { +// Assert.isNotNull(toAdd); + for (int i = 0; i < toAdd.length; i++) { + Object object = toAdd[i]; + + add(object); + } + + testInvariants(); + } + + /** + * Returns true iff the collection is empty + * + * @return true iff the collection contains no elements + */ + public final bool isEmpty() { + bool result = (root is -1); + + testInvariants(); + + return result; + } + + /** + * Removes the given object from the collection. Has no effect if + * the element does not exist in this collection. + * + * @param toRemove element to remove + */ + public final void remove(Object toRemove) { + internalRemove(toRemove); + + pack(); + + testInvariants(); + } + + /** + * Internal implementation of remove. Removes the given element but does not + * pack the container after the removal. + * + * @param toRemove element to remove + */ + private void internalRemove(Object toRemove) { + int objectIndex = getObjectIndex(toRemove); + + if (objectIndex !is -1) { + int parent = parentTree[objectIndex]; + lazyRemoveNode(objectIndex); + //Edge parentEdge = getEdgeTo(objectIndex); + //parentEdge.setTarget(lazyRemoveNode(objectIndex)); + recomputeAncestorTreeSizes(parent); + } + + //testInvariants(); + } + + /** + * Removes all elements in the given array from this collection. + * + * @param toRemove elements to remove + */ + public final void removeAll(Object[] toRemove) { +// Assert.isNotNull(toRemove); + + for (int i = 0; i < toRemove.length; i++) { + Object object = toRemove[i]; + + internalRemove(object); + } + pack(); + } + + /** + * Retains the n smallest items in the collection, removing the rest. When + * this method returns, the size of the collection will be n. Note that + * this is a no-op if n > the current size of the collection. + * + * Temporarily package visibility until the implementation of FastProgressReporter + * is finished. + * + * @param n number of items to retain + * @param mon progress monitor + * @throws InterruptedException if the progress monitor is cancelled in another thread + */ + /* package */ final void retainFirst(int n, FastProgressReporter mon) { + int sz = size(); + + if (n >= sz) { + return; + } + + removeRange(n, sz - n, mon); + + testInvariants(); + } + + /** + * Retains the n smallest items in the collection, removing the rest. When + * this method returns, the size of the collection will be n. Note that + * this is a no-op if n > the current size of the collection. + * + * @param n number of items to retain + */ + public final void retainFirst(int n) { + try { + retainFirst(n, new FastProgressReporter()); + } catch (InterruptedException e) { + } + + testInvariants(); + } + + /** + * Removes all elements in the given range from this collection. + * For example, removeRange(10, 3) would remove the 11th through 13th + * smallest items from the collection. + * + * @param first 0-based index of the smallest item to remove + * @param length number of items to remove + */ + public final void removeRange(int first, int length) { + try { + removeRange(first, length, new FastProgressReporter()); + } catch (InterruptedException e) { + } + + testInvariants(); + } + + /** + * Removes all elements in the given range from this collection. + * For example, removeRange(10, 3) would remove the 11th through 13th + * smallest items from the collection. + * + * Temporarily package visiblity until the implementation of FastProgressReporter is + * finished. + * + * @param first 0-based index of the smallest item to remove + * @param length number of items to remove + * @param mon progress monitor + * @throws InterruptedException if the progress monitor is cancelled in another thread + */ + /* package */ final void removeRange(int first, int length, FastProgressReporter mon) { + removeRange(root, first, length, mon); + + pack(); + + testInvariants(); + } + + private final void removeRange(int node, int rangeStart, int rangeLength, FastProgressReporter mon) { + if (rangeLength is 0) { + return; + } + + int size = getSubtreeSize(node); + + if (size <= rangeStart) { + return; + } + + // If we can chop off this entire subtree without any sorting, do so. + if (rangeStart is 0 && rangeLength >= size) { + removeSubTree(node); + return; + } + try { + // Partition any unsorted nodes + node = partition(node, mon); + + int left = leftSubTree[node]; + int leftSize = getSubtreeSize(left); + + int toRemoveFromLeft = Math.min(leftSize - rangeStart, rangeLength); + + // If we're removing anything from the left node + if (toRemoveFromLeft >= 0) { + removeRange(leftSubTree[node], rangeStart, toRemoveFromLeft, mon); + + // Check if we're removing from both sides + int toRemoveFromRight = rangeStart + rangeLength - leftSize - 1; + + if (toRemoveFromRight >= 0) { + // Remove from right subtree + removeRange(rightSubTree[node], 0, toRemoveFromRight, mon); + + // ... removing from both sides means we need to remove the node itself too + removeNode(node); + return; + } + } else { + // If removing from the right side only + removeRange(rightSubTree[node], rangeStart - leftSize - 1, rangeLength, mon); + } + } finally { + recomputeTreeSize(node); + } + } + + /** + * Prunes the given subtree (and all child nodes, sorted or unsorted). + * + * @param subTree + * @since 3.1 + */ + private final void removeSubTree(int subTree) { + if (subTree is -1) { + return; + } + + // Destroy all unsorted nodes + for (int next = nextUnsorted[subTree]; next !is -1;) { + int current = next; + next = nextUnsorted[next]; + + // Destroy this unsorted node + destroyNode(current); + } + + // Destroy left subtree + removeSubTree(leftSubTree[subTree]); + + // Destroy right subtree + removeSubTree(rightSubTree[subTree]); + + replaceNode(subTree, -1); + // Destroy pivot node + destroyNode(subTree); + } + + /** + * Schedules the node for removal. If the node can be removed in constant time, + * it is removed immediately. + * + * @param subTree + * @return the replacement node + * @since 3.1 + */ + private final int lazyRemoveNode(int subTree) { + int left = leftSubTree[subTree]; + int right = rightSubTree[subTree]; + + // If this is a leaf node, remove it immediately + if (left is -1 && right is -1) { + int result = nextUnsorted[subTree]; + replaceNode(subTree, result); + destroyNode(subTree); + return result; + } + + // Otherwise, flag it for future removal + Object value = contents[subTree]; + contents[subTree] = lazyRemovalFlag; + treeSize[subTree]--; + if (objectIndices !is null) { + objectIndices.remove(value); + } + + return subTree; + } + + /** + * Removes the given subtree, replacing it with one of its children. + * Returns the new root of the subtree + * + * @param subTree + * @return the index of the new root + * @since 3.1 + */ + private final int removeNode(int subTree) { + int left = leftSubTree[subTree]; + int right = rightSubTree[subTree]; + + if (left is -1 || right is -1) { + int result = -1; + + if (left is -1 && right is -1) { + // If this is a leaf node, replace it with its first unsorted child + result = nextUnsorted[subTree]; + } else { + // Either the left or right child is missing -- replace with the remaining child + if (left is -1) { + result = right; + } else { + result = left; + } + + try { + result = partition(result, new FastProgressReporter()); + } catch (InterruptedException e) { + + } + if (result is -1) { + result = nextUnsorted[subTree]; + } else { + int unsorted = nextUnsorted[subTree]; + nextUnsorted[result] = unsorted; + int additionalNodes = 0; + if (unsorted !is -1) { + parentTree[unsorted] = result; + additionalNodes = treeSize[unsorted]; + } + treeSize[result] += additionalNodes; + } + } + + replaceNode(subTree, result); + destroyNode(subTree); + return result; + } + + // Find the edges that lead to the next-smallest and + // next-largest nodes + Edge nextSmallest = new Edge(subTree, DIR_LEFT); + while (!nextSmallest.isNull()) { + nextSmallest.advance(DIR_RIGHT); + } + + Edge nextLargest = new Edge(subTree, DIR_RIGHT); + while (!nextLargest.isNull()) { + nextLargest.advance(DIR_LEFT); + } + + // Index of the replacement node + int replacementNode = -1; + + // Count of number of nodes moved to the right + + int leftSize = getSubtreeSize(left); + int rightSize = getSubtreeSize(right); + + // Swap with a child from the larger subtree + if (leftSize > rightSize) { + replacementNode = nextSmallest.getStart(); + + // Move any unsorted nodes that are larger than the replacement node into + // the left subtree of the next-largest node + Edge unsorted = new Edge(replacementNode, DIR_UNSORTED); + while (!unsorted.isNull()) { + int target = unsorted.getTarget(); + + if (!isLess(target, replacementNode)) { + unsorted.setTarget(nextUnsorted[target]); + nextLargest.setTarget(addUnsorted(nextLargest.getTarget(), target)); + } else { + unsorted.advance(DIR_UNSORTED); + } + } + + forceRecomputeTreeSize(unsorted.getStart(), replacementNode); + forceRecomputeTreeSize(nextLargest.getStart(), subTree); + } else { + replacementNode = nextLargest.getStart(); + + // Move any unsorted nodes that are smaller than the replacement node into + // the right subtree of the next-smallest node + Edge unsorted = new Edge(replacementNode, DIR_UNSORTED); + while (!unsorted.isNull()) { + int target = unsorted.getTarget(); + + if (isLess(target, replacementNode)) { + unsorted.setTarget(nextUnsorted[target]); + nextSmallest.setTarget(addUnsorted(nextSmallest.getTarget(), target)); + } else { + unsorted.advance(DIR_UNSORTED); + } + } + + forceRecomputeTreeSize(unsorted.getStart(), replacementNode); + forceRecomputeTreeSize(nextSmallest.getStart(), subTree); + } + + // Now all the affected treeSize[...] elements should be updated to reflect the + // unsorted nodes that moved. Swap nodes. + Object replacementContent = contents[replacementNode]; + contents[replacementNode] = contents[subTree]; + contents[subTree] = replacementContent; + + if (objectIndices !is null) { + objectIndices.put(replacementContent, subTree); + // Note: currently we don't bother updating the index of the replacement + // node since we're going to remove it immediately afterwards and there's + // no good reason to search for the index in a method that was given the + // index as a parameter... + + // objectIndices.put(contents[replacementNode], replacementNode) + } + + int replacementParent = parentTree[replacementNode]; + + replaceNode(replacementNode, removeNode(replacementNode)); + //Edge parentEdge = getEdgeTo(replacementNode); + //parentEdge.setTarget(removeNode(replacementNode)); + + forceRecomputeTreeSize(replacementParent, subTree); + recomputeTreeSize(subTree); + + //testInvariants(); + + return subTree; + } + + /** + * Removes all elements from the collection + */ + public final void clear() { + lastNode = 0; + setArraySize(MIN_CAPACITY); + root = -1; + firstUnusedNode = -1; + objectIndices = null; + + testInvariants(); + } + + /** + * Returns the comparator that is determining the sort order for this collection + * + * @return comparator for this collection + */ + public Comparator getComparator() { + return comparator; + } + + /** + * Fills in an array of size n with the n smallest elements from the collection. + * Can compute the result in sorted or unsorted order. + * + * Currently package visible until the implementation of FastProgressReporter is finished. + * + * @param result array to be filled + * @param sorted if true, the result array will be sorted. If false, the result array + * may be unsorted. This does not affect which elements appear in the result, only their + * order. + * @param mon monitor used to report progress and check for cancellation + * @return the number of items inserted into the result array. This will be equal to the minimum + * of result.length and container.size() + * @throws InterruptedException if the progress monitor is cancelled + */ + /* package */ final int getFirst(Object[] result, bool sorted, FastProgressReporter mon) { + int returnValue = getRange(result, 0, sorted, mon); + + testInvariants(); + + return returnValue; + } + + /** + * Fills in an array of size n with the n smallest elements from the collection. + * Can compute the result in sorted or unsorted order. + * + * @param result array to be filled + * @param sorted if true, the result array will be sorted. If false, the result array + * may be unsorted. This does not affect which elements appear in the result. It only + * affects their order. Computing an unsorted result is asymptotically faster. + * @return the number of items inserted into the result array. This will be equal to the minimum + * of result.length and container.size() + */ + public final int getFirst(Object[] result, bool sorted) { + int returnValue = 0; + + try { + returnValue = getFirst(result, sorted, new FastProgressReporter()); + } catch (InterruptedException e) { + } + + testInvariants(); + + return returnValue; + } + + /** + * Given a position defined by k and an array of size n, this fills in the array with + * the kth smallest element through to the (k+n)th smallest element. For example, + * getRange(myArray, 10, false) would fill in myArray starting with the 10th smallest item + * in the collection. The result can be computed in sorted or unsorted order. Computing the + * result in unsorted order is more efficient. + *+ * Temporarily set to package visibility until the implementation of FastProgressReporter + * is finished. + *
+ * + * @param result array to be filled in + * @param rangeStart index of the smallest element to appear in the result + * @param sorted true iff the result array should be sorted + * @param mon progress monitor used to cancel the operation + * @throws InterruptedException if the progress monitor was cancelled in another thread + */ + /* package */ final int getRange(Object[] result, int rangeStart, bool sorted, FastProgressReporter mon) { + return getRange(result, 0, rangeStart, root, sorted, mon); + } + + /** + * Computes the n through n+k items in this collection. + * Computing the result in unsorted order is more efficient. Sorting the result will + * not change which elements actually show up in the result. That is, even if the result is + * unsorted, it will still contain the same elements as would have been at that range in + * a fully sorted collection. + * + * @param result array containing the result + * @param rangeStart index of the first element to be inserted into the result array + * @param sorted true iff the result will be computed in sorted order + * @return the number of items actually inserted into the result array (will be the minimum + * of result.length and this.size()) + */ + public final int getRange(Object[] result, int rangeStart, bool sorted) { + int returnValue = 0; + + try { + returnValue = getRange(result, rangeStart, sorted, new FastProgressReporter()); + } catch (InterruptedException e) { + } + + testInvariants(); + + return returnValue; + } + + /** + * Returns the item at the given index. Indexes are based on sorted order. + * + * @param index index to test + * @return the item at the given index + */ + public final Object getItem(int index) { + Object[] result = new Object[1]; + try { + getRange(result, index, false, new FastProgressReporter()); + } catch (InterruptedException e) { + // shouldn't happen + } + Object returnValue = result[0]; + + testInvariants(); + + return returnValue; + } + + /** + * Returns the contents of this collection as a sorted or unsorted + * array. Computing an unsorted array is more efficient. + * + * @param sorted if true, the result will be in sorted order. If false, + * the result may be in unsorted order. + * @return the contents of this collection as an array. + */ + public final Object[] getItems(bool sorted) { + Object[] result = new Object[size()]; + + getRange(result, 0, sorted); + + return result; + } + + private final int getRange(Object[] result, int resultIdx, int rangeStart, int node, bool sorted, FastProgressReporter mon) { + if (node is -1) { + return 0; + } + + int availableSpace = result.length - resultIdx; + + // If we're asking for all children of the current node, simply call getChildren + if (rangeStart is 0) { + if (treeSize[node] <= availableSpace) { + return getChildren(result, resultIdx, node, sorted, mon); + } + } + + node = partition(node, mon); + if (node is -1) { + return 0; + } + + int inserted = 0; + + int numberLessThanNode = getSubtreeSize(leftSubTree[node]); + + if (rangeStart < numberLessThanNode) { + if (inserted < availableSpace) { + inserted += getRange(result, resultIdx, rangeStart, leftSubTree[node], sorted, mon); + } + } + + if (rangeStart <= numberLessThanNode) { + if (inserted < availableSpace) { + result[resultIdx + inserted] = contents[node]; + inserted++; + } + } + + if (inserted < availableSpace) { + inserted += getRange(result, resultIdx + inserted, + Math.max(rangeStart - numberLessThanNode - 1, 0), rightSubTree[node], sorted, mon); + } + + return inserted; + } + + /** + * Fills in the available space in the given array with all children of the given node. + * + * @param result + * @param resultIdx index in the result array where we will begin filling in children + * @param node + * @return the number of children added to the array + * @since 3.1 + */ + private final int getChildren(Object[] result, int resultIdx, int node, bool sorted, FastProgressReporter mon) { + if (node is -1) { + return 0; + } + + int tempIdx = resultIdx; + + if (sorted) { + node = partition(node, mon); + if (node is -1) { + return 0; + } + } + + // Add child nodes smaller than this one + if (tempIdx < result.length) { + tempIdx += getChildren(result, tempIdx, leftSubTree[node], sorted, mon); + } + + // Add the pivot + if (tempIdx < result.length) { + Object value = contents[node]; + if (value !is lazyRemovalFlag) { + result[tempIdx++] = value; + } + } + + // Add child nodes larger than this one + if (tempIdx < result.length) { + tempIdx += getChildren(result, tempIdx, rightSubTree[node], sorted, mon); + } + + // Add unsorted children (should be empty if the sorted flag was true) + for (int unsortedNode = nextUnsorted[node]; unsortedNode !is -1 && tempIdx < result.length; + unsortedNode = nextUnsorted[unsortedNode]) { + + result[tempIdx++] = contents[unsortedNode]; + } + + return tempIdx - resultIdx; + } + + /** + * Returns true iff this collection contains the given item + * + * @param item item to test + * @return true iff this collection contains the given item + */ + public bool contains(Object item) { + Assert.isNotNull(item); + bool returnValue = (getObjectIndex(item) !is -1); + + testInvariants(); + + return returnValue; + } +} diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/SetModel.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/viewers/deferred/SetModel.d Mon Mar 31 00:47:19 2008 +0200 @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank BenoitIConcurrentModel
. Implements
+ * an unordered set of elements that fires off change notifications whenever
+ * elements are added or removed from the set. All notifications are sent
+ * synchronously.
+ *
+ * @since 3.1
+ */
+public class SetModel : AbstractConcurrentModel {
+
+ private HashSet!(Object) data;
+
+ public this(){
+ data = new HashSet!(Object);
+ }
+
+ /**
+ * Return the contents of the model.
+ * @return the array of elements
+ *
+ */
+ public Object[] getElements() {
+ return data.toArray();
+ }
+
+ /**
+ * Sets the contents to the given array of elements
+ *
+ * @param newContents new contents of this set
+ */
+ public void set(Object[] newContents) {
+// Assert.isNotNull(newContents);
+ data.clear();
+ for (int i = 0; i < newContents.length; i++) {
+ Object object = newContents[i];
+
+ data.add(object);
+ }
+
+ IConcurrentModelListener[] listeners = getListeners();
+ foreach( listener; listeners ){
+ listener.setContents(newContents);
+ }
+ }
+
+ /**
+ * Empties the set
+ */
+ public void clear() {
+ Object[] removed = data.toArray();
+ data.clear();
+ fireRemove(removed);
+ }
+
+ /**
+ * Adds the given elements to the set
+ *
+ * @param toAdd elements to add
+ */
+ public void addAll(Object[] toAdd) {
+// Assert.isNotNull(toAdd);
+ for (int i = 0; i < toAdd.length; i++) {
+ Object object = toAdd[i];
+
+ data.add(object);
+ }
+
+ fireAdd(toAdd);
+ }
+
+ /**
+ * Adds the given elements to the set. Duplicate elements are ignored.
+ *
+ * @param toAdd elements to add
+ */
+ public void addAll(View!(Object) toAdd) {
+ Assert.isNotNull(cast(Object)toAdd);
+ addAll(toAdd.toArray());
+ }
+
+ /**
+ * Fires a change notification for all elements in the given array
+ *
+ * @param changed array of elements that have changed
+ */
+ public void changeAll(Object[] changed) {
+// Assert.isNotNull(changed);
+ fireUpdate(changed);
+ }
+
+ /**
+ * Removes all of the given elements from the set.
+ *
+ * @param toRemove elements to remove
+ */
+ public void removeAll(Object[] toRemove) {
+// Assert.isNotNull(toRemove);
+ for (int i = 0; i < toRemove.length; i++) {
+ Object object = toRemove[i];
+
+ data.remove(object);
+ }
+
+ fireRemove(toRemove);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.viewers.deferred.IConcurrentModel#requestUpdate(dwtx.jface.viewers.deferred.IConcurrentModelListener)
+ */
+ public void requestUpdate(IConcurrentModelListener listener) {
+ Assert.isNotNull(cast(Object)listener);
+ listener.setContents(getElements());
+ }
+}
diff -r 6c14e54dfc11 -r b6c35faf97c8 dwtx/jface/viewers/deferred/package.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/deferred/package.html Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ The deferred viewers are viewers that can handle concurrent updates from a
+ variety of Threads.
+
+
+