aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpaturzo2014-03-14 07:44:57 (EDT)
committermpaturzo2014-03-14 09:39:26 (EDT)
commit384bdf13b2c73b4d2a45a2dbfdd14f3c72a8f1fa (patch)
tree45f116bd519ad3b1b0a7031b8d518181ca307532
parent880d43b7d4476ed623ec7640466028cac56ea27c (diff)
downloadorg.eclipse.nebula-384bdf13b2c73b4d2a45a2dbfdd14f3c72a8f1fa.zip
org.eclipse.nebula-384bdf13b2c73b4d2a45a2dbfdd14f3c72a8f1fa.tar.gz
org.eclipse.nebula-384bdf13b2c73b4d2a45a2dbfdd14f3c72a8f1fa.tar.bz2
Bug 430106 - Data held by GridItem are incoherentrefs/changes/87/23387/4
I fixed the bug and I made some tests using snippets. I have increased the performance of the Grid, further reducing the size of the memory and I have extended the concept of virtual data visualizer also to the trees. I ran all the snippets and they worked. But there is a problem: i had to change the interface DataVisualizer. Is a major change, i had to replace the row index parameter with the reference to GridItem. Change-Id: I71093eec1d816364f82535fbb78db790fc2f2f1a Signed-off-by: mpaturzo <caosmpz@yahoo.it>
-rw-r--r--examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetDisposePerformance.java355
-rw-r--r--examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetDisposeTreeTest.java332
-rw-r--r--examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithAdaptedDataVisualizer.java71
-rw-r--r--examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithGridItemDataVisualizer.java (renamed from examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithColumnRowBigDataVisualizer.java)6
-rw-r--r--examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithRowColumnBigDataVisualizer.java234
-rw-r--r--widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/AdaptedDataVisualizer.java155
-rw-r--r--widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/ColumnRowBigDataVisualizer.java358
-rw-r--r--widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/DataVisualizer.java124
-rw-r--r--widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/Grid.java20033
-rw-r--r--widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/GridItem.java222
-rw-r--r--widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/GridItemDataVisualizer.java413
-rw-r--r--widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/RowColumnBigDataVisualizer.java101
12 files changed, 10872 insertions, 11532 deletions
diff --git a/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetDisposePerformance.java b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetDisposePerformance.java
new file mode 100644
index 0000000..aa4c9ad
--- /dev/null
+++ b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetDisposePerformance.java
@@ -0,0 +1,355 @@
+package org.eclipse.nebula.snippets.grid.viewer;
+
+/*******************************************************************************
+ * 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
+ * Mirko Paturzo - adding dispose functions example and
+ * defaults properties change
+ *******************************************************************************/
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.FontRegistry;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ColumnViewerEditor;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableColorProvider;
+import org.eclipse.jface.viewers.ITableFontProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.nebula.jface.gridviewer.GridTableViewer;
+import org.eclipse.nebula.jface.gridviewer.GridViewerEditor;
+import org.eclipse.nebula.widgets.grid.GridColumn;
+import org.eclipse.nebula.widgets.grid.GridItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Example usage of none mandatory interfaces of ITableFontProvider and
+ * ITableColorProvider
+ *
+ * @author Tom Schindl <tom.schindl@bestsolution.at>
+ * @author Mirko Paturzo <mirko.paturzo@exeura.eu>
+ *
+ * Original example, with something else (NUM_COLUMNS, NUM_MODELS) Using
+ * {@link ColumnRowBigDataVisualizer}
+ *
+ * Suggestions: Take heap dump by jvisualvm and analyze it with
+ * MemoryAnalyzer
+ *
+ */
+public class GridViewerSnippetDisposePerformance {
+
+ private static final int NUM_COLUMNS = 10;
+ private static final int NUM_MODELS = 10;
+
+ private class MyContentProvider implements IStructuredContentProvider {
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.eclipse.jface.viewers.IStructuredContentProvider#getElements(
+ * java.lang.Object)
+ */
+
+ public Object[] getElements(Object inputElement) {
+ return (MyModel[]) inputElement;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+
+ public void dispose() {
+
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse
+ * .jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+
+ }
+
+ }
+
+ public static boolean flag = true;
+
+ public class MyModel {
+ public int counter;
+
+ public MyModel(int counter) {
+ this.counter = counter;
+ }
+
+ @Override
+ public String toString() {
+ return "Item " + this.counter;
+ }
+ }
+
+ final FontRegistry registry = new FontRegistry();
+
+ public class MyLabelProvider extends LabelProvider implements ITableLabelProvider, ITableFontProvider,
+ ITableColorProvider {
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ return "Column " + columnIndex + " => " + element.toString();
+ }
+
+ public Font getFont(Object element, int columnIndex) {
+ if (((MyModel) element).counter % 2 == 0) {
+ return registry.getBold(Display.getCurrent().getSystemFont().getFontData()[0].getName());
+ }
+ return null;
+ }
+
+ public Color getBackground(Object element, int columnIndex) {
+ if (((MyModel) element).counter % 2 == 0) {
+ return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
+ }
+ return null;
+ }
+
+ public Color getForeground(Object element, int columnIndex) {
+ if (((MyModel) element).counter % 2 == 1) {
+ return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
+ }
+ return null;
+ }
+
+ }
+
+ public GridViewerSnippetDisposePerformance(final Shell shell, boolean createButtons) {
+ final GridTableViewer v = new GridTableViewer(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+ v.setLabelProvider(new MyLabelProvider());
+ v.setContentProvider(new MyContentProvider());
+ v.getGrid().setCellSelectionEnabled(true);
+
+ v.setCellEditors(new CellEditor[] { new TextCellEditor(v.getGrid()), new TextCellEditor(v.getGrid()) });
+ v.setCellModifier(new ICellModifier() {
+
+ public boolean canModify(Object element, String property) {
+ return true;
+ }
+
+ public Object getValue(Object element, String property) {
+ if (element == null)
+ return "Element is null";
+ return "Column " + property + " => " + element.toString();
+ }
+
+ public void modify(Object element, String property, Object value) {
+
+ }
+
+ });
+
+ v.setColumnProperties(new String[] { "1", "2" });
+
+ ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(v) {
+
+ @Override
+ protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
+ return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
+ || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
+ || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR);
+ }
+ };
+
+ GridViewerEditor.create(v, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
+ | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR | ColumnViewerEditor.TABBING_VERTICAL
+ | ColumnViewerEditor.KEYBOARD_ACTIVATION);
+
+ for (int i = 0; i < NUM_COLUMNS; i++) {
+ createColumn(v, "Column " + i);
+ }
+ if (createButtons) {
+ Composite buttons = new Composite(shell, SWT.NONE);
+ buttons.setLayout(new RowLayout());
+
+ final Button remove3 = new Button(buttons, SWT.NONE);
+ remove3.setText("remove row with index 3");
+ final String restore = "restore grid";
+ remove3.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ // button.dispose();
+ try {
+ v.getGrid().remove(3);
+ }
+ catch (java.lang.IllegalArgumentException ie) {
+ new MessageDialog(shell, "IndexOutOfBound error", null, "Restore the grid with button \""
+ + restore + "\"", MessageDialog.WARNING, new String[] { "Ok" }, 0).open();
+ }
+
+ shell.layout();
+ }
+ });
+
+ final Button add3 = new Button(buttons, SWT.NONE);
+ add3.setText("add row with index 3");
+ add3.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ GridItem gridItem = new GridItem(v.getGrid(), SWT.NONE, 3);
+ gridItem.setText(0, "Added in 3");
+ shell.layout();
+ }
+ });
+ final Button addColumn1 = new Button(buttons, SWT.NONE);
+ addColumn1.setText("add column in 1");
+ addColumn1.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ new GridColumn(v.getGrid(), SWT.NONE, 1);
+ shell.layout();
+ }
+ });
+ final Button removeColumn = new Button(buttons, SWT.NONE);
+ removeColumn.setText("remove first column");
+ removeColumn.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ // button.dispose();
+ try {
+ v.getGrid().getColumn(0).dispose();
+ v.getGrid().redraw();
+ v.getGrid().layout();
+ }
+ catch (java.lang.IllegalArgumentException ie) {
+ new MessageDialog(shell, "IndexOutOfBound error", null, "Restore the grid with button \""
+ + restore + "\"", MessageDialog.WARNING, new String[] { "Ok" }, 0).open();
+ }
+
+ shell.layout();
+ }
+ });
+ final Button addColumn = new Button(buttons, SWT.NONE);
+ addColumn.setText("add column");
+ addColumn.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ // button.dispose();
+ try {
+ createColumn(v, "Added");
+ }
+ catch (java.lang.IllegalArgumentException ie) {
+ new MessageDialog(shell, "IndexOutOfBound error", null, "Restore the grid with button \""
+ + restore + "\"", MessageDialog.WARNING, new String[] { "Ok" }, 0).open();
+ }
+
+ shell.layout();
+ }
+ });
+ final Button changeFont = new Button(buttons, SWT.NONE);
+ changeFont.setText("Change Default");
+ changeFont.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ v.getGrid().setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ v.getGrid().setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
+ v.getGrid().setFont(
+ registry.getItalic(Display.getCurrent().getSystemFont().getFontData()[0].getName()));
+ shell.layout();
+ }
+ });
+ final Button restoreButton = new Button(buttons, SWT.NONE);
+ restoreButton.setText(restore);
+ restoreButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ GridColumn[] columns = v.getGrid().getColumns();
+ for (GridColumn gridColumn : columns) {
+ gridColumn.dispose();
+ }
+ for (int i = 0; i < NUM_COLUMNS; i++) {
+ createColumn(v, "Column " + i);
+ }
+ v.setInput(createModel());
+ v.getGrid().setItemCount(10);
+ v.getGrid().redraw();
+ v.getGrid().layout();
+ shell.layout();
+ }
+ });
+ Button gcButton = new Button(buttons, SWT.NONE);
+ gcButton.setText("gc");
+ gcButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ System.gc();
+ }
+ });
+
+ }
+ MyModel[] model = createModel();
+ v.setInput(model);
+ v.getGrid().setLinesVisible(true);
+ v.getGrid().setHeaderVisible(true);
+ }
+
+ private void createColumn(final GridTableViewer v, String name) {
+ GridColumn column = new GridColumn(v.getGrid(), SWT.NONE);
+ column.setWidth(200);
+ column.setText(name);
+ }
+
+ private MyModel[] createModel() {
+ MyModel[] elements = new MyModel[NUM_MODELS];
+
+ for (int i = 0; i < NUM_MODELS; i++) {
+ elements[i] = new MyModel(i);
+ }
+
+ return elements;
+ }
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ Display display = new Display();
+
+ Shell shell = new Shell(display);
+ shell.setLayout(new FillLayout());
+ new GridViewerSnippetDisposePerformance(shell, true);
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+
+ display.dispose();
+
+ }
+
+}
diff --git a/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetDisposeTreeTest.java b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetDisposeTreeTest.java
new file mode 100644
index 0000000..6f3e97c
--- /dev/null
+++ b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetDisposeTreeTest.java
@@ -0,0 +1,332 @@
+/*******************************************************************************
+ * 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
+ * Mirko Paturzo - adding dispose functions example and defaults properties change
+ *******************************************************************************/
+
+package org.eclipse.nebula.snippets.grid.viewer;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.FontRegistry;
+import org.eclipse.jface.viewers.ITableColorProvider;
+import org.eclipse.jface.viewers.ITableFontProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.nebula.jface.gridviewer.GridTreeViewer;
+import org.eclipse.nebula.jface.gridviewer.GridViewerColumn;
+import org.eclipse.nebula.widgets.grid.GridColumn;
+import org.eclipse.nebula.widgets.grid.GridItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A simple TreeViewer for verify dispose improvement
+ *
+ * @author Tom Schindl <tom.schindl@bestsolution.at>
+ * @author Mirko Paturzo <mirko.paturzo@exeura.eu>
+ *
+ */
+public class GridViewerSnippetDisposeTreeTest {
+ private class MyContentProvider implements ITreeContentProvider {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ return ((MyModel) inputElement).child.toArray();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
+ * java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
+ */
+ public Object[] getChildren(Object parentElement) {
+ return getElements(parentElement);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
+ */
+ public Object getParent(Object element) {
+ if (element == null) {
+ return null;
+ }
+
+ return ((MyModel) element).parent;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
+ */
+ public boolean hasChildren(Object element) {
+ return ((MyModel) element).child.size() > 0;
+ }
+
+ }
+
+ public class MyModel {
+ public MyModel parent;
+
+ public ArrayList child = new ArrayList();
+
+ public int counter;
+
+ public MyModel(int counter, MyModel parent) {
+ this.parent = parent;
+ this.counter = counter;
+ }
+
+ @Override
+ public String toString() {
+ String rv = "Item ";
+ if (parent != null) {
+ rv = parent.toString() + ".";
+ }
+
+ rv += counter;
+
+ return rv;
+ }
+ }
+
+ final FontRegistry registry = new FontRegistry();
+
+ public class MyLabelProvider extends LabelProvider implements ITableLabelProvider, ITableFontProvider,
+ ITableColorProvider {
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ return "Column " + columnIndex + " => " + element.toString();
+ }
+
+ public Font getFont(Object element, int columnIndex) {
+ if (((MyModel) element).counter % 2 == 0) {
+ return registry.getBold(Display.getCurrent().getSystemFont().getFontData()[0].getName());
+ }
+ return null;
+ }
+
+ public Color getBackground(Object element, int columnIndex) {
+ if (((MyModel) element).counter % 2 == 0) {
+ return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
+ }
+ return null;
+ }
+
+ public Color getForeground(Object element, int columnIndex) {
+ if (((MyModel) element).counter % 2 == 1) {
+ return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
+ }
+ return null;
+ }
+
+ }
+
+ public GridViewerSnippetDisposeTreeTest(final Shell shell) {
+ final GridTreeViewer v = new GridTreeViewer(shell);
+
+ Composite buttons = new Composite(shell, SWT.NONE);
+ buttons.setLayout(new RowLayout());
+ final Button remove3 = new Button(buttons, SWT.NONE);
+ remove3.setText("remove row with index 3");
+ final String restore = "restore grid";
+ remove3.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ // button.dispose();
+ try {
+ v.getGrid().remove(3);
+ }
+ catch (java.lang.IllegalArgumentException ie) {
+ new MessageDialog(shell, "IndexOutOfBound error", null, "Restore the grid with button \"" + restore
+ + "\"", MessageDialog.WARNING, new String[] { "Ok" }, 0).open();
+ }
+
+ shell.layout();
+ }
+ });
+ final Button add3 = new Button(buttons, SWT.NONE);
+ add3.setText("add row with index 3");
+ add3.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ GridItem gridItem = new GridItem(v.getGrid(), SWT.NONE, 3);
+ gridItem.setText(0, "Added in 3");
+ shell.layout();
+ }
+ });
+ final Button addColumn1 = new Button(buttons, SWT.NONE);
+ addColumn1.setText("add column in 1");
+ addColumn1.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ new GridColumn(v.getGrid(), SWT.NONE, 1);
+ shell.layout();
+ }
+ });
+ final Button removeColumn = new Button(buttons, SWT.NONE);
+ removeColumn.setText("remove first column");
+ removeColumn.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ // button.dispose();
+ try {
+ v.getGrid().getColumn(0).dispose();
+ v.getGrid().redraw();
+ v.getGrid().layout();
+ }
+ catch (java.lang.IllegalArgumentException ie) {
+ new MessageDialog(shell, "IndexOutOfBound error", null, "Restore the grid with button \"" + restore
+ + "\"", MessageDialog.WARNING, new String[] { "Ok" }, 0).open();
+ }
+
+ shell.layout();
+ }
+ });
+ final Button addColumn = new Button(buttons, SWT.NONE);
+ addColumn.setText("add column");
+ addColumn.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ // button.dispose();
+ try {
+ createColumn(v, "Added");
+ }
+ catch (java.lang.IllegalArgumentException ie) {
+ new MessageDialog(shell, "IndexOutOfBound error", null, "Restore the grid with button \"" + restore
+ + "\"", MessageDialog.WARNING, new String[] { "Ok" }, 0).open();
+ }
+
+ shell.layout();
+ }
+ });
+ final Button changeFont = new Button(buttons, SWT.NONE);
+ changeFont.setText("Change Default");
+ changeFont.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ v.getGrid().setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ v.getGrid().setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
+ v.getGrid()
+ .setFont(registry.getItalic(Display.getCurrent().getSystemFont().getFontData()[0].getName()));
+ shell.layout();
+ }
+ });
+ final Button restoreButton = new Button(buttons, SWT.NONE);
+ restoreButton.setText(restore);
+ restoreButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ GridColumn[] columns = v.getGrid().getColumns();
+ for (GridColumn gridColumn : columns) {
+ gridColumn.dispose();
+ }
+ revertGrid(v);
+ shell.layout();
+ }
+ });
+ revertGrid(v);
+ }
+
+ private void revertGrid(final GridTreeViewer v) {
+ GridViewerColumn column = new GridViewerColumn(v, SWT.NONE);
+ column.getColumn().setWidth(200);
+ column.getColumn().setText("Column 1");
+ column.getColumn().setTree(true);
+
+ column = new GridViewerColumn(v, SWT.NONE);
+ column.getColumn().setWidth(200);
+ column.getColumn().setText("Column 2");
+
+ v.setLabelProvider(new MyLabelProvider());
+ v.setContentProvider(new MyContentProvider());
+ v.setInput(createModel());
+ }
+
+ private MyModel createModel() {
+
+ MyModel root = new MyModel(0, null);
+ root.counter = 0;
+
+ MyModel tmp;
+ for (int i = 1; i < 10; i++) {
+ tmp = new MyModel(i, root);
+ root.child.add(tmp);
+ for (int j = 1; j < i; j++) {
+ tmp.child.add(new MyModel(j, tmp));
+ }
+ }
+
+ return root;
+ }
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setLayout(new FillLayout());
+ new GridViewerSnippetDisposeTreeTest(shell);
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+
+ display.dispose();
+ }
+
+ private static void createColumn(final GridTreeViewer v, String name) {
+ GridColumn column = new GridColumn(v.getGrid(), SWT.NONE);
+ column.setWidth(200);
+ column.setText(name);
+ }
+}
diff --git a/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithAdaptedDataVisualizer.java b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithAdaptedDataVisualizer.java
index 28d5371..506ab76 100644
--- a/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithAdaptedDataVisualizer.java
+++ b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithAdaptedDataVisualizer.java
@@ -9,9 +9,9 @@ package org.eclipse.nebula.snippets.grid.viewer;
*
* Contributors:
* Tom Schindl - initial API and implementation
+ * Mirko Paturzo - adapt the example for AdaptedDataVisualizer
*******************************************************************************/
-
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewerEditor;
@@ -29,6 +29,7 @@ import org.eclipse.nebula.jface.gridviewer.GridTableViewer;
import org.eclipse.nebula.jface.gridviewer.GridViewerEditor;
import org.eclipse.nebula.widgets.grid.AdaptedDataVisualizer;
import org.eclipse.nebula.widgets.grid.GridColumn;
+import org.eclipse.nebula.widgets.grid.GridItem;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
@@ -84,7 +85,7 @@ public class GridViewerSnippetWithAdaptedDataVisualizer {
}
public static boolean flag = true;
-
+
public class MyModel {
public int counter;
@@ -98,8 +99,8 @@ public class GridViewerSnippetWithAdaptedDataVisualizer {
}
}
- public class MyLabelProvider extends LabelProvider implements
- ITableLabelProvider, ITableFontProvider, ITableColorProvider {
+ public class MyLabelProvider extends LabelProvider implements ITableLabelProvider, ITableFontProvider,
+ ITableColorProvider {
FontRegistry registry = new FontRegistry();
public Image getColumnImage(Object element, int columnIndex) {
@@ -112,8 +113,7 @@ public class GridViewerSnippetWithAdaptedDataVisualizer {
public Font getFont(Object element, int columnIndex) {
if (((MyModel) element).counter % 2 == 0) {
- return registry.getBold(Display.getCurrent().getSystemFont()
- .getFontData()[0].getName());
+ return registry.getBold(Display.getCurrent().getSystemFont().getFontData()[0].getName());
}
return null;
}
@@ -133,7 +133,7 @@ public class GridViewerSnippetWithAdaptedDataVisualizer {
}
}
-
+
/**
* Below myown AdaptedDataVisualizer
* @author Mirko Paturzo
@@ -141,43 +141,42 @@ public class GridViewerSnippetWithAdaptedDataVisualizer {
*/
private static class MyOwnDataVisualizer extends AdaptedDataVisualizer {
FontRegistry registry = new FontRegistry();
-
+
private final MyModel models[];
-
+
public MyOwnDataVisualizer(MyModel models[]) {
this.models = models;
}
-
+
@Override
- public Image getImage(int row, int columnIndex) {
+ public Image getImage(GridItem gridItem, int columnIndex) {
return null;
}
@Override
- public String getText(int row, int columnIndex) {
- return "Column " + columnIndex + " => " + models[row].toString();
+ public String getText(GridItem gridItem, int columnIndex) {
+ return "Column " + columnIndex + " => " + models[gridItem.getRowIndex()].toString();
}
@Override
- public Font getFont(int row, int columnIndex) {
- if ((models[row]).counter % 2 == 0) {
- return registry.getBold(Display.getCurrent().getSystemFont()
- .getFontData()[0].getName());
+ public Font getFont(GridItem gridItem, int columnIndex) {
+ if ((models[gridItem.getRowIndex()]).counter % 2 == 0) {
+ return registry.getBold(Display.getCurrent().getSystemFont().getFontData()[0].getName());
}
return null;
}
@Override
- public Color getBackground(int row, int columnIndex) {
- if ((models[row]).counter % 2 == 0) {
+ public Color getBackground(GridItem gridItem, int columnIndex) {
+ if ((models[gridItem.getRowIndex()]).counter % 2 == 0) {
return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
}
return Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);
}
-
+
@Override
- public Color getForeground(int row, int columnIndex) {
- if ((models[row]).counter % 2 == 1) {
+ public Color getForeground(GridItem gridItem, int columnIndex) {
+ if ((models[gridItem.getRowIndex()]).counter % 2 == 1) {
return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
}
return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
@@ -186,11 +185,12 @@ public class GridViewerSnippetWithAdaptedDataVisualizer {
public GridViewerSnippetWithAdaptedDataVisualizer(Shell shell) {
MyModel[] models = createModel();
- final GridTableViewer v = new GridTableViewer(new MyOwnDataVisualizer(models), shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+ final GridTableViewer v = new GridTableViewer(new MyOwnDataVisualizer(models), shell, SWT.BORDER | SWT.V_SCROLL
+ | SWT.H_SCROLL);
v.setLabelProvider(new MyLabelProvider());
v.setContentProvider(new MyContentProvider());
v.getGrid().setCellSelectionEnabled(true);
-
+
v.setCellEditors(new CellEditor[] { new TextCellEditor(v.getGrid()), new TextCellEditor(v.getGrid()) });
v.setCellModifier(new ICellModifier() {
@@ -203,28 +203,27 @@ public class GridViewerSnippetWithAdaptedDataVisualizer {
}
public void modify(Object element, String property, Object value) {
-
+
}
-
+
});
-
- v.setColumnProperties(new String[] {"1","2"});
-
+
+ v.setColumnProperties(new String[] { "1", "2" });
+
ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(v) {
@Override
- protected boolean isEditorActivationEvent(
- ColumnViewerEditorActivationEvent event) {
+ protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
|| event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR);
}
};
-
+
GridViewerEditor.create(v, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
- | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
- | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
-
- for(int i = 0; i < NUM_COLUMNS; i++) {
+ | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR | ColumnViewerEditor.TABBING_VERTICAL
+ | ColumnViewerEditor.KEYBOARD_ACTIVATION);
+
+ for (int i = 0; i < NUM_COLUMNS; i++) {
createColumn(v, "Column " + i);
}
diff --git a/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithColumnRowBigDataVisualizer.java b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithGridItemDataVisualizer.java
index 33ced32..b154ef1 100644
--- a/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithColumnRowBigDataVisualizer.java
+++ b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithGridItemDataVisualizer.java
@@ -47,7 +47,7 @@ import org.eclipse.swt.widgets.Shell;
* Using {@link ColumnRowBigDataVisualizer}
*
*/
-public class GridViewerSnippetWithColumnRowBigDataVisualizer {
+public class GridViewerSnippetWithGridItemDataVisualizer {
private static final int NUM_COLUMNS = 1000;
private static final int NUM_MODELS = 1000;
@@ -143,7 +143,7 @@ public class GridViewerSnippetWithColumnRowBigDataVisualizer {
}
- public GridViewerSnippetWithColumnRowBigDataVisualizer(Shell shell) {
+ public GridViewerSnippetWithGridItemDataVisualizer(Shell shell) {
final GridTableViewer v = new GridTableViewer(shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
v.setLabelProvider(new MyLabelProvider());
v.setContentProvider(new MyContentProvider());
@@ -219,7 +219,7 @@ public class GridViewerSnippetWithColumnRowBigDataVisualizer {
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
- new GridViewerSnippetWithColumnRowBigDataVisualizer(shell);
+ new GridViewerSnippetWithGridItemDataVisualizer(shell);
shell.open();
while (!shell.isDisposed()) {
diff --git a/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithRowColumnBigDataVisualizer.java b/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithRowColumnBigDataVisualizer.java
deleted file mode 100644
index e6f6980..0000000
--- a/examples/org.eclipse.nebula.snippets/src/org/eclipse/nebula/snippets/grid/viewer/GridViewerSnippetWithRowColumnBigDataVisualizer.java
+++ /dev/null
@@ -1,234 +0,0 @@
-package org.eclipse.nebula.snippets.grid.viewer;
-
-/*******************************************************************************
- * 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
- *******************************************************************************/
-
-
-import org.eclipse.jface.resource.FontRegistry;
-import org.eclipse.jface.viewers.CellEditor;
-import org.eclipse.jface.viewers.ColumnViewerEditor;
-import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
-import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
-import org.eclipse.jface.viewers.ICellModifier;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableColorProvider;
-import org.eclipse.jface.viewers.ITableFontProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TextCellEditor;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.nebula.jface.gridviewer.GridTableViewer;
-import org.eclipse.nebula.jface.gridviewer.GridViewerEditor;
-import org.eclipse.nebula.widgets.grid.GridColumn;
-import org.eclipse.nebula.widgets.grid.RowColumnBigDataVisualizer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-/**
- * Example usage of none mandatory interfaces of ITableFontProvider and
- * ITableColorProvider
- *
- * @author Tom Schindl <tom.schindl@bestsolution.at>
- * @author Mirko Paturzo <mirko.paturzo@exeura.eu>
- *
- * Example with {@link RowColumnBigDataVisualizer}
- *
- */
-public class GridViewerSnippetWithRowColumnBigDataVisualizer {
-
- private static final int NUM_COLUMNS = 1000;
- private static final int NUM_MODELS = 1000;
-
- private class MyContentProvider implements IStructuredContentProvider {
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
- */
-
- public Object[] getElements(Object inputElement) {
- return (MyModel[]) inputElement;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.viewers.IContentProvider#dispose()
- */
-
- public void dispose() {
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
- * java.lang.Object, java.lang.Object)
- */
-
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-
- }
-
- }
-
- public static boolean flag = true;
-
- public class MyModel {
- public int counter;
-
- public MyModel(int counter) {
- this.counter = counter;
- }
-
-
- public String toString() {
- return "Item " + this.counter;
- }
- }
-
- public class MyLabelProvider extends LabelProvider implements
- ITableLabelProvider, ITableFontProvider, ITableColorProvider {
- FontRegistry registry = new FontRegistry();
-
-
- public Image getColumnImage(Object element, int columnIndex) {
- return null;
- }
-
-
- public String getColumnText(Object element, int columnIndex) {
- return "Column " + columnIndex + " => " + element.toString();
- }
-
-
- public Font getFont(Object element, int columnIndex) {
- if (((MyModel) element).counter % 2 == 0) {
- return registry.getBold(Display.getCurrent().getSystemFont()
- .getFontData()[0].getName());
- }
- return null;
- }
-
-
- public Color getBackground(Object element, int columnIndex) {
- if (((MyModel) element).counter % 2 == 0) {
- return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
- }
- return null;
- }
-
-
- public Color getForeground(Object element, int columnIndex) {
- if (((MyModel) element).counter % 2 == 1) {
- return Display.getCurrent().getSystemColor(SWT.COLOR_RED);
- }
- return null;
- }
-
- }
-
- public GridViewerSnippetWithRowColumnBigDataVisualizer(Shell shell) {
- final GridTableViewer v = new GridTableViewer(new RowColumnBigDataVisualizer(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE), Display.getCurrent().getSystemColor(SWT.COLOR_BLACK), null), shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
- v.setLabelProvider(new MyLabelProvider());
- v.setContentProvider(new MyContentProvider());
- v.getGrid().setCellSelectionEnabled(true);
-
- v.setCellEditors(new CellEditor[] { new TextCellEditor(v.getGrid()), new TextCellEditor(v.getGrid()) });
- v.setCellModifier(new ICellModifier() {
-
-
- public boolean canModify(Object element, String property) {
- return true;
- }
-
-
- public Object getValue(Object element, String property) {
- return "Column " + property + " => " + element.toString();
- }
-
-
- public void modify(Object element, String property, Object value) {
-
- }
-
- });
-
- v.setColumnProperties(new String[] {"1","2"});
-
- ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(v) {
-
- protected boolean isEditorActivationEvent(
- ColumnViewerEditorActivationEvent event) {
- return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
- || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
- || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR);
- }
- };
-
- GridViewerEditor.create(v, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
- | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
- | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
-
- for(int i = 0; i < NUM_COLUMNS; i++) {
- createColumn(v, "Column " + i);
- }
-
- MyModel[] model = createModel();
- v.setInput(model);
- v.getGrid().setLinesVisible(true);
- v.getGrid().setHeaderVisible(true);
- }
-
- private void createColumn(final GridTableViewer v, String name) {
- GridColumn column = new GridColumn(v.getGrid(), SWT.NONE);
- column.setWidth(200);
- column.setText(name);
- }
-
- private MyModel[] createModel() {
- MyModel[] elements = new MyModel[NUM_MODELS];
-
- for (int i = 0; i < NUM_MODELS; i++) {
- elements[i] = new MyModel(i);
- }
-
- return elements;
- }
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- Display display = new Display();
-
- Shell shell = new Shell(display);
- shell.setLayout(new FillLayout());
- new GridViewerSnippetWithRowColumnBigDataVisualizer(shell);
- shell.open();
-
- while (!shell.isDisposed()) {
- if (!display.readAndDispatch())
- display.sleep();
- }
-
- display.dispose();
-
- }
-
-}
diff --git a/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/AdaptedDataVisualizer.java b/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/AdaptedDataVisualizer.java
index 84ba584..027b01f 100644
--- a/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/AdaptedDataVisualizer.java
+++ b/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/AdaptedDataVisualizer.java
@@ -37,18 +37,18 @@ import org.eclipse.swt.widgets.Display;
* }
*
* @Override
- * public Image getImage(int row, int columnIndex) {
+ * public Image getImage(GridItem gridItem, int columnIndex) {
* return null;
* }
*
* @Override
- * public String getText(int row, int columnIndex) {
- * return "Column " + columnIndex + " => " + models[row].toString();
+ * public String getText(GridItem gridItem, int columnIndex) {
+ * return "Column " + columnIndex + " => " + models[gridItem.getRowIndex()].toString();
* }
*
* @Override
- * public Font getFont(int row, int columnIndex) {
- * if ((models[row]).counter % 2 == 0) {
+ * public Font getFont(GridItem gridItem, int columnIndex) {
+ * if ((models[gridItem.getRowIndex()]).counter % 2 == 0) {
* return registry.getBold(Display.getCurrent().getSystemFont()
* .getFontData()[0].getName());
* }
@@ -60,224 +60,211 @@ import org.eclipse.swt.widgets.Display;
* @author Mirko Paturzo <mirko.paturzo@exeura.eu>
*
*/
-public class AdaptedDataVisualizer implements DataVisualizer{
-
+public class AdaptedDataVisualizer implements DataVisualizer {
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setBackground(int, int, org.eclipse.swt.graphics.Color)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setBackground(GridItem, int, org.eclipse.swt.graphics.Color)
*/
@Override
- public void setBackground(int row, int index, Color color) {
+ public void setBackground(GridItem gridItem, int index, Color color) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setChecked(int, int, boolean)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setChecked(GridItem, int, boolean)
*/
@Override
- public void setChecked(int row, int i, boolean checked) {
+ public void setChecked(GridItem gridItem, int i, boolean checked) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setColumnSpan(int, int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setColumnSpan(GridItem, int, int)
*/
@Override
- public void setColumnSpan(int row, int index, int span) {
+ public void setColumnSpan(GridItem gridItem, int index, int span) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setRowSpan(int, int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setRowSpan(GridItem, int, int)
*/
@Override
- public void setRowSpan(int row, int index, int span) {
+ public void setRowSpan(GridItem gridItem, int index, int span) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setFont(int, int, org.eclipse.swt.graphics.Font)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setFont(GridItem, int, org.eclipse.swt.graphics.Font)
*/
@Override
- public void setFont(int row, int index, Font font) {
+ public void setFont(GridItem gridItem, int index, Font font) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setForeground(int, int, org.eclipse.swt.graphics.Color)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setForeground(GridItem, int, org.eclipse.swt.graphics.Color)
*/
@Override
- public void setForeground(int row, int index, Color foreground) {
+ public void setForeground(GridItem gridItem, int index, Color foreground) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setGrayed(int, int, boolean)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setGrayed(GridItem, int, boolean)
*/
@Override
- public void setGrayed(int row, int i, boolean grayed) {
+ public void setGrayed(GridItem gridItem, int i, boolean grayed) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setImage(int, int, org.eclipse.swt.graphics.Image)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setImage(GridItem, int, org.eclipse.swt.graphics.Image)
*/
@Override
- public void setImage(int row, int i, Image image) {
+ public void setImage(GridItem gridItem, int i, Image image) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setText(int, int, java.lang.String)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setText(GridItem, int, java.lang.String)
*/
@Override
- public void setText(int row, int i, String text) {
+ public void setText(GridItem gridItem, int i, String text) {
/**
* Is empty
*/
}
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setCheckable(int, int, boolean)
- */
- @Override
- public void setCheckable(int row, int index, boolean checked) {
- /**
- * Is empty
- */
- }
-
-
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setToolTipText(int, int, java.lang.String)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setCheckable(GridItem, int, boolean)
*/
@Override
- public void setToolTipText(int row, int index, String tooltip) {
+ public void setCheckable(GridItem gridItem, int index, boolean checked) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#removeIndex(int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setToolTipText(GridItem, int, java.lang.String)
*/
@Override
- public void removeIndex(int row) {
+ public void setToolTipText(GridItem gridItem, int index, String tooltip) {
/**
* Is empty
*/
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getBackground(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getBackground(GridItem, int)
*/
@Override
- public Color getBackground(int row, int index) {
+ public Color getBackground(GridItem gridItem, int index) {
return getDefaultBackground();
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getChecked(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getChecked(GridItem, int)
*/
@Override
- public boolean getChecked(int row, int i) {
+ public boolean getChecked(GridItem gridItem, int i) {
return false;
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getColumnSpan(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getColumnSpan(GridItem, int)
*/
@Override
- public int getColumnSpan(int row, int index) {
+ public int getColumnSpan(GridItem gridItem, int index) {
return 0;
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getRowSpan(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getRowSpan(GridItem, int)
*/
@Override
- public int getRowSpan(int row, int index) {
+ public int getRowSpan(GridItem gridItem, int index) {
return 0;
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getFont(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getFont(GridItem, int)
*/
@Override
- public Font getFont(int row, int index) {
+ public Font getFont(GridItem gridItem, int index) {
return getDefaultFont();
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getForeground(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getForeground(GridItem, int)
*/
@Override
- public Color getForeground(int row, int index) {
+ public Color getForeground(GridItem gridItem, int index) {
return getDefaultForeground();
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getGrayed(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getGrayed(GridItem, int)
*/
@Override
- public boolean getGrayed(int row, int index) {
+ public boolean getGrayed(GridItem gridItem, int index) {
return false;
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getImage(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getImage(GridItem, int)
*/
@Override
- public Image getImage(int row, int i) {
+ public Image getImage(GridItem gridItem, int i) {
return null;
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getText(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getText(GridItem, int)
*/
@Override
- public String getText(int row, int i) {
+ public String getText(GridItem gridItem, int i) {
return null;
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getCheckable(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getCheckable(GridItem, int)
*/
@Override
- public boolean getCheckable(int row, int index) {
+ public boolean getCheckable(GridItem gridItem, int index) {
return false;
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getToolTipText(int, int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getToolTipText(GridItem, int)
*/
@Override
- public String getToolTipText(int row, int index) {
+ public String getToolTipText(GridItem gridItem, int index) {
return null;
}
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#clearRow(int)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#clearRow(GridItem)
*/
@Override
- public void clearRow(int row) {
+ public void clearRow(GridItem gridItem) {
/**
* Is empty
*/
@@ -317,12 +304,44 @@ public class AdaptedDataVisualizer implements DataVisualizer{
return null;
}
+ /** (non-Javadoc)
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#addColumn(int)
+ */
+ @Override
+ public void addColumn(int column) {
+ /**
+ * Is empty
+ */
+ }
+
+ /**
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setDefaultBackground(org.eclipse.swt.graphics.Color)
+ */
+ @Override
+ public void setDefaultBackground(Color defaultBackground) {
+ /**
+ * Is empty
+ */
+ }
+
+ /**
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setDefaultForeground(org.eclipse.swt.graphics.Color)
+ */
+ @Override
+ public void setDefaultForeground(Color defaultForeground) {
+ /**
+ * Is empty
+ */
+ }
+
/**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#createAndGetChildenGridItemDataVisualizer()
+ * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setDefaultFont(org.eclipse.swt.graphics.Font)
*/
@Override
- public DataVisualizer createAndGetChildenGridItemDataVisualizer() {
- throw new UnsupportedOperationException("GridItem Children dataVisualizer is not supported in AdaptedDataVisualizer");
+ public void setDefaultFont(Font defaultFont) {
+ /**
+ * Is empty
+ */
}
}
diff --git a/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/ColumnRowBigDataVisualizer.java b/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/ColumnRowBigDataVisualizer.java
deleted file mode 100644
index 2bf7e89..0000000
--- a/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/ColumnRowBigDataVisualizer.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014 Mirko Paturzo (Exeura srl).
- * 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:
- * Mirko Paturzo - initial API and implementation
- *******************************************************************************/
-package org.eclipse.nebula.widgets.grid;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.Image;
-
-/**
- * This class can be used to provide general visualization values for various aspects
- * of the GridItem like background, font and text. Your own subclass of this class
- * could be used in combination with the JFace LabelProvider if you use the GridViewer.
- * This dataVisualizer implementation replace the current paradigma of GridItem with
- * memory less.
- * This implementation is preferable in the case where there are more rows than columns.
- *
- * This datavisualizer kind is default for Grid.
- *
- * @author Mirko Paturzo <mirko.paturzo@exeura.eu>
- *
- */
-public class ColumnRowBigDataVisualizer implements DataVisualizer {
-
- /**
- * Create {@link ColumnRowBigDataVisualizer} with default value
- * @param defaultBackground
- * @param defaultForeground
- * @param defaultFont
- */
- public ColumnRowBigDataVisualizer(Color defaultBackground, Color defaultForeground, Font defaultFont) {
- this.defaultBackground = defaultBackground;
- this.defaultForeground = defaultForeground;
- this.defaultFont = defaultFont;
- }
-
- private final Map<Integer, List<Color>> backgrounds = new HashMap<Integer, List<Color>>();
- private final Map<Integer, List<Color>> foregrounds = new HashMap<Integer, List<Color>>();
- private final Map<Integer, List<Boolean>> checkables = new HashMap<Integer, List<Boolean>>();
- private final Map<Integer, List<Boolean>> checkeds = new HashMap<Integer, List<Boolean>>();
- private final Map<Integer, List<Boolean>> grayeds = new HashMap<Integer, List<Boolean>>();
- private final Map<Integer, List<Integer>> columnSpans = new HashMap<Integer, List<Integer>>();
- private final Map<Integer, List<Integer>> rowSpans = new HashMap<Integer, List<Integer>>();
- private final Map<Integer, List<Font>> fonts = new HashMap<Integer, List<Font>>();
- private final Map<Integer, List<Image>> images = new HashMap<Integer, List<Image>>();
- private final Map<Integer, List<String>> texts = new HashMap<Integer, List<String>>();
- private final Map<Integer, List<String>> toolTipTexts = new HashMap<Integer, List<String>>();
-
- private final Color defaultBackground;
- private final Color defaultForeground;
- private final Font defaultFont;
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getDefaultBackground()
- */
- @Override
- public Color getDefaultBackground() {
- return defaultBackground;
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getDefaultForeground()
- */
- @Override
- public Color getDefaultForeground() {
- return defaultForeground;
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getDefaultFont()
- */
- @Override
- public Font getDefaultFont() {
- return defaultFont;
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getBackground(int, int)
- */
- @Override
- public Color getBackground(int row, int column) {
- return getValueOrDefault(backgrounds, row, column, defaultBackground);
- }
-
- /**
- * get value or default.. inverted index on {@link RowColumnBigDataVisualizer}
- * @param map
- * @param row
- * @param column
- * @param defaultValue
- * @return T
- */
- protected <T> T getValueOrDefault(Map<Integer, List<T>> map, int row, int column, T defaultValue) {
- List<T> list = map.get(column);
- if(list == null)
- return defaultValue;
-
- if(row >= list.size())
- return defaultValue;
-
- T t = list.get(row);
-
- if(t == null)
- return defaultValue;
-
- return t;
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getChecked(int, int)
- */
- @Override
- public boolean getChecked(int row, int column) {
- return getValueOrDefault(checkeds, row, column, Boolean.FALSE);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getColumnSpan(int, int)
- */
- @Override
- public int getColumnSpan(int row, int column) {
- return getValueOrDefault(columnSpans, row, column, 0);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getRowSpan(int, int)
- */
- @Override
- public int getRowSpan(int row, int column) {
- return getValueOrDefault(rowSpans, row, column, 0);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getFont(int, int)
- */
- @Override
- public Font getFont(int row, int column) {
- return getValueOrDefault(fonts, row, column, defaultFont);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getForeground(int, int)
- */
- @Override
- public Color getForeground(int row, int column) {
- return getValueOrDefault(foregrounds, row, column, defaultForeground);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getGrayed(int, int)
- */
- @Override
- public boolean getGrayed(int row, int column) {
- return getValueOrDefault(grayeds, row,column, Boolean.FALSE);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getImage(int, int)
- */
- @Override
- public Image getImage(int row, int column) {
- return getValueOrDefault(images, row,column, null);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getText(int, int)
- */
- @Override
- public String getText(int row, int column) {
- return getValueOrDefault(texts, row, column, "");
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setBackground(int, int, org.eclipse.swt.graphics.Color)
- */
- @Override
- public void setBackground(int row, int column, Color color) {
- put(backgrounds, row, column, color);
- }
-
- /**
- * put value on maps.. inverted index for {@link RowColumnBigDataVisualizer}
- * @param map
- * @param row
- * @param column
- * @param value
- */
- protected <T> void put(Map<Integer, List<T>> map, int row, int column,
- T value) {
- List<T> list = map.get(column);
- if(list == null) {
- list = new ArrayList<T>();
- map.put(column, list);
- }
- while(row > list.size()) {
- list.add(null);
- }
- if(list.size() > row) {
- list.remove(row);
- }
- list.add(row, value);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setChecked(int, int, boolean)
- */
- @Override
- public void setChecked(int row, int column, boolean checked) {
- put(checkeds, row, column, checked);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setColumnSpan(int, int, int)
- */
- @Override
- public void setColumnSpan(int row, int column, int span) {
- put(columnSpans, row, column, span);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setRowSpan(int, int, int)
- */
- @Override
- public void setRowSpan(int row, int column, int span) {
- put(rowSpans, row, column, span);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setFont(int, int, org.eclipse.swt.graphics.Font)
- */
- @Override
- public void setFont(int row, int column, Font font) {
- put(fonts, row, column, font);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setForeground(int, int, org.eclipse.swt.graphics.Color)
- */
- @Override
- public void setForeground(int row, int column, Color foreground) {
- put(foregrounds, row, column, foreground);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setGrayed(int, int, boolean)
- */
- @Override
- public void setGrayed(int row, int column, boolean grayed) {
- put(grayeds, row, column, grayed);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setImage(int, int, org.eclipse.swt.graphics.Image)
- */
- @Override
- public void setImage(int row, int column, Image image) {
- put(images, row, column, image);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setText(int, int, java.lang.String)
- */
- @Override
- public void setText(int row, int column, String text) {
- put(texts, row, column, text);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getCheckable(int, int)
- */
- @Override
- public boolean getCheckable(int row, int column) {
- return getValueOrDefault(checkables, row,column, Boolean.TRUE);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setCheckable(int, int, boolean)
- */
- @Override
- public void setCheckable(int row, int column, boolean checked) {
- put(this.checkables, row, column, checked);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#getToolTipText(int, int)
- */
- @Override
- public String getToolTipText(int row, int column) {
- return getValueOrDefault(toolTipTexts, row,column, "");
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#setToolTipText(int, int, java.lang.String)
- */
- @Override
- public void setToolTipText(int row, int column, String tooltip) {
- put(texts, row, column, tooltip);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#removeIndex(int)
- */
- @Override
- public void removeIndex(int index) {
- texts.remove(index);
- toolTipTexts.remove(index);
- foregrounds.remove(index);
- backgrounds.remove(index);
- images.remove(index);
- fonts.remove(index);
- rowSpans.remove(index);
- columnSpans.remove(index);
- grayeds.remove(index);
- checkables.remove(index);
- checkeds.remove(index);
- }
-
- /**
- * In this implementation is too much expensive...
- * Empty is Much better
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#clearRow(int)
- */
- @Override
- public void clearRow(int row) {
- /*
- * Is empty
- */
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#clearColumn(int)
- */
- @Override
- public void clearColumn(int column) {
- removeIndex(column);
- }
-
- /**
- * @see org.eclipse.nebula.widgets.grid.DataVisualizer#createAndGetChildenGridItemDataVisualizer()
- */
- @Override
- public DataVisualizer createAndGetChildenGridItemDataVisualizer() {
- return new ColumnRowBigDataVisualizer(defaultBackground, defaultForeground, defaultFont);
- }
-
-}
diff --git a/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/DataVisualizer.java b/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/DataVisualizer.java
index 8d50aa5..cbe62f3 100644
--- a/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/DataVisualizer.java
+++ b/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/DataVisualizer.java
@@ -10,8 +10,6 @@
*******************************************************************************/
package org.eclipse.nebula.widgets.grid;
-import java.util.Map;
-
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
@@ -29,193 +27,191 @@ public interface DataVisualizer {
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @return {@link Color}
*/
- Color getBackground(int row, int index);
+ Color getBackground(GridItem gridItem, int index);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param i
* @return boolean
*/
- boolean getChecked(int row, int i);
+ boolean getChecked(GridItem gridItem, int i);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @return int
*/
- int getColumnSpan(int row, int index);
+ int getColumnSpan(GridItem gridItem, int index);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @return int
*/
- int getRowSpan(int row, int index);
+ int getRowSpan(GridItem gridItem, int index);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @return {@link Font}
*/
- Font getFont(int row, int index);
+ Font getFont(GridItem gridItem, int index);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @return {@link Color}
*/
- Color getForeground(int row, int index);
+ Color getForeground(GridItem gridItem, int index);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @return boolean
*/
- boolean getGrayed(int row, int index);
+ boolean getGrayed(GridItem gridItem, int index);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param i
* @return {@link Image}
*/
- Image getImage(int row, int i);
+ Image getImage(GridItem gridItem, int i);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param i
* @return {@link String}
*/
- String getText(int row, int i);
+ String getText(GridItem gridItem, int i);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @param color
*/
- void setBackground(int row, int index, Color color);
+ void setBackground(GridItem gridItem, int index, Color color);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param column
* @param checked
*/
- void setChecked(int row, int column, boolean checked);
+ void setChecked(GridItem gridItem, int column, boolean checked);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @param span
*/
- void setColumnSpan(int row, int index, int span);
+ void setColumnSpan(GridItem gridItem, int index, int span);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @param span
*/
- void setRowSpan(int row, int index, int span);
+ void setRowSpan(GridItem gridItem, int index, int span);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @param font
*/
- void setFont(int row, int index, Font font);
+ void setFont(GridItem gridItem, int index, Font font);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @param foreground
*/
- void setForeground(int row, int index, Color foreground);
+ void setForeground(GridItem gridItem, int index, Color foreground);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param i
* @param grayed
*/
- void setGrayed(int row, int i, boolean grayed);
+ void setGrayed(GridItem gridItem, int i, boolean grayed);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param i
* @param image
*/
- void setImage(int row, int i, Image image);
+ void setImage(GridItem gridItem, int i, Image image);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param i
* @param text
*/
- void setText(int row, int i, String text);
+ void setText(GridItem gridItem, int i, String text);
+
+ /**
+ * Insert a column on DataVisualizer
+ * @param column is the column index
+ */
+ void addColumn(int column);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @return boolean
*/
- boolean getCheckable(int row, int index);
+ boolean getCheckable(GridItem gridItem, int index);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @param checked
*/
- void setCheckable(int row, int index, boolean checked);
+ void setCheckable(GridItem gridItem, int index, boolean checked);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @return String
*/
- String getToolTipText(int row, int index);
+ String getToolTipText(GridItem gridItem, int index);
/**
* Method substitute GridItem method
- * @param row
+ * @param gridItem
* @param index
* @param tooltip
*/
- void setToolTipText(int row, int index, String tooltip);
-
- /**
- * remove {@link Map} index (key)
- * for {@link ColumnRowBigDataVisualizer} index is column
- * for {@link RowColumnBigDataVisualizer} index is row
- * @param index
- */
- void removeIndex(int index);
+ void setToolTipText(GridItem gridItem, int index, String tooltip);
/**
* Clear rows dataVisualizer values
- * @param row
+ * @param gridItem
*/
- void clearRow(int row);
+ void clearRow(GridItem gridItem);
/**
* Clear columns dataVisualizer values
@@ -237,10 +233,20 @@ public interface DataVisualizer {
* @return default font
*/
Font getDefaultFont();
-
+
+ /**
+ * set default background
+ */
+ void setDefaultBackground(Color defaultBackground);
+
+ /**
+ * set default foreground
+ */
+ void setDefaultForeground(Color defaultForeground);
+
/**
- * @return GridItem children dataVisualizer.
+ * set default font
*/
- DataVisualizer createAndGetChildenGridItemDataVisualizer();
+ void setDefaultFont(Font defaultFont);
}
diff --git a/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/Grid.java b/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/Grid.java
index 0998198..1974984 100644
--- a/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/Grid.java
+++ b/widgets/grid/org.eclipse.nebula.widgets.grid/src/org/eclipse/nebula/widgets/grid/Grid.java
@@ -107,17 +107,16 @@ import org.eclipse.swt.widgets.TypedListener;
* Mirko modified this widget for improve performace and reduce used memory
* fix memory leak and slow disposed object
*/
-public class Grid extends Canvas
-{
- //TODO: figure out better way to allow renderers to trigger events
- //TODO: scroll as necessary when performing drag select (current strategy ok)
- //TODO: need to refactor the way the range select remembers older selection
- //TODO: remember why i decided i needed to refactor the way the range select remembers older selection
- //TODO: need to alter how column drag selection works to allow selection of spanned cells
- //TODO: JAVADOC!
- //TODO: column freezing
+public class Grid extends Canvas {
+ //TODO: figure out better way to allow renderers to trigger events
+ //TODO: scroll as necessary when performing drag select (current strategy ok)
+ //TODO: need to refactor the way the range select remembers older selection
+ //TODO: remember why i decided i needed to refactor the way the range select remembers older selection
+ //TODO: need to alter how column drag selection works to allow selection of spanned cells
+ //TODO: JAVADOC!
+ //TODO: column freezing
- //TODO: Performance - need to cache top index
+ //TODO: Performance - need to cache top index
/**
* @return {@link DataVisualizer}
@@ -130,12 +129,12 @@ public class Grid extends Canvas
* Object holding the visible range
*/
public static class GridVisibleRange {
- private GridItem[] items = new GridItem[0];
- private GridColumn[] columns = new GridColumn[0];
+ private GridItem[] items = new GridItem[0];
+ private GridColumn[] columns = new GridColumn[0];
- /**
- * @return the current items shown
- */
+ /**
+ * @return the current items shown
+ */
public GridItem[] getItems() {
return items;
}
@@ -146,541 +145,538 @@ public class Grid extends Canvas
public GridColumn[] getColumns() {
return columns;
}
- }
-
+ }
+
/**
* Clear simply all GridItems
*/
- public void clearItems()
- {
- items.clear();
- rootItems.clear();
- deselectAll();
- redraw();
- }
-
- /**
- * Accessibility default action for column headers and column group headers.
- */
- private static final String ACC_COLUMN_DEFAULT_ACTION = "Click";
-
- /**
- * Accessibility default action for items.
- */
- private static final String ACC_ITEM_DEFAULT_ACTION = "Double Click";
-
- /**
- * Accessibility expand action for tree items.
- */
- private static final String ACC_ITEM_ACTION_EXPAND = "Expand";
-
- /**
- * Accessibility collapse action for tree items.
- */
- private static final String ACC_ITEM_ACTION_COLLAPSE = "Collapse";
-
- /**
- * Accessibility name for the column group header toggle button.
- */
- private static final String ACC_TOGGLE_BUTTON_NAME = "Toggle Button";
-
- /**
- * Alpha blending value used when drawing the dragged column header.
- */
- private static final int COLUMN_DRAG_ALPHA = 128;
-
- /**
- * Number of pixels below the header to draw the drop point.
- */
- private static final int DROP_POINT_LOWER_OFFSET = 3;
-
- /**
- * Horizontal scrolling increment, in pixels.
- */
- private static final int HORZ_SCROLL_INCREMENT = 5;
-
- /**
- * The area to the left and right of the column boundary/resizer that is
- * still considered the resizer area. This prevents a user from having to be
- * *exactly* over the resizer.
- */
- private static final int COLUMN_RESIZER_THRESHOLD = 4;
-
- /**
- * @see #COLUMN_RESIZER_THRESHOLD
- */
- private static final int ROW_RESIZER_THRESHOLD = 3;
-
-
- /**
- * The minimum width of a column header.
- */
- private static final int MIN_COLUMN_HEADER_WIDTH = 20;
- /**
- * The minimum height of a row header.
- */
- private static final int MIN_ROW_HEADER_HEIGHT = 10;
-
- /**
- * The number used when sizing the row header (i.e. size it for '1000')
- * initially.
- */
-// private static final int INITIAL_ROW_HEADER_SIZING_VALUE = 1000;
-
- /**
- * The factor to multiply the current row header sizing value by when
- * determining the next sizing value. Used for performance reasons.
- */
-// private static final int ROW_HEADER_SIZING_MULTIPLIER = 10;
-
- /**
- * Tracks whether the scroll values are correct. If not they will be
- * recomputed in onPaint. This allows us to get a free ride on top of the
- * OS's paint event merging to assure that we don't perform this expensive
- * operation when unnecessary.
- */
- private boolean scrollValuesObsolete = false;
-
- /**
- * All items in the table, not just root items.
- */
- private final List items = new ArrayList();
-
- /**
- * All root items.
- */
- private final List rootItems = new ArrayList();
-
- /**
- * List of selected items.
- */
- private final List selectedItems = new ArrayList();
-
- /**
- * Reference to the item in focus.
- */
- private GridItem focusItem;
-
- private boolean cellSelectionEnabled = false;
-
- private final List selectedCells = new ArrayList();
- private final List selectedCellsBeforeRangeSelect = new ArrayList();
-
- private boolean cellDragSelectionOccuring = false;
- private boolean cellRowDragSelectionOccuring = false;
- private boolean cellColumnDragSelectionOccuring = false;
- private boolean cellDragCTRL = false;
- private boolean followupCellSelectionEventOwed = false;
-
- private boolean cellSelectedOnLastMouseDown;
- private boolean cellRowSelectedOnLastMouseDown;
- private boolean cellColumnSelectedOnLastMouseDown;
-
- private GridColumn shiftSelectionAnchorColumn;
-
- private GridColumn focusColumn;
-
- private final List selectedColumns = new ArrayList();
-
- /**
- * This is the column that the user last navigated to, but may not be the focusColumn because
- * that column may be spanned in the current row. This is only used in situations where the user
- * has used the keyboard to navigate up or down in the table and the focusColumn has switched to
- * a new column because the intended column (was maintained in this var) was spanned. The table
- * will attempt to set focus back to the intended column during subsequent up/down navigations.
- */
- private GridColumn intendedFocusColumn;
-
-
- /**
- * List of table columns in creation/index order.
- */
- private final List columns = new ArrayList();
-
- /**
- * List of the table columns in the order they are displayed.
- */
- private final List displayOrderedColumns = new ArrayList();
-
- private GridColumnGroup[] columnGroups = new GridColumnGroup[0];
-
- /**
- * Renderer to paint the top left area when both column and row headers are
- * shown.
- */
- private IRenderer topLeftRenderer = new DefaultTopLeftRenderer();
-
- /**
- * Renderer to paint the bottom left area when row headers and column footers are shown
- */
- private IRenderer bottomLeftRenderer = new DefaultBottomLeftRenderer();
-
- /**
- * Renderer used to paint row headers.
- */
- private IRenderer rowHeaderRenderer = new DefaultRowHeaderRenderer();
-
- /**
- * Renderer used to paint empty column headers, used when the columns don't
- * fill the horz space.
- */
- private IRenderer emptyColumnHeaderRenderer = new DefaultEmptyColumnHeaderRenderer();
-
- /**
- * Renderer used to paint empty column footers, used when the columns don't
- * fill the horz space.
- */
- private IRenderer emptyColumnFooterRenderer = new DefaultEmptyColumnFooterRenderer();
-
- /**
- * Renderer used to paint empty cells to fill horz and vert space.
- */
- private GridCellRenderer emptyCellRenderer = new DefaultEmptyCellRenderer();
-
- /**
- * Renderer used to paint empty row headers when the rows don't fill the
- * vertical space.
- */
- private IRenderer emptyRowHeaderRenderer = new DefaultEmptyRowHeaderRenderer();
-
- /**
- * Renderers the UI affordance identifying where the dragged column will be
- * dropped.
- */
- private final IRenderer dropPointRenderer = new DefaultDropPointRenderer();
-
- /**
- * Renderer used to paint on top of an already painted row to denote focus.
- */
- private IRenderer focusRenderer = new DefaultFocusRenderer();
-
- /**
- * Are row headers visible?
- */
- private boolean rowHeaderVisible = false;
-
- /**
- * Are column headers visible?
- */
- private boolean columnHeadersVisible = false;
-
- /**
- * Are column footers visible?
- */
- private boolean columnFootersVisible = false;
-
- /**
- * Type of selection behavior. Valid values are SWT.SINGLE and SWT.MULTI.
- */
- private int selectionType = SWT.SINGLE;
-
- /**
- * True if selection highlighting is enabled.
- */
- private boolean selectionEnabled = true;
-
- /**
- * Default height of items. This value is used
- * for <code>GridItem</code>s with a height
- * of -1.
- */
- private int itemHeight = 1;
-
- private boolean userModifiedItemHeight = false;
-
- /**
- * Width of each row header.
- */
- private int rowHeaderWidth = 0;
-
- /**
- * The row header width is variable. The row header width gets larger as
- * more rows are added to the table to ensure that the row header has enough
- * room to display the longest string of numbers that display in the row
- * header. This determination of how wide to make the row header is rather
- * slow and therefore is only done at every 1000 items (or so). This
- * variable remembers how many items were last computed and therefore when
- * the number of items is greater than this value, we need to recalculate
- * the row header width. See newItem().
- */
-// private int lastRowHeaderWidthCalculationAt = 0;
-
- /**
- * Height of each column header.
- */
- private int headerHeight = 0;
-
- /**
- * Height of each column footer
- */
- private int footerHeight = 0;
-
- /**
- * True if mouse is hover on a column boundary and can resize the column.
- */
- boolean hoveringOnColumnResizer = false;
-
- /**
- * Reference to the column being resized.
- */
- private GridColumn columnBeingResized;
-
- /**
- * Are this <code>Grid</code>'s rows resizeable?
- */
- private boolean rowsResizeable = false;
-
- /**
- * Is the user currently resizing a column?
- */
- private boolean resizingColumn = false;
-
- /**
- * The mouse X position when the user starts the resize.
- */
- private int resizingStartX = 0;
-
- /**
- * The width of the column when the user starts the resize. This, together
- * with the resizingStartX determines the current width during resize.
- */
- private int resizingColumnStartWidth = 0;
-
- private boolean hoveringOnRowResizer = false;
- private GridItem rowBeingResized;
+ public void clearItems() {
+ items.clear();
+ rootItems.clear();
+ deselectAll();
+ redraw();
+ }
+
+ /**
+ * Accessibility default action for column headers and column group headers.
+ */
+ private static final String ACC_COLUMN_DEFAULT_ACTION = "Click";
+
+ /**
+ * Accessibility default action for items.
+ */
+ private static final String ACC_ITEM_DEFAULT_ACTION = "Double Click";
+
+ /**
+ * Accessibility expand action for tree items.
+ */
+ private static final String ACC_ITEM_ACTION_EXPAND = "Expand";
+
+ /**
+ * Accessibility collapse action for tree items.
+ */
+ private static final String ACC_ITEM_ACTION_COLLAPSE = "Collapse";
+
+ /**
+ * Accessibility name for the column group header toggle button.
+ */
+ private static final String ACC_TOGGLE_BUTTON_NAME = "Toggle Button";
+
+ /**
+ * Alpha blending value used when drawing the dragged column header.
+ */
+ private static final int COLUMN_DRAG_ALPHA = 128;
+
+ /**
+ * Number of pixels below the header to draw the drop point.
+ */
+ private static final int DROP_POINT_LOWER_OFFSET = 3;
+
+ /**
+ * Horizontal scrolling increment, in pixels.
+ */
+ private static final int HORZ_SCROLL_INCREMENT = 5;
+
+ /**
+ * The area to the left and right of the column boundary/resizer that is
+ * still considered the resizer area. This prevents a user from having to be
+ * *exactly* over the resizer.
+ */
+ private static final int COLUMN_RESIZER_THRESHOLD = 4;
+
+ /**
+ * @see #COLUMN_RESIZER_THRESHOLD
+ */
+ private static final int ROW_RESIZER_THRESHOLD = 3;
+
+ /**
+ * The minimum width of a column header.
+ */
+ private static final int MIN_COLUMN_HEADER_WIDTH = 20;
+ /**
+ * The minimum height of a row header.
+ */
+ private static final int MIN_ROW_HEADER_HEIGHT = 10;
+
+ /**
+ * The number used when sizing the row header (i.e. size it for '1000')
+ * initially.
+ */
+ // private static final int INITIAL_ROW_HEADER_SIZING_VALUE = 1000;
+
+ /**
+ * The factor to multiply the current row header sizing value by when
+ * determining the next sizing value. Used for performance reasons.
+ */
+ // private static final int ROW_HEADER_SIZING_MULTIPLIER = 10;
+
+ /**
+ * Tracks whether the scroll values are correct. If not they will be
+ * recomputed in onPaint. This allows us to get a free ride on top of the
+ * OS's paint event merging to assure that we don't perform this expensive
+ * operation when unnecessary.
+ */
+ private boolean scrollValuesObsolete = false;
+
+ /**
+ * All items in the table, not just root items.
+ */
+ private final List items = new ArrayList();
+
+ /**
+ * All root items.
+ */
+ private final List rootItems = new ArrayList();
+
+ /**
+ * List of selected items.
+ */
+ private final List selectedItems = new ArrayList();
+
+ /**
+ * Reference to the item in focus.
+ */
+ private GridItem focusItem;
+
+ private boolean cellSelectionEnabled = false;
+
+ private final List selectedCells = new ArrayList();
+ private final List selectedCellsBeforeRangeSelect = new ArrayList();
+
+ private boolean cellDragSelectionOccuring = false;
+ private boolean cellRowDragSelectionOccuring = false;
+ private boolean cellColumnDragSelectionOccuring = false;
+ private boolean cellDragCTRL = false;
+ private boolean followupCellSelectionEventOwed = false;
+
+ private boolean cellSelectedOnLastMouseDown;
+ private boolean cellRowSelectedOnLastMouseDown;
+ private boolean cellColumnSelectedOnLastMouseDown;
+
+ private GridColumn shiftSelectionAnchorColumn;
+
+ private GridColumn focusColumn;
+
+ private final List selectedColumns = new ArrayList();
+
+ /**
+ * This is the column that the user last navigated to, but may not be the focusColumn because
+ * that column may be spanned in the current row. This is only used in situations where the user
+ * has used the keyboard to navigate up or down in the table and the focusColumn has switched to
+ * a new column because the intended column (was maintained in this var) was spanned. The table
+ * will attempt to set focus back to the intended column during subsequent up/down navigations.
+ */
+ private GridColumn intendedFocusColumn;
+
+ /**
+ * List of table columns in creation/index order.
+ */
+ private final List columns = new ArrayList();
+
+ /**
+ * List of the table columns in the order they are displayed.
+ */
+ private final List displayOrderedColumns = new ArrayList();
+
+ private GridColumnGroup[] columnGroups = new GridColumnGroup[0];
+
+ /**
+ * Renderer to paint the top left area when both column and row headers are
+ * shown.
+ */
+ private IRenderer topLeftRenderer = new DefaultTopLeftRenderer();
+
+ /**
+ * Renderer to paint the bottom left area when row headers and column footers are shown
+ */
+ private IRenderer bottomLeftRenderer = new DefaultBottomLeftRenderer();
+
+ /**
+ * Renderer used to paint row headers.
+ */
+ private IRenderer rowHeaderRenderer = new DefaultRowHeaderRenderer();
+
+ /**
+ * Renderer used to paint empty column headers, used when the columns don't
+ * fill the horz space.
+ */
+ private IRenderer emptyColumnHeaderRenderer = new DefaultEmptyColumnHeaderRenderer();
+
+ /**
+ * Renderer used to paint empty column footers, used when the columns don't
+ * fill the horz space.
+ */
+ private IRenderer emptyColumnFooterRenderer = new DefaultEmptyColumnFooterRenderer();
+
+ /**
+ * Renderer used to paint empty cells to fill horz and vert space.
+ */
+ private GridCellRenderer emptyCellRenderer = new DefaultEmptyCellRenderer();
+
+ /**
+ * Renderer used to paint empty row headers when the rows don't fill the
+ * vertical space.
+ */
+ private IRenderer emptyRowHeaderRenderer = new DefaultEmptyRowHeaderRenderer();
+
+ /**
+ * Renderers the UI affordance identifying where the dragged column will be
+ * dropped.
+ */
+ private final IRenderer dropPointRenderer = new DefaultDropPointRenderer();
+
+ /**
+ * Renderer used to paint on top of an already painted row to denote focus.
+ */
+ private IRenderer focusRenderer = new DefaultFocusRenderer();
+
+ /**
+ * Are row headers visible?
+ */
+ private boolean rowHeaderVisible = false;
+
+ /**
+ * Are column headers visible?
+ */
+ private boolean columnHeadersVisible = false;
+
+ /**
+ * Are column footers visible?
+ */
+ private boolean columnFootersVisible = false;
+
+ /**
+ * Type of selection behavior. Valid values are SWT.SINGLE and SWT.MULTI.
+ */
+ private int selectionType = SWT.SINGLE;
+
+ /**
+ * True if selection highlighting is enabled.
+ */
+ private boolean selectionEnabled = true;
+
+ /**
+ * Default height of items. This value is used
+ * for <code>GridItem</code>s with a height
+ * of -1.
+ */
+ private int itemHeight = 1;
+
+ private boolean userModifiedItemHeight = false;
+
+ /**
+ * Width of each row header.
+ */
+ private int rowHeaderWidth = 0;
+
+ /**
+ * The row header width is variable. The row header width gets larger as
+ * more rows are added to the table to ensure that the row header has enough
+ * room to display the longest string of numbers that display in the row
+ * header. This determination of how wide to make the row header is rather
+ * slow and therefore is only done at every 1000 items (or so). This
+ * variable remembers how many items were last computed and therefore when
+ * the number of items is greater than this value, we need to recalculate
+ * the row header width. See newItem().
+ */
+ // private int lastRowHeaderWidthCalculationAt = 0;
+
+ /**
+ * Height of each column header.
+ */
+ private int headerHeight = 0;
+
+ /**
+ * Height of each column footer
+ */
+ private int footerHeight = 0;
+
+ /**
+ * True if mouse is hover on a column boundary and can resize the column.
+ */
+ boolean hoveringOnColumnResizer = false;
+
+ /**
+ * Reference to the column being resized.
+ */
+ private GridColumn columnBeingResized;
+
+ /**
+ * Are this <code>Grid</code>'s rows resizeable?
+ */
+ private boolean rowsResizeable = false;
+
+ /**
+ * Is the user currently resizing a column?
+ */
+ private boolean resizingColumn = false;
+
+ /**
+ * The mouse X position when the user starts the resize.
+ */
+ private int resizingStartX = 0;
+
+ /**
+ * The width of the column when the user starts the resize. This, together
+ * with the resizingStartX determines the current width during resize.
+ */
+ private int resizingColumnStartWidth = 0;
+
+ private boolean hoveringOnRowResizer = false;
+ private GridItem rowBeingResized;
private boolean resizingRow = false;
private int resizingStartY;
private int resizingRowStartHeight;
- /**
- * Reference to the column whose header is currently in a pushed state.
- */
- private GridColumn columnBeingPushed;
-
- /**
- * Is the user currently pushing a column header?
- */
- private boolean pushingColumn = false;
-
- /**
- * Is the user currently pushing a column header and hovering over that same
- * header?
- */
- private boolean pushingAndHovering = false;
-
- /**
- * X position of the mouse when the user first pushes a column header.
- */
- private int startHeaderPushX = 0;
-
- /**
- * X position of the mouse when the user has initiated a drag. This is
- * different than startHeaderPushX because the mouse is allowed some
- * 'wiggle-room' until the header is put into drag mode.
- */
- private int startHeaderDragX = 0;
-
- /**
- * The current X position of the mouse during a header drag.
- */
- private int currentHeaderDragX = 0;
-
- /**
- * Are we currently dragging a column header?
- */
- private boolean draggingColumn = false;
-
- private GridColumn dragDropBeforeColumn = null;
-
- private GridColumn dragDropAfterColumn = null;
-
- /**
- * True if the current dragDropPoint is a valid drop point for the dragged
- * column. This is false if the column groups are involved and a column is
- * being dropped into or out of its column group.
- */
- private boolean dragDropPointValid = true;
-
- /**
- * Reference to the currently item that the mouse is currently hovering
- * over.
- */
- private GridItem hoveringItem;
-
- /**
- * Reference to the column that the mouse is currently hovering over.
- * Includes the header and all cells (all rows) in this column.
- */
- private GridColumn hoveringColumn;
-
- private GridColumn hoveringColumnHeader;
-
- private GridColumnGroup hoverColumnGroupHeader;
-
- /**
- * String-based detail of what is being hovered over in a cell. This allows
- * a renderer to differentiate between hovering over different parts of the
- * cell. For example, hovering over a checkbox in the cell or hovering over
- * a tree node in the cell. The table does nothing with this string except
- * to set it back in the renderer when its painted. The renderer sets this
- * during its notify method (InternalWidget.HOVER) and the table pulls it
- * back and maintains it so it can be set back when the cell is painted. The
- * renderer determines what the hover detail means and how it affects
- * painting.
- */
- private String hoveringDetail = "";
-
- /**
- * True if the mouse is hovering of a cell's text.
- */
- private boolean hoveringOverText = false;
-
- /**
- * Are the grid lines visible?
- */
- private boolean linesVisible = true;
-
- /**
- * Are tree lines visible?
- */
+ /**
+ * Reference to the column whose header is currently in a pushed state.
+ */
+ private GridColumn columnBeingPushed;
+
+ /**
+ * Is the user currently pushing a column header?
+ */
+ private boolean pushingColumn = false;
+
+ /**
+ * Is the user currently pushing a column header and hovering over that same
+ * header?
+ */
+ private boolean pushingAndHovering = false;
+
+ /**
+ * X position of the mouse when the user first pushes a column header.
+ */
+ private int startHeaderPushX = 0;
+
+ /**
+ * X position of the mouse when the user has initiated a drag. This is
+ * different than startHeaderPushX because the mouse is allowed some
+ * 'wiggle-room' until the header is put into drag mode.
+ */
+ private int startHeaderDragX = 0;
+
+ /**
+ * The current X position of the mouse during a header drag.
+ */
+ private int currentHeaderDragX = 0;
+
+ /**
+ * Are we currently dragging a column header?
+ */
+ private boolean draggingColumn = false;
+
+ private GridColumn dragDropBeforeColumn = null;
+
+ private GridColumn dragDropAfterColumn = null;
+
+ /**
+ * True if the current dragDropPoint is a valid drop point for the dragged
+ * column. This is false if the column groups are involved and a column is
+ * being dropped into or out of its column group.
+ */
+ private boolean dragDropPointValid = true;
+
+ /**
+ * Reference to the currently item that the mouse is currently hovering
+ * over.
+ */
+ private GridItem hoveringItem;
+
+ /**
+ * Reference to the column that the mouse is currently hovering over.
+ * Includes the header and all cells (all rows) in this column.
+ */
+ private GridColumn hoveringColumn;
+
+ private GridColumn hoveringColumnHeader;
+
+ private GridColumnGroup hoverColumnGroupHeader;
+
+ /**
+ * String-based detail of what is being hovered over in a cell. This allows
+ * a renderer to differentiate between hovering over different parts of the
+ * cell. For example, hovering over a checkbox in the cell or hovering over
+ * a tree node in the cell. The table does nothing with this string except
+ * to set it back in the renderer when its painted. The renderer sets this
+ * during its notify method (InternalWidget.HOVER) and the table pulls it
+ * back and maintains it so it can be set back when the cell is painted. The
+ * renderer determines what the hover detail means and how it affects
+ * painting.
+ */
+ private String hoveringDetail = "";
+
+ /**
+ * True if the mouse is hovering of a cell's text.
+ */
+ private boolean hoveringOverText = false;
+
+ /**
+ * Are the grid lines visible?
+ */
+ private boolean linesVisible = true;
+
+ /**
+ * Are tree lines visible?
+ */
private boolean treeLinesVisible = true;
- /**
- * Grid line color.
- */
- private Color lineColor;
-
- /**
- * Vertical scrollbar proxy.
- * <p>
- * Note:
- * <ul>
- * <li>{@link Grid#getTopIndex()} is the only method allowed to call vScroll.getSelection()
- * (except #updateScrollbars() of course)</li>
- * <li>{@link Grid#setTopIndex(int)} is the only method allowed to call vScroll.setSelection(int)</li>
- * </ul>
- */
- private IScrollBarProxy vScroll;
-
- /**
- * Horizontal scrollbar proxy.
- */
- private IScrollBarProxy hScroll;
-
- /**
- * The number of GridItems whose visible = true. Maintained for
- * performance reasons (rather than iterating over all items).
- */
- private int currentVisibleItems = 0;
-
- /**
- * Item selected when a multiple selection using shift+click first occurs.
- * This item anchors all further shift+click selections.
- */
- private GridItem shiftSelectionAnchorItem;
-
- private boolean columnScrolling = false;
-
- private int groupHeaderHeight;
-
- private Color cellHeaderSelectionBackground;
-
- /**
- * Dispose listener. This listener is removed during the dispose event to allow re-firing of
- * the event.
- */
- private Listener disposeListener;
-
- /**
- * The inplace tooltip.
- */
- private GridToolTip inplaceToolTip;
-
- private final GC sizingGC;
-
- private Color backgroundColor;
-
- /**
- * True if the widget is being disposed. When true, events are not fired.
- */
- private boolean disposing = false;
-
- /**
- * True if there is at least one tree node. This is used by accessibility and various
- * places for optimization.
- */
- private boolean isTree = false;
-
- /**
- * True if there is at least one <code>GridItem</code> with an individual height.
- * This value is only set to true in {@link GridItem#setHeight(int,boolean)}
- * and it is never reset to false.
- */
- boolean hasDifferingHeights = false;
-
- /**
- * True if three is at least one cell spanning columns. This is used in various places for
- * optimizatoin.
- */
- private boolean hasSpanning = false;
-
- /**
- * Index of first visible item. The value must never be read directly. It is cached and
- * updated when appropriate. #getTopIndex should be called for every client (even internal
- * callers). A value of -1 indicates that the value is old and will be recomputed.
- *
- * @see #bottomIndex
- */
- int topIndex = -1;
- /**
- * Index of last visible item. The value must never be read directly. It is cached and
- * updated when appropriate. #getBottomIndex() should be called for every client (even internal
- * callers). A value of -1 indicates that the value is old and will be recomputed.
- * <p>
- * Note that the item with this index is often only partly visible; maybe only
- * a single line of pixels is visible. In extreme cases, bottomIndex may be the
- * same as topIndex.
- *
- * @see #topIndex
- */
- int bottomIndex = -1;
-
- /**
- * Index of the first visible column. A value of -1 indicates that the value is old and will be recomputed.
- */
- int startColumnIndex = -1;
-
- /**
- * Index of the the last visible column. A value of -1 indicates that the value is old and will be recomputed.
- */
- int endColumnIndex = -1;
-
- /**
- * True if the last visible item is completely visible. The value must never be read directly. It is cached and
- * updated when appropriate. #isShown() should be called for every client (even internal
- * callers).
- *
- * @see #bottomIndex
- */
- private boolean bottomIndexShownCompletely = false;
-
- /**
- * Tooltip text - overriden because we have cell specific tooltips
- */
- private String toolTipText = null;
-
- /**
- * Flag that is set to true as soon as one image is set on any one item.
- * This is used to mimic Table behavior that resizes the rows on the first image added.
- * See imageSetOnItem.
- */
- private boolean firstImageSet = false;
-
- /**
- * Mouse capture flag. Used for inplace tooltips. This flag must be used to ensure that
- * we don't setCapture(false) in situations where we didn't do setCapture(true). The OS (SWT?)
- * will automatically capture the mouse for us during a drag operation.
- */
+ /**
+ * Grid line color.
+ */
+ private Color lineColor;
+
+ /**
+ * Vertical scrollbar proxy.
+ * <p>
+ * Note:
+ * <ul>
+ * <li>{@link Grid#getTopIndex()} is the only method allowed to call vScroll.getSelection()
+ * (except #updateScrollbars() of course)</li>
+ * <li>{@link Grid#setTopIndex(int)} is the only method allowed to call vScroll.setSelection(int)</li>
+ * </ul>
+ */
+ private IScrollBarProxy vScroll;
+
+ /**
+ * Horizontal scrollbar proxy.
+ */
+ private IScrollBarProxy hScroll;
+
+ /**
+ * The number of GridItems whose visible = true. Maintained for
+ * performance reasons (rather than iterating over all items).
+ */
+ private int currentVisibleItems = 0;
+
+ /**
+ * Item selected when a multiple selection using shift+click first occurs.
+ * This item anchors all further shift+click selections.
+ */
+ private GridItem shiftSelectionAnchorItem;
+
+ private boolean columnScrolling = false;
+
+ private int groupHeaderHeight;
+
+ private Color cellHeaderSelectionBackground;
+
+ /**
+ * Dispose listener. This listener is removed during the dispose event to allow re-firing of
+ * the event.
+ */
+ private Listener disposeListener;
+
+ /**
+ * The inplace tooltip.
+ */
+ private GridToolTip inplaceToolTip;
+
+ private final GC sizingGC;
+
+ private Color backgroundColor;
+
+ /**
+ * True if the widget is being disposed. When true, events are not fired.
+ */
+ private boolean disposing = false;
+
+ /**
+ * True if there is at least one tree node. This is used by accessibility and various
+ * places for optimization.
+ */
+ private boolean isTree = false;
+
+ /**
+ * True if there is at least one <code>GridItem</code> with an individual height.
+ * This value is only set to true in {@link GridItem#setHeight(int,boolean)}
+ * and it is never reset to false.
+ */
+ boolean hasDifferingHeights = false;
+
+ /**
+ * True if three is at least one cell spanning columns. This is used in various places for
+ * optimizatoin.
+ */
+ private boolean hasSpanning = false;
+
+ /**
+ * Index of first visible item. The value must never be read directly. It is cached and
+ * updated when appropriate. #getTopIndex should be called for every client (even internal
+ * callers). A value of -1 indicates that the value is old and will be recomputed.
+ *
+ * @see #bottomIndex
+ */
+ int topIndex = -1;
+ /**
+ * Index of last visible item. The value must never be read directly. It is cached and
+ * updated when appropriate. #getBottomIndex() should be called for every client (even internal
+ * callers). A value of -1 indicates that the value is old and will be recomputed.
+ * <p>
+ * Note that the item with this index is often only partly visible; maybe only
+ * a single line of pixels is visible. In extreme cases, bottomIndex may be the
+ * same as topIndex.
+ *
+ * @see #topIndex
+ */
+ int bottomIndex = -1;
+
+ /**
+ * Index of the first visible column. A value of -1 indicates that the value is old and will be recomputed.
+ */
+ int startColumnIndex = -1;
+
+ /**
+ * Index of the the last visible column. A value of -1 indicates that the value is old and will be recomputed.
+ */
+ int endColumnIndex = -1;
+
+ /**
+ * True if the last visible item is completely visible. The value must never be read directly. It is cached and
+ * updated when appropriate. #isShown() should be called for every client (even internal
+ * callers).
+ *
+ * @see #bottomIndex
+ */
+ private boolean bottomIndexShownCompletely = false;
+
+ /**
+ * Tooltip text - overriden because we have cell specific tooltips
+ */
+ private String toolTipText = null;
+
+ /**
+ * Flag that is set to true as soon as one image is set on any one item.
+ * This is used to mimic Table behavior that resizes the rows on the first image added.
+ * See imageSetOnItem.
+ */
+ private boolean firstImageSet = false;
+
+ /**
+ * Mouse capture flag. Used for inplace tooltips. This flag must be used to ensure that
+ * we don't setCapture(false) in situations where we didn't do setCapture(true). The OS (SWT?)
+ * will automatically capture the mouse for us during a drag operation.
+ */
private boolean inplaceTooltipCapture;
/**
@@ -702,1406 +698,1294 @@ public class Grid extends Canvas
*/
private static final int SELECTION_DRAG_BORDER_THRESHOLD = 2;
- private boolean hoveringOnSelectionDragArea = false;
+ private boolean hoveringOnSelectionDragArea = false;
private GridItem insertMarkItem = null;
private GridColumn insertMarkColumn = null;
private boolean insertMarkBefore = false;
- private final IRenderer insertMarkRenderer = new DefaultInsertMarkRenderer();
- private boolean sizeOnEveryItemImageChange;
- private boolean autoHeight = false;
- private boolean autoWidth = true;
- private boolean wordWrapRowHeader = false;
+ private final IRenderer insertMarkRenderer = new DefaultInsertMarkRenderer();
+ private boolean sizeOnEveryItemImageChange;
+ private boolean autoHeight = false;
+ private boolean autoWidth = true;
+ private boolean wordWrapRowHeader = false;
private final DataVisualizer dataVisualizer;
- /**
- * A range of rows in a <code>Grid</code>.
- * <p>
- * A row in this sense exists only for visible items
- * (i.e. items with {@link GridItem#isVisible()} == true).
- * Therefore, the items at 'startIndex' and 'endIndex'
- * are always visible.
- *
- * @see Grid#getRowRange(int, int, boolean, boolean)
- */
- private static class RowRange {
- /** index of first item in range */
- public int startIndex;
- /** index of last item in range */
- public int endIndex;
- /** number of rows (i.e. <em>visible</em> items) in this range */
- public int rows;
- /** height in pixels of this range (including horizontal separator between rows) */
- public int height;
- }
-
- /**
- * Filters out unnecessary styles, adds mandatory styles and generally
- * manages the style to pass to the super class.
- *
- * @param style user specified style.
- * @return style to pass to the super class.
- */
- private static int checkStyle(int style)
- {
- int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.H_SCROLL | SWT.V_SCROLL
- | SWT.SINGLE | SWT.MULTI | SWT.NO_FOCUS | SWT.CHECK | SWT.VIRTUAL;
- int newStyle = style & mask;
- newStyle |= SWT.DOUBLE_BUFFERED;
- return newStyle;
- }
-
- /**
- * Grid with generic DataVisualizer
- */
- public Grid(Composite parent, int style) {
- this(new ColumnRowBigDataVisualizer(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE), Display.getCurrent().getSystemColor(SWT.COLOR_BLACK), null), parent, style);
- }
-
- /**
- * Constructs a new instance of this class given its parent and a style
- * value describing its behavior and appearance.
- * <p>
- * @param dataVisualizer manage all data of grid and its items
- * @param parent a composite control which will be the parent of the new
- * instance (cannot be null)
- * @param style the style of control to construct
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the parent</li>
- * </ul>
- * @see SWT#SINGLE
- * @see SWT#MULTI
- */
- public Grid(DataVisualizer dataVisualizer, Composite parent, int style)
- {
- super(parent, checkStyle(style));
- this.dataVisualizer = dataVisualizer;
-
- // initialize drag & drop support
- setData("DEFAULT_DRAG_SOURCE_EFFECT", new GridDragSourceEffect(this));
- setData("DEFAULT_DROP_TARGET_EFFECT", new GridDropTargetEffect(this));
-
- sizingGC = new GC(this);
-
- topLeftRenderer.setDisplay(getDisplay());
- bottomLeftRenderer.setDisplay(getDisplay());
- rowHeaderRenderer.setDisplay(getDisplay());
- emptyColumnHeaderRenderer.setDisplay(getDisplay());
- emptyColumnFooterRenderer.setDisplay(getDisplay());
- emptyCellRenderer.setDisplay(getDisplay());
- dropPointRenderer.setDisplay(getDisplay());
- focusRenderer.setDisplay(getDisplay());
- emptyRowHeaderRenderer.setDisplay(getDisplay());
- insertMarkRenderer.setDisplay(getDisplay());
-
- setForeground(getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND));
- setLineColor(getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
-
- if ((style & SWT.MULTI) != 0)
- {
- selectionType = SWT.MULTI;
- }
-
- if (getVerticalBar() != null)
- {
- getVerticalBar().setVisible(false);
- vScroll = new ScrollBarProxyAdapter(getVerticalBar());
- }
- else
- {
- vScroll = new NullScrollBarProxy();
- }
-
- if (getHorizontalBar() != null)
- {
- getHorizontalBar().setVisible(false);
- hScroll = new ScrollBarProxyAdapter(getHorizontalBar());
- }
- else
- {
- hScroll = new NullScrollBarProxy();
- }
-
- scrollValuesObsolete = true;
-
- initListeners();
- initAccessible();
-
-
- itemHeight = sizingGC.getFontMetrics().getHeight() + 2;
-
-
- RGB sel = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION).getRGB();
- RGB white = getDisplay().getSystemColor(SWT.COLOR_WHITE).getRGB();
-
- RGB cellSel = blend(sel,white,50);
-
- cellHeaderSelectionBackground = new Color(getDisplay(),cellSel);
-
- setDragDetect(false);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Color getBackground()
- {
- checkWidget();
- if (backgroundColor == null)
- return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
- return backgroundColor;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setBackground(Color color)
- {
- checkWidget();
- backgroundColor = color;
- redraw();
- }
-
- /**
- * Returns the background color of column and row headers when a cell in
- * the row or header is selected.
- *
- * @return cell header selection background color
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public Color getCellHeaderSelectionBackground()
- {
- checkWidget();
- return cellHeaderSelectionBackground;
- }
-
- /**
- * Sets the background color of column and row headers displayed when a cell in
- * the row or header is selected.
- *
- * @param cellSelectionBackground color to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setCellHeaderSelectionBackground(Color cellSelectionBackground)
- {
- checkWidget();
- this.cellHeaderSelectionBackground = cellSelectionBackground;
- }
-
- /**
- * Adds the listener to the collection of listeners who will be notified
- * when the receiver's selection changes, by sending it one of the messages
- * defined in the {@code SelectionListener} interface.
- * <p>
- * Cell selection events may have <code>Event.detail = SWT.DRAG</code> when the
- * user is drag selecting multiple cells. A follow up selection event will be generated
- * when the drag is complete.
- *
- * @param listener the listener which should be notified
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void addSelectionListener(SelectionListener listener)
- {
- checkWidget();
- if (listener == null)
- {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- addListener(SWT.Selection, new TypedListener(listener));
- addListener(SWT.DefaultSelection, new TypedListener(listener));
- }
-
- /**
- * Adds the listener to the collection of listeners who will be notified
- * when the receiver's items changes, by sending it one of the messages
- * defined in the {@code TreeListener} interface.
- *
- * @param listener the listener which should be notified
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see TreeListener
- * @see #removeTreeListener
- * @see org.eclipse.swt.events.TreeEvent
- */
- public void addTreeListener(TreeListener listener)
- {
- checkWidget();
- if (listener == null)
- {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
-
- addListener(SWT.Expand, new TypedListener(listener));
- addListener(SWT.Collapse, new TypedListener(listener));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Point computeSize(int wHint, int hHint, boolean changed)
- {
- checkWidget();
-
- Point prefSize = null;
- if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT)
- {
- prefSize = getTableSize();
- prefSize.x += 2 * getBorderWidth();
- prefSize.y += 2 * getBorderWidth();
- }
-
- int x = 0;
- int y = 0;
-
- if (wHint == SWT.DEFAULT)
- {
- x += prefSize.x;
- if (getVerticalBar() != null)
- {
- x += getVerticalBar().getSize().x;
- }
- }
- else
- {
- x = wHint;
- }
-
- if (hHint == SWT.DEFAULT)
- {
- y += prefSize.y;
- if (getHorizontalBar() != null)
- {
- y += getHorizontalBar().getSize().y;
- }
- }
- else
- {
- y = hHint;
- }
-
- return new Point(x, y);
- }
-
- /**
- * Deselects the item at the given zero-relative index in the receiver. If
- * the item at the index was already deselected, it remains deselected.
- * Indices that are out of range are ignored.
- * <p>
- * If cell selection is enabled, all cells in the specified item are deselected.
- *
- * @param index the index of the item to deselect
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void deselect(int index)
- {
- checkWidget();
-
- if (index < 0 || index > items.size() - 1)
- {
- return;
- }
-
- GridItem item = (GridItem)items.get(index);
-
- if (!cellSelectionEnabled)
- {
- if (selectedItems.contains(item))
- {
- selectedItems.remove(item);
- }
- }
- else
- {
- deselectCells(getCells(item));
- }
- redraw();
- }
-
- /**
- * Deselects the items at the given zero-relative indices in the receiver.
- * If the item at the given zero-relative index in the receiver is selected,
- * it is deselected. If the item at the index was not selected, it remains
- * deselected. The range of the indices is inclusive. Indices that are out
- * of range are ignored.
- * <p>
- * If cell selection is enabled, all cells in the given range are deselected.
- *
- * @param start the start index of the items to deselect
- * @param end the end index of the items to deselect
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void deselect(int start, int end)
- {
- checkWidget();
-
- for (int i = start; i <= end; i++)
- {
- if (i < 0)
- {
- continue;
- }
- if (i > items.size() - 1)
- {
- break;
- }
-
- GridItem item = (GridItem)items.get(i);
-
- if (!cellSelectionEnabled)
- {
- if (selectedItems.contains(item))
- {
- selectedItems.remove(item);
- }
- }
- else
- {
- deselectCells(getCells(item));
- }
- }
- redraw();
- }
-
- /**
- * Deselects the items at the given zero-relative indices in the receiver.
- * If the item at the given zero-relative index in the receiver is selected,
- * it is deselected. If the item at the index was not selected, it remains
- * deselected. Indices that are out of range and duplicate indices are
- * ignored.
- * <p>
- * If cell selection is enabled, all cells in the given items are deselected.
- *
- * @param indices the array of indices for the items to deselect
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the set of indices is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void deselect(int[] indices)
- {
- checkWidget();
- if (indices == null)
- {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
-
- for (int i = 0; i < indices.length; i++)
- {
- int j = indices[i];
-
- if (j >= 0 && j < items.size())
- {
- GridItem item = (GridItem)items.get(j);
-
- if (!cellSelectionEnabled)
- {
- if (selectedItems.contains(item))
- {
- selectedItems.remove(item);
- }
- }
- else
- {
- deselectCells(getCells(item));
- }
- }
- }
- redraw();
- }
-
- /**
- * Deselects all selected items in the receiver. If cell selection is enabled,
- * all cells are deselected.
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void deselectAll()
- {
- checkWidget();
-
- if (!cellSelectionEnabled)
- {
- selectedItems.clear();
- redraw();
- }
- else
- {
- deselectAllCells();
- }
- }
-
- /**
- * Returns the column at the given, zero-relative index in the receiver.
- * Throws an exception if the index is out of range. If no
- * {@code GridColumn}s were created by the programmer, this method will
- * throw {@code ERROR_INVALID_RANGE} despite the fact that a single column
- * of data may be visible in the table. This occurs when the programmer uses
- * the table like a list, adding items but never creating a column.
- *
- * @param index the index of the column to return
- * @return the column at the given index
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
- * of elements in the list minus 1 (inclusive)</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridColumn getColumn(int index)
- {
- checkWidget();
-
- if (index < 0 || index > getColumnCount() - 1)
- {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
-
- return (GridColumn)columns.get(index);
- }
-
- /**
- * Returns the column at the given point in the receiver or null if no such
- * column exists. The point is in the coordinate system of the receiver.
- *
- * @param point the point used to locate the column
- * @return the column at the given point
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridColumn getColumn(Point point)
- {
- return getColumn(null, point);
- }
-
- /**
- * Returns the column at the given point and a known item in the receiver or null if no such
- * column exists. The point is in the coordinate system of the receiver.
- *
- * @param item a known GridItem
- * @param point the point used to locate the column
- * @return the column at the given point
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- private GridColumn getColumn(GridItem item, Point point)
- {
- checkWidget();
- if (point == null)
- {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
-
- GridColumn overThis = null;
-
- int x2 = 0;
-
- if (rowHeaderVisible)
- {
- if (point.x <= rowHeaderWidth)
- {
- return null;
- }
-
- x2 += rowHeaderWidth;
- }
-
- x2 -= getHScrollSelectionInPixels();
-
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnIterator.next();
-
- if (!column.isVisible())
- {
- continue;
- }
-
- if (point.x >= x2 && point.x < x2 + column.getWidth())
- {
- overThis = column;
- break;
- }
-
- x2 += column.getWidth();
- }
-
- if (overThis == null)
- {
- return null;
- }
-
- if (hasSpanning)
- {
- // special logic for column spanning
- if(item == null) {
- item = getItem(point);
- }
-
- if (item != null)
- {
- int displayColIndex = displayOrderedColumns.indexOf(overThis);
-
- // track back all previous columns and check their spanning
- for (int i = 0; i < displayColIndex; i++)
- {
- if (!((GridColumn)displayOrderedColumns.get(i)).isVisible())
- {
- continue;
- }
-
- int colIndex = indexOf((GridColumn)displayOrderedColumns.get(i));
- int span = item.getColumnSpan(colIndex);
-
- if (i + span >= displayColIndex)
- {
- overThis = (GridColumn)displayOrderedColumns.get(i);
- break;
- }
- }
- }
- }
-
- return overThis;
- }
-
- /**
- * Returns the number of columns contained in the receiver. If no
- * {@code GridColumn}s 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 table like a list, adding items
- * but never creating a column.
- *
- * @return the number of columns
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getColumnCount()
- {
- checkWidget();
- return columns.size();
- }
-
- /**
- * Returns an array of zero-relative integers that map the creation order of
- * the receiver's items to the order in which they are currently being
- * displayed.
- * <p>
- * Specifically, the indices of the returned array represent the current
- * visual order of the items, and the contents of the array represent the
- * creation order of the items.
- * </p>
- * <p>
- * Note: This is not the actual structure used by the receiver to maintain
- * its list of items, so modifying the array will not affect the receiver.
- * </p>
- *
- * @return the current visual order of the receiver's items
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int[] getColumnOrder()
- {
- checkWidget();
-
- int[] order = new int[columns.size()];
- int i = 0;
- for (Iterator colIterator = displayOrderedColumns.iterator(); colIterator.hasNext(); )
- {
- GridColumn col = (GridColumn) colIterator.next();
- order[i] = columns.indexOf(col);
- i++;
- }
- return order;
- }
-
- /**
- * Returns the number of column groups contained in the receiver.
- *
- * @return the number of column groups
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getColumnGroupCount()
- {
- checkWidget();
- return columnGroups.length;
- }
-
- /**
- * Returns an array of {@code GridColumnGroup}s which are the column groups in the
- * receiver.
- * <p>
- * Note: This is not the actual structure used by the receiver to maintain
- * its list of items, so modifying the array will not affect the receiver.
- * </p>
- *
- * @return the column groups in the receiver
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridColumnGroup[] getColumnGroups()
- {
- checkWidget();
- GridColumnGroup[] newArray = new GridColumnGroup[columnGroups.length];
- System.arraycopy (columnGroups, 0, newArray, 0, columnGroups.length);
- return newArray;
- }
-
- /**
- * Returns the column group at the given, zero-relative index in the receiver.
- * Throws an exception if the index is out of range.
- *
- * @param index the index of the column group to return
- * @return the column group at the given index
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
- * of elements in the list minus 1 (inclusive)</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridColumnGroup getColumnGroup(int index)
- {
- checkWidget();
-
- if (index < 0 || index >= columnGroups.length)
- SWT.error(SWT.ERROR_INVALID_RANGE);
-
- return columnGroups[index];
- }
-
- /**
- * Sets the order that the items in the receiver should be displayed in to
- * the given argument which is described in terms of the zero-relative
- * ordering of when the items were added.
- *
- * @param order the new order to display the items
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS -if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the item order is null</li>
- * <li>ERROR_INVALID_ARGUMENT - if the order is not the same length as the
- * number of items, or if an item is listed twice, or if the order splits a
- * column group</li>
- * </ul>
- */
- public void setColumnOrder(int[] order)
- {
- checkWidget();
-
- if (order == null)
- {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
-
- if (order.length != displayOrderedColumns.size())
- {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
-
- boolean[] seen = new boolean[displayOrderedColumns.size()];
-
- for (int i = 0; i < order.length; i++)
- {
- if (order[i] < 0 || order[i] >= displayOrderedColumns.size())
- {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- if (seen[order[i]])
- {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- seen[order[i]] = true;
- }
-
- if (columnGroups.length != 0)
- {
- GridColumnGroup currentGroup = null;
- int colsInGroup = 0;
-
- for (int i = 0; i < order.length; i++)
- {
- GridColumn col = getColumn(order[i]);
-
- if (currentGroup != null)
- {
- if (col.getColumnGroup() != currentGroup && colsInGroup > 0 )
- {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- else
- {
- colsInGroup--;
- if (colsInGroup <= 0)
- {
- currentGroup = null;
- }
- }
- }
- else if (col.getColumnGroup() != null)
- {
- currentGroup = col.getColumnGroup();
- colsInGroup = currentGroup.getColumns().length - 1;
- }
- }
- }
-
- GridColumn[] cols = getColumns();
-
- displayOrderedColumns.clear();
-
- for (int i = 0; i < order.length; i++)
- {
- displayOrderedColumns.add(cols[order[i]]);
- }
- }
-
- /**
- * Returns an array of {@code GridColumn}s which are the columns in the
- * receiver. If no {@code GridColumn}s were created by the programmer,
- * the array is empty, despite the fact that visually, one column of items
- * may be visible. This occurs when the programmer uses the table like a
- * list, adding items but never creating a column.
- * <p>
- * Note: This is not the actual structure used by the receiver to maintain
- * its list of items, so modifying the array will not affect the receiver.
- * </p>
- *
- * @return the items in the receiver
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridColumn[] getColumns()
- {
- checkWidget();
- return (GridColumn[])columns.toArray(new GridColumn[columns.size()]);
- }
-
- /**
- * Returns the empty cell renderer.
- *
- * @return Returns the emptyCellRenderer.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridCellRenderer getEmptyCellRenderer()
- {
- checkWidget();
- return emptyCellRenderer;
- }
-
- /**
- * Returns the empty column header renderer.
- *
- * @return Returns the emptyColumnHeaderRenderer.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public IRenderer getEmptyColumnHeaderRenderer()
- {
- checkWidget();
- return emptyColumnHeaderRenderer;
- }
-
- /**
- * Returns the empty column footer renderer.
- *
- * @return Returns the emptyColumnFooterRenderer.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public IRenderer getEmptyColumnFooterRenderer() {
- checkWidget();
- return emptyColumnFooterRenderer;
- }
-
- /**
- * Returns the empty row header renderer.
- *
- * @return Returns the emptyRowHeaderRenderer.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public IRenderer getEmptyRowHeaderRenderer()
- {
- checkWidget();
- return emptyRowHeaderRenderer;
- }
-
- /**
- * Returns the externally managed horizontal scrollbar.
- *
- * @return the external horizontal scrollbar.
- * @see #setHorizontalScrollBarProxy(IScrollBarProxy)
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- protected IScrollBarProxy getHorizontalScrollBarProxy()
- {
- checkWidget();
- return hScroll;
- }
-
- /**
- * Returns the externally managed vertical scrollbar.
- *
- * @return the external vertical scrollbar.
- * @see #setlVerticalScrollBarProxy(IScrollBarProxy)
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- protected IScrollBarProxy getVerticalScrollBarProxy()
- {
- checkWidget();
- return vScroll;
- }
-
- /**
- * Gets the focus renderer.
- *
- * @return Returns the focusRenderer.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public IRenderer getFocusRenderer()
- {
- checkWidget();
- return focusRenderer;
- }
-
- /**
- * Returns the height of the column headers. If this table has column
- * groups, the returned value includes the height of group headers.
- *
- * @return height of the column header row
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getHeaderHeight()
- {
- checkWidget();
- return headerHeight;
- }
-
- /**
- * Returns the height of the column footers.
- *
- * @return height of the column footer row
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getFooterHeight() {
- checkWidget();
- return footerHeight;
- }
-
- /**
- * Returns the height of the column group headers.
- *
- * @return height of column group headers
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getGroupHeaderHeight()
- {
- checkWidget();
- return groupHeaderHeight;
- }
-
- /**
- * Returns {@code true} if the receiver's header is visible, and
- * {@code false} otherwise.
- *
- * @return the receiver's header's visibility state
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean getHeaderVisible()
- {
- checkWidget();
- return columnHeadersVisible;
- }
-
- /**
- * Returns {@code true} if the receiver's footer is visible, and {@code false} otherwise
- * @return the receiver's footer's visibility state
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean getFooterVisible() {
- checkWidget();
- return columnFootersVisible;
- }
-
- /**
- * Returns the item at the given, zero-relative index in the receiver.
- * Throws an exception if the index is out of range.
- *
- * @param index the index of the item to return
- * @return the item at the given index
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the
- * list minus 1 (inclusive) </li> *
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridItem getItem(int index)
- {
- checkWidget();
-
- if (index < 0 || index >= items.size())
- {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
-
- return (GridItem)items.get(index);
- }
-
- /**
- * Returns the item at the given point in the receiver or null if no such
- * item exists. The point is in the coordinate system of the receiver.
- *
- * @param point the point used to locate the item
- * @return the item at the given point
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridItem getItem(Point point)
- {
- checkWidget();
-
- if (point == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- if (point.x < 0 || point.x > getClientArea().width) return null;
-
- Point p = new Point(point.x, point.y);
-
- int y2=0;
-
- if (columnHeadersVisible)
- {
- if (p.y <= headerHeight)
- {
- return null;
- }
- y2 += headerHeight;
- }
-
- GridItem itemToReturn = null;
-
- int row=getTopIndex();
- while(row<items.size() && y2<=getClientArea().height)
- {
- GridItem currItem = (GridItem)items.get(row);
- if (currItem.isVisible())
- {
- int currItemHeight = currItem.getHeight();
-
- if (p.y >= y2 && p.y < y2+currItemHeight+1)
- {
- itemToReturn = currItem;
- break;
- }
-
- y2 += currItemHeight +1;
- }
- row++;
- }
-
- if (hasSpanning)
- {
- if (itemToReturn != null)
- {
- int itemIndex = this.getIndexOfItem(itemToReturn);
-
- GridColumn gridColumn = getColumn(itemToReturn, point);
- int displayColIndex = displayOrderedColumns.indexOf(gridColumn);
-
-
- // track back all previous columns and check their spanning
- for (int i = 0; i < itemIndex; i++)
- {
- GridItem gridItem = this.getItem(i);
- if (gridItem.isVisible() == false)
- {
- continue;
- }
- int span = gridItem.getRowSpan(displayColIndex);
-
- if (i + span >= itemIndex)
- {
- itemToReturn = gridItem;
- break;
- }
- }
- }
- }
-
- return itemToReturn;
- }
-
- /**
- * Returns the number of items contained in the receiver.
- *
- * @return the number of items
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getItemCount()
- {
- checkWidget();
- return getItems().length;
- }
-
- /**
- * Returns the default height of the items
- * in this <code>Grid</code>. See {@link #setItemHeight(int)}
- * for details.
- *
- * <p>IMPORTANT: The Grid's items need not all have the
- * height returned by this method, because an
- * item's height may have been changed by calling
- * {@link GridItem#setHeight(int)}.
- *
- * @return default height of items
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see #setItemHeight(int)
- */
- public int getItemHeight()
- {
- checkWidget();
- return itemHeight;
- }
-
- /**
- * Sets the default height for this <code>Grid</code>'s items. When
- * this method is called, all existing items are resized
- * to the specified height and items created afterwards will be
- * initially sized to this height.
- * <p>
- * As long as no default height was set by the client through this method,
- * the preferred height of the first item in this <code>Grid</code> is
- * used as a default for all items (and is returned by {@link #getItemHeight()}).
- *
- * @param height default height in pixels
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_ARGUMENT - if the height is < 1</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- *
- * @see GridItem#getHeight()
- * @see GridItem#setHeight(int)
- */
- public void setItemHeight(int height)
- {
- checkWidget();
- if (height < 1)
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- itemHeight = height;
- userModifiedItemHeight = true;
- for(int cnt=0;cnt<items.size();cnt++)
- ((GridItem)items.get(cnt)).setHeight(height);
- hasDifferingHeights=false;
- setScrollValuesObsolete();
- redraw();
- }
-
- /**
- * Returns true if the rows are resizable.
- *
- * @return the row resizeable state
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see #setRowsResizeable(boolean)
- */
- public boolean getRowsResizeable() {
- checkWidget();
- return rowsResizeable;
- }
- /**
- * Sets the rows resizeable state of this <code>Grid</code>.
- * The default is 'false'.
- * <p>
- * If a row in a <code>Grid</code> is resizeable,
- * then the user can interactively change its height
- * by dragging the border of the row header.
- * <p>
- * Note that for rows to be resizable the row headers must be visible.
- *
- * @param rowsResizeable true if this <code>Grid</code>'s rows should be resizable
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see #setRowHeaderVisible(boolean)
- */
- public void setRowsResizeable(boolean rowsResizeable) {
- checkWidget();
- this.rowsResizeable=rowsResizeable;
- }
-
- /**
- * Returns a (possibly empty) array of {@code GridItem}s which are the
- * items in the receiver.
- * <p>
- * Note: This is not the actual structure used by the receiver to maintain
- * its list of items, so modifying the array will not affect the receiver.
- * </p>
- *
- * @return the items in the receiver
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridItem[] getItems()
- {
- checkWidget();
- return (GridItem[])items.toArray(new GridItem[items.size()]);
- }
-
- /**
- *
- * @param item
- * @return t
- */
- public int getIndexOfItem(GridItem item)
- {
- checkWidget();
-
- return items.indexOf(item);
- }
-
- /**
- * Returns the line color.
- *
- * @return Returns the lineColor.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public Color getLineColor()
- {
- checkWidget();
- return lineColor;
- }
-
- /**
- * Returns true if the lines are visible.
- *
- * @return Returns the linesVisible.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean getLinesVisible()
- {
- checkWidget();
- return linesVisible;
- }
+ /**
+ * A range of rows in a <code>Grid</code>.
+ * <p>
+ * A row in this sense exists only for visible items
+ * (i.e. items with {@link GridItem#isVisible()} == true).
+ * Therefore, the items at 'startIndex' and 'endIndex'
+ * are always visible.
+ *
+ * @see Grid#getRowRange(int, int, boolean, boolean)
+ */
+ private static class RowRange {
+ /** index of first item in range */
+ public int startIndex;
+ /** index of last item in range */
+ public int endIndex;
+ /** number of rows (i.e. <em>visible</em> items) in this range */
+ public int rows;
+ /** height in pixels of this range (including horizontal separator between rows) */
+ public int height;
+ }
+
+ /**
+ * Filters out unnecessary styles, adds mandatory styles and generally
+ * manages the style to pass to the super class.
+ *
+ * @param style user specified style.
+ * @return style to pass to the super class.
+ */
+ private static int checkStyle(int style) {
+ int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE
+ | SWT.MULTI | SWT.NO_FOCUS | SWT.CHECK | SWT.VIRTUAL;
+ int newStyle = style & mask;
+ newStyle |= SWT.DOUBLE_BUFFERED;
+ return newStyle;
+ }
+
+ /**
+ * Grid with generic DataVisualizer
+ */
+ public Grid(Composite parent, int style) {
+ this(new GridItemDataVisualizer(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE), Display.getCurrent()
+ .getSystemColor(SWT.COLOR_BLACK), null), parent, style);
+ }
+
+ /**
+ * Constructs a new instance of this class given its parent and a style
+ * value describing its behavior and appearance.
+ * <p>
+ * @param dataVisualizer manage all data of grid and its items
+ * @param parent a composite control which will be the parent of the new
+ * instance (cannot be null)
+ * @param style the style of control to construct
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the parent</li>
+ * </ul>
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ */
+ public Grid(DataVisualizer dataVisualizer, Composite parent, int style) {
+ super(parent, checkStyle(style));
+ this.dataVisualizer = dataVisualizer;
+
+ // initialize drag & drop support
+ setData("DEFAULT_DRAG_SOURCE_EFFECT", new GridDragSourceEffect(this));
+ setData("DEFAULT_DROP_TARGET_EFFECT", new GridDropTargetEffect(this));
+
+ sizingGC = new GC(this);
+
+ topLeftRenderer.setDisplay(getDisplay());
+ bottomLeftRenderer.setDisplay(getDisplay());
+ rowHeaderRenderer.setDisplay(getDisplay());
+ emptyColumnHeaderRenderer.setDisplay(getDisplay());
+ emptyColumnFooterRenderer.setDisplay(getDisplay());
+ emptyCellRenderer.setDisplay(getDisplay());
+ dropPointRenderer.setDisplay(getDisplay());
+ focusRenderer.setDisplay(getDisplay());
+ emptyRowHeaderRenderer.setDisplay(getDisplay());
+ insertMarkRenderer.setDisplay(getDisplay());
+
+ setForeground(getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+ setLineColor(getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
+
+ if ((style & SWT.MULTI) != 0) {
+ selectionType = SWT.MULTI;
+ }
+
+ if (getVerticalBar() != null) {
+ getVerticalBar().setVisible(false);
+ vScroll = new ScrollBarProxyAdapter(getVerticalBar());
+ }
+ else {
+ vScroll = new NullScrollBarProxy();
+ }
+
+ if (getHorizontalBar() != null) {
+ getHorizontalBar().setVisible(false);
+ hScroll = new ScrollBarProxyAdapter(getHorizontalBar());
+ }
+ else {
+ hScroll = new NullScrollBarProxy();
+ }
+
+ scrollValuesObsolete = true;
+
+ initListeners();
+ initAccessible();
+
+ itemHeight = sizingGC.getFontMetrics().getHeight() + 2;
+
+ RGB sel = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION).getRGB();
+ RGB white = getDisplay().getSystemColor(SWT.COLOR_WHITE).getRGB();
+
+ RGB cellSel = blend(sel, white, 50);
+
+ cellHeaderSelectionBackground = new Color(getDisplay(), cellSel);
+
+ setDragDetect(false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Color getBackground() {
+ checkWidget();
+ if (backgroundColor == null)
+ return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+ return backgroundColor;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBackground(Color color) {
+ checkWidget();
+ backgroundColor = color;
+ dataVisualizer.setDefaultBackground(color);
+ redraw();
+ }
+
+ /**
+ * Returns the background color of column and row headers when a cell in
+ * the row or header is selected.
+ *
+ * @return cell header selection background color
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public Color getCellHeaderSelectionBackground() {
+ checkWidget();
+ return cellHeaderSelectionBackground;
+ }
+
+ /**
+ * Sets the background color of column and row headers displayed when a cell in
+ * the row or header is selected.
+ *
+ * @param cellSelectionBackground color to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setCellHeaderSelectionBackground(Color cellSelectionBackground) {
+ checkWidget();
+ this.cellHeaderSelectionBackground = cellSelectionBackground;
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the receiver's selection changes, by sending it one of the messages
+ * defined in the {@code SelectionListener} interface.
+ * <p>
+ * Cell selection events may have <code>Event.detail = SWT.DRAG</code> when the
+ * user is drag selecting multiple cells. A follow up selection event will be generated
+ * when the drag is complete.
+ *
+ * @param listener the listener which should be notified
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ addListener(SWT.Selection, new TypedListener(listener));
+ addListener(SWT.DefaultSelection, new TypedListener(listener));
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified
+ * when the receiver's items changes, by sending it one of the messages
+ * defined in the {@code TreeListener} interface.
+ *
+ * @param listener the listener which should be notified
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see TreeListener
+ * @see #removeTreeListener
+ * @see org.eclipse.swt.events.TreeEvent
+ */
+ public void addTreeListener(TreeListener listener) {
+ checkWidget();
+ if (listener == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ addListener(SWT.Expand, new TypedListener(listener));
+ addListener(SWT.Collapse, new TypedListener(listener));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ checkWidget();
+
+ Point prefSize = null;
+ if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+ prefSize = getTableSize();
+ prefSize.x += 2 * getBorderWidth();
+ prefSize.y += 2 * getBorderWidth();
+ }
+
+ int x = 0;
+ int y = 0;
+
+ if (wHint == SWT.DEFAULT) {
+ x += prefSize.x;
+ if (getVerticalBar() != null) {
+ x += getVerticalBar().getSize().x;
+ }
+ }
+ else {
+ x = wHint;
+ }
+
+ if (hHint == SWT.DEFAULT) {
+ y += prefSize.y;
+ if (getHorizontalBar() != null) {
+ y += getHorizontalBar().getSize().y;
+ }
+ }
+ else {
+ y = hHint;
+ }
+
+ return new Point(x, y);
+ }
+
+ /**
+ * Deselects the item at the given zero-relative index in the receiver. If
+ * the item at the index was already deselected, it remains deselected.
+ * Indices that are out of range are ignored.
+ * <p>
+ * If cell selection is enabled, all cells in the specified item are deselected.
+ *
+ * @param index the index of the item to deselect
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void deselect(int index) {
+ checkWidget();
+
+ if (index < 0 || index > items.size() - 1) {
+ return;
+ }
+
+ GridItem item = (GridItem) items.get(index);
+
+ if (!cellSelectionEnabled) {
+ if (selectedItems.contains(item)) {
+ selectedItems.remove(item);
+ }
+ }
+ else {
+ deselectCells(getCells(item));
+ }
+ redraw();
+ }
+
+ /**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver is selected,
+ * it is deselected. If the item at the index was not selected, it remains
+ * deselected. The range of the indices is inclusive. Indices that are out
+ * of range are ignored.
+ * <p>
+ * If cell selection is enabled, all cells in the given range are deselected.
+ *
+ * @param start the start index of the items to deselect
+ * @param end the end index of the items to deselect
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void deselect(int start, int end) {
+ checkWidget();
+
+ for (int i = start; i <= end; i++) {
+ if (i < 0) {
+ continue;
+ }
+ if (i > items.size() - 1) {
+ break;
+ }
+
+ GridItem item = (GridItem) items.get(i);
+
+ if (!cellSelectionEnabled) {
+ if (selectedItems.contains(item)) {
+ selectedItems.remove(item);
+ }
+ }
+ else {
+ deselectCells(getCells(item));
+ }
+ }
+ redraw();
+ }
+
+ /**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver is selected,
+ * it is deselected. If the item at the index was not selected, it remains
+ * deselected. Indices that are out of range and duplicate indices are
+ * ignored.
+ * <p>
+ * If cell selection is enabled, all cells in the given items are deselected.
+ *
+ * @param indices the array of indices for the items to deselect
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the set of indices is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void deselect(int[] indices) {
+ checkWidget();
+ if (indices == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ for (int i = 0; i < indices.length; i++) {
+ int j = indices[i];
+
+ if (j >= 0 && j < items.size()) {
+ GridItem item = (GridItem) items.get(j);
+
+ if (!cellSelectionEnabled) {
+ if (selectedItems.contains(item)) {
+ selectedItems.remove(item);
+ }
+ }
+ else {
+ deselectCells(getCells(item));
+ }
+ }
+ }
+ redraw();
+ }
+
+ /**
+ * Deselects all selected items in the receiver. If cell selection is enabled,
+ * all cells are deselected.
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void deselectAll() {
+ checkWidget();
+
+ if (!cellSelectionEnabled) {
+ selectedItems.clear();
+ redraw();
+ }
+ else {
+ deselectAllCells();
+ }
+ }
+
+ /**
+ * Returns the column at the given, zero-relative index in the receiver.
+ * Throws an exception if the index is out of range. If no
+ * {@code GridColumn}s were created by the programmer, this method will
+ * throw {@code ERROR_INVALID_RANGE} despite the fact that a single column
+ * of data may be visible in the table. This occurs when the programmer uses
+ * the table like a list, adding items but never creating a column.
+ *
+ * @param index the index of the column to return
+ * @return the column at the given index
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
+ * of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridColumn getColumn(int index) {
+ checkWidget();
+
+ if (index < 0 || index > getColumnCount() - 1) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+
+ return (GridColumn) columns.get(index);
+ }
+
+ /**
+ * Returns the column at the given point in the receiver or null if no such
+ * column exists. The point is in the coordinate system of the receiver.
+ *
+ * @param point the point used to locate the column
+ * @return the column at the given point
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridColumn getColumn(Point point) {
+ return getColumn(null, point);
+ }
+
+ /**
+ * Returns the column at the given point and a known item in the receiver or null if no such
+ * column exists. The point is in the coordinate system of the receiver.
+ *
+ * @param item a known GridItem
+ * @param point the point used to locate the column
+ * @return the column at the given point
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ private GridColumn getColumn(GridItem item, Point point) {
+ checkWidget();
+ if (point == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ GridColumn overThis = null;
+
+ int x2 = 0;
+
+ if (rowHeaderVisible) {
+ if (point.x <= rowHeaderWidth) {
+ return null;
+ }
+
+ x2 += rowHeaderWidth;
+ }
+
+ x2 -= getHScrollSelectionInPixels();
+
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnIterator.next();
+
+ if (!column.isVisible()) {
+ continue;
+ }
+
+ if (point.x >= x2 && point.x < x2 + column.getWidth()) {
+ overThis = column;
+ break;
+ }
+
+ x2 += column.getWidth();
+ }
+
+ if (overThis == null) {
+ return null;
+ }
+
+ if (hasSpanning) {
+ // special logic for column spanning
+ if (item == null) {
+ item = getItem(point);
+ }
+
+ if (item != null) {
+ int displayColIndex = displayOrderedColumns.indexOf(overThis);
+
+ // track back all previous columns and check their spanning
+ for (int i = 0; i < displayColIndex; i++) {
+ if (!((GridColumn) displayOrderedColumns.get(i)).isVisible()) {
+ continue;
+ }
+
+ int colIndex = indexOf((GridColumn) displayOrderedColumns.get(i));
+ int span = item.getColumnSpan(colIndex);
+
+ if (i + span >= displayColIndex) {
+ overThis = (GridColumn) displayOrderedColumns.get(i);
+ break;
+ }
+ }
+ }
+ }
+
+ return overThis;
+ }
+
+ /**
+ * Returns the number of columns contained in the receiver. If no
+ * {@code GridColumn}s 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 table like a list, adding items
+ * but never creating a column.
+ *
+ * @return the number of columns
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getColumnCount() {
+ checkWidget();
+ return columns.size();
+ }
+
+ /**
+ * Returns an array of zero-relative integers that map the creation order of
+ * the receiver's items to the order in which they are currently being
+ * displayed.
+ * <p>
+ * Specifically, the indices of the returned array represent the current
+ * visual order of the items, and the contents of the array represent the
+ * creation order of the items.
+ * </p>
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its list of items, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the current visual order of the receiver's items
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int[] getColumnOrder() {
+ checkWidget();
+
+ int[] order = new int[columns.size()];
+ int i = 0;
+ for (Iterator colIterator = displayOrderedColumns.iterator(); colIterator.hasNext();) {
+ GridColumn col = (GridColumn) colIterator.next();
+ order[i] = columns.indexOf(col);
+ i++;
+ }
+ return order;
+ }
+
+ /**
+ * Returns the number of column groups contained in the receiver.
+ *
+ * @return the number of column groups
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getColumnGroupCount() {
+ checkWidget();
+ return columnGroups.length;
+ }
+
+ /**
+ * Returns an array of {@code GridColumnGroup}s which are the column groups in the
+ * receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its list of items, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the column groups in the receiver
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridColumnGroup[] getColumnGroups() {
+ checkWidget();
+ GridColumnGroup[] newArray = new GridColumnGroup[columnGroups.length];
+ System.arraycopy(columnGroups, 0, newArray, 0, columnGroups.length);
+ return newArray;
+ }
+
+ /**
+ * Returns the column group at the given, zero-relative index in the receiver.
+ * Throws an exception if the index is out of range.
+ *
+ * @param index the index of the column group to return
+ * @return the column group at the given index
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
+ * of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridColumnGroup getColumnGroup(int index) {
+ checkWidget();
+
+ if (index < 0 || index >= columnGroups.length)
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+
+ return columnGroups[index];
+ }
+
+ /**
+ * Sets the order that the items in the receiver should be displayed in to
+ * the given argument which is described in terms of the zero-relative
+ * ordering of when the items were added.
+ *
+ * @param order the new order to display the items
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS -if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item order is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the order is not the same length as the
+ * number of items, or if an item is listed twice, or if the order splits a
+ * column group</li>
+ * </ul>
+ */
+ public void setColumnOrder(int[] order) {
+ checkWidget();
+
+ if (order == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (order.length != displayOrderedColumns.size()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ boolean[] seen = new boolean[displayOrderedColumns.size()];
+
+ for (int i = 0; i < order.length; i++) {
+ if (order[i] < 0 || order[i] >= displayOrderedColumns.size()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (seen[order[i]]) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ seen[order[i]] = true;
+ }
+
+ if (columnGroups.length != 0) {
+ GridColumnGroup currentGroup = null;
+ int colsInGroup = 0;
+
+ for (int i = 0; i < order.length; i++) {
+ GridColumn col = getColumn(order[i]);
+
+ if (currentGroup != null) {
+ if (col.getColumnGroup() != currentGroup && colsInGroup > 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ else {
+ colsInGroup--;
+ if (colsInGroup <= 0) {
+ currentGroup = null;
+ }
+ }
+ }
+ else if (col.getColumnGroup() != null) {
+ currentGroup = col.getColumnGroup();
+ colsInGroup = currentGroup.getColumns().length - 1;
+ }
+ }
+ }
+
+ GridColumn[] cols = getColumns();
+
+ displayOrderedColumns.clear();
+
+ for (int i = 0; i < order.length; i++) {
+ displayOrderedColumns.add(cols[order[i]]);
+ }
+ }
+
+ /**
+ * Returns an array of {@code GridColumn}s which are the columns in the
+ * receiver. If no {@code GridColumn}s were created by the programmer,
+ * the array is empty, despite the fact that visually, one column of items
+ * may be visible. This occurs when the programmer uses the table like a
+ * list, adding items but never creating a column.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its list of items, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridColumn[] getColumns() {
+ checkWidget();
+ return (GridColumn[]) columns.toArray(new GridColumn[columns.size()]);
+ }
+
+ /**
+ * Returns the empty cell renderer.
+ *
+ * @return Returns the emptyCellRenderer.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridCellRenderer getEmptyCellRenderer() {
+ checkWidget();
+ return emptyCellRenderer;
+ }
+
+ /**
+ * Returns the empty column header renderer.
+ *
+ * @return Returns the emptyColumnHeaderRenderer.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public IRenderer getEmptyColumnHeaderRenderer() {
+ checkWidget();
+ return emptyColumnHeaderRenderer;
+ }
+
+ /**
+ * Returns the empty column footer renderer.
+ *
+ * @return Returns the emptyColumnFooterRenderer.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public IRenderer getEmptyColumnFooterRenderer() {
+ checkWidget();
+ return emptyColumnFooterRenderer;
+ }
+
+ /**
+ * Returns the empty row header renderer.
+ *
+ * @return Returns the emptyRowHeaderRenderer.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public IRenderer getEmptyRowHeaderRenderer() {
+ checkWidget();
+ return emptyRowHeaderRenderer;
+ }
+
+ /**
+ * Returns the externally managed horizontal scrollbar.
+ *
+ * @return the external horizontal scrollbar.
+ * @see #setHorizontalScrollBarProxy(IScrollBarProxy)
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ protected IScrollBarProxy getHorizontalScrollBarProxy() {
+ checkWidget();
+ return hScroll;
+ }
+
+ /**
+ * Returns the externally managed vertical scrollbar.
+ *
+ * @return the external vertical scrollbar.
+ * @see #setlVerticalScrollBarProxy(IScrollBarProxy)
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ protected IScrollBarProxy getVerticalScrollBarProxy() {
+ checkWidget();
+ return vScroll;
+ }
+
+ /**
+ * Gets the focus renderer.
+ *
+ * @return Returns the focusRenderer.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public IRenderer getFocusRenderer() {
+ checkWidget();
+ return focusRenderer;
+ }
+
+ /**
+ * Returns the height of the column headers. If this table has column
+ * groups, the returned value includes the height of group headers.
+ *
+ * @return height of the column header row
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getHeaderHeight() {
+ checkWidget();
+ return headerHeight;
+ }
+
+ /**
+ * Returns the height of the column footers.
+ *
+ * @return height of the column footer row
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getFooterHeight() {
+ checkWidget();
+ return footerHeight;
+ }
+
+ /**
+ * Returns the height of the column group headers.
+ *
+ * @return height of column group headers
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getGroupHeaderHeight() {
+ checkWidget();
+ return groupHeaderHeight;
+ }
+
+ /**
+ * Returns {@code true} if the receiver's header is visible, and
+ * {@code false} otherwise.
+ *
+ * @return the receiver's header's visibility state
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean getHeaderVisible() {
+ checkWidget();
+ return columnHeadersVisible;
+ }
+
+ /**
+ * Returns {@code true} if the receiver's footer is visible, and {@code false} otherwise
+ * @return the receiver's footer's visibility state
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean getFooterVisible() {
+ checkWidget();
+ return columnFootersVisible;
+ }
+
+ /**
+ * Returns the item at the given, zero-relative index in the receiver.
+ * Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the
+ * list minus 1 (inclusive) </li> *
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridItem getItem(int index) {
+ checkWidget();
+
+ if (index < 0 || index >= items.size()) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+
+ return (GridItem) items.get(index);
+ }
+
+ /**
+ * Returns the item at the given point in the receiver or null if no such
+ * item exists. The point is in the coordinate system of the receiver.
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridItem getItem(Point point) {
+ checkWidget();
+
+ if (point == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ if (point.x < 0 || point.x > getClientArea().width)
+ return null;
+
+ Point p = new Point(point.x, point.y);
+
+ int y2 = 0;
+
+ if (columnHeadersVisible) {
+ if (p.y <= headerHeight) {
+ return null;
+ }
+ y2 += headerHeight;
+ }
+
+ GridItem itemToReturn = null;
+
+ int row = getTopIndex();
+ while (row < items.size() && y2 <= getClientArea().height) {
+ GridItem currItem = (GridItem) items.get(row);
+ if (currItem.isVisible()) {
+ int currItemHeight = currItem.getHeight();
+
+ if (p.y >= y2 && p.y < y2 + currItemHeight + 1) {
+ itemToReturn = currItem;
+ break;
+ }
+
+ y2 += currItemHeight + 1;
+ }
+ row++;
+ }
+
+ if (hasSpanning) {
+ if (itemToReturn != null) {
+ int itemIndex = this.getIndexOfItem(itemToReturn);
+
+ GridColumn gridColumn = getColumn(itemToReturn, point);
+ int displayColIndex = displayOrderedColumns.indexOf(gridColumn);
+
+ // track back all previous columns and check their spanning
+ for (int i = 0; i < itemIndex; i++) {
+ GridItem gridItem = this.getItem(i);
+ if (gridItem.isVisible() == false) {
+ continue;
+ }
+ int span = gridItem.getRowSpan(displayColIndex);
+
+ if (i + span >= itemIndex) {
+ itemToReturn = gridItem;
+ break;
+ }
+ }
+ }
+ }
+
+ return itemToReturn;
+ }
+
+ /**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getItemCount() {
+ checkWidget();
+ return getItems().length;
+ }
+
+ /**
+ * Returns the default height of the items
+ * in this <code>Grid</code>. See {@link #setItemHeight(int)}
+ * for details.
+ *
+ * <p>IMPORTANT: The Grid's items need not all have the
+ * height returned by this method, because an
+ * item's height may have been changed by calling
+ * {@link GridItem#setHeight(int)}.
+ *
+ * @return default height of items
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see #setItemHeight(int)
+ */
+ public int getItemHeight() {
+ checkWidget();
+ return itemHeight;
+ }
+
+ /**
+ * Sets the default height for this <code>Grid</code>'s items. When
+ * this method is called, all existing items are resized
+ * to the specified height and items created afterwards will be
+ * initially sized to this height.
+ * <p>
+ * As long as no default height was set by the client through this method,
+ * the preferred height of the first item in this <code>Grid</code> is
+ * used as a default for all items (and is returned by {@link #getItemHeight()}).
+ *
+ * @param height default height in pixels
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the height is < 1</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ *
+ * @see GridItem#getHeight()
+ * @see GridItem#setHeight(int)
+ */
+ public void setItemHeight(int height) {
+ checkWidget();
+ if (height < 1)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ itemHeight = height;
+ userModifiedItemHeight = true;
+ for (int cnt = 0; cnt < items.size(); cnt++)
+ ((GridItem) items.get(cnt)).setHeight(height);
+ hasDifferingHeights = false;
+ setScrollValuesObsolete();
+ redraw();
+ }
+
+ /**
+ * Returns true if the rows are resizable.
+ *
+ * @return the row resizeable state
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see #setRowsResizeable(boolean)
+ */
+ public boolean getRowsResizeable() {
+ checkWidget();
+ return rowsResizeable;
+ }
+
+ /**
+ * Sets the rows resizeable state of this <code>Grid</code>.
+ * The default is 'false'.
+ * <p>
+ * If a row in a <code>Grid</code> is resizeable,
+ * then the user can interactively change its height
+ * by dragging the border of the row header.
+ * <p>
+ * Note that for rows to be resizable the row headers must be visible.
+ *
+ * @param rowsResizeable true if this <code>Grid</code>'s rows should be resizable
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see #setRowHeaderVisible(boolean)
+ */
+ public void setRowsResizeable(boolean rowsResizeable) {
+ checkWidget();
+ this.rowsResizeable = rowsResizeable;
+ }
+
+ /**
+ * Returns a (possibly empty) array of {@code GridItem}s which are the
+ * items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its list of items, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridItem[] getItems() {
+ checkWidget();
+ return (GridItem[]) items.toArray(new GridItem[items.size()]);
+ }
+
+ /**
+ *
+ * @param item
+ * @return t
+ */
+ public int getIndexOfItem(GridItem item) {
+ checkWidget();
+
+ return items.indexOf(item);
+ }
+
+ /**
+ * Returns the line color.
+ *
+ * @return Returns the lineColor.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public Color getLineColor() {
+ checkWidget();
+ return lineColor;
+ }
+
+ /**
+ * Returns true if the lines are visible.
+ *
+ * @return Returns the linesVisible.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean getLinesVisible() {
+ checkWidget();
+ return linesVisible;
+ }
/**
* Returns true if the tree lines are visible.
@@ -2119,1493 +2003,1404 @@ public class Grid extends Canvas
return treeLinesVisible;
}
- /**
- * Returns the next visible item in the table.
- *
- * @param item item
- * @return next visible item or null
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridItem getNextVisibleItem(GridItem item)
- {
- checkWidget();
-
- int index = items.indexOf(item);
- if (items.size() == index + 1)
- {
- return null;
- }
-
- GridItem nextItem = (GridItem)items.get(index + 1);
-
- while (!nextItem.isVisible())
- {
- index++;
- if (items.size() == index + 1)
- {
- return null;
- }
-
- nextItem = (GridItem)items.get(index + 1);
- }
-
- return nextItem;
- }
-
- /**
- * Returns the previous visible item in the table. Passing null for the item
- * will return the last visible item in the table.
- *
- * @param item item or null
- * @return previous visible item or if item==null last visible item
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridItem getPreviousVisibleItem(GridItem item)
- {
- checkWidget();
-
- int index = 0;
- if (item == null)
- {
- index = items.size();
- }
- else
- {
- index = items.indexOf(item);
- if (index == 0)
- {
- return null;
- }
- }
-
- GridItem prevItem = (GridItem)items.get(index - 1);
-
- while (!prevItem.isVisible())
- {
- index--;
- if (index == 0)
- {
- return null;
- }
-
- prevItem = (GridItem)items.get(index - 1);
- }
-
- return prevItem;
- }
-
- /**
- * Returns the previous visible column in the table.
- *
- * @param column column
- * @return previous visible column or null
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridColumn getPreviousVisibleColumn(GridColumn column)
- {
- checkWidget();
-
- int index = displayOrderedColumns.indexOf(column);
-
- if (index == 0)
- return null;
-
- index --;
-
- GridColumn previous = (GridColumn)displayOrderedColumns.get(index);
-
- while (!previous.isVisible())
- {
- if (index == 0)
- return null;
-
- index --;
- previous = (GridColumn)displayOrderedColumns.get(index);
- }
-
- return previous;
- }
-
- /**
- * Returns the next visible column in the table.
- *
- * @param column column
- * @return next visible column or null
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridColumn getNextVisibleColumn(GridColumn column)
- {
- checkWidget();
-
- int index = displayOrderedColumns.indexOf(column);
-
- if (index == displayOrderedColumns.size() - 1)
- return null;
-
- index ++;
-
- GridColumn next = (GridColumn)displayOrderedColumns.get(index);
-
- while (!next.isVisible())
- {
- if (index == displayOrderedColumns.size() - 1)
- return null;
-
- index ++;
- next = (GridColumn)displayOrderedColumns.get(index);
- }
-
- return next;
- }
-
- /**
- * Returns the number of root items contained in the receiver.
- *
- * @return the number of items
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getRootItemCount()
- {
- checkWidget();
- return rootItems.size();
- }
-
- /**
- * Returns a (possibly empty) array of {@code GridItem}s which are
- * the root items in the receiver.
- * <p>
- * Note: This is not the actual structure used by the receiver to maintain
- * its list of items, so modifying the array will not affect the receiver.
- * </p>
- *
- * @return the root items in the receiver
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridItem[] getRootItems()
- {
- checkWidget();
-
- return (GridItem[])rootItems.toArray(new GridItem[rootItems.size()]);
- }
-
- /**
- * TODO: asl;fj
- * @param index
- * @return asdf
- */
- public GridItem getRootItem(int index)
- {
- checkWidget();
-
- if (index < 0 || index >= rootItems.size())
- {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
-
- return (GridItem)rootItems.get(index);
- }
-
- /**
- * Gets the row header renderer.
- *
- * @return Returns the rowHeaderRenderer.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public IRenderer getRowHeaderRenderer()
- {
- checkWidget();
- return rowHeaderRenderer;
- }
-
- /**
- * Returns a array of {@code GridItem}s that are currently selected in the
- * receiver. The order of the items is unspecified. An empty array indicates
- * that no items are selected.
- * <p>
- * Note: This is not the actual structure used by the receiver to maintain
- * its selection, so modifying the array will not affect the receiver.
- * <p>
- * If cell selection is enabled, any items which contain at least one selected
- * cell are returned.
- *
- * @return an array representing the selection
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridItem[] getSelection()
- {
- checkWidget();
-
- if (!cellSelectionEnabled)
- {
- return (GridItem[])selectedItems.toArray(new GridItem[selectedItems.size()]);
- }
- else
- {
- Vector items = new Vector();
- int itemCount = getItemCount();
-
- for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
- {
- Point cell = (Point)iter.next();
- if (cell.y >= 0 && cell.y < itemCount) {
- GridItem item = getItem(cell.y);
- if (!items.contains(item))
- items.add(item);
- }
- }
- return (GridItem[])items.toArray(new GridItem[]{});
- }
- }
-
- /**
- * Returns the number of selected items contained in the receiver. If cell selection
- * is enabled, the number of items with at least one selected cell are returned.
- *
- * @return the number of selected items
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getSelectionCount()
- {
- checkWidget();
-
- if (!cellSelectionEnabled)
- {
- return selectedItems.size();
- }
- else
- {
- Vector items = new Vector();
- for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
- {
- Point cell = (Point)iter.next();
- GridItem item = getItem(cell.y);
- if (!items.contains(item))
- items.add(item);
- }
- return items.size();
- }
- }
-
- /**
- * Returns the number of selected cells contained in the receiver.
- *
- * @return the number of selected cells
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getCellSelectionCount()
- {
- checkWidget();
- return selectedCells.size();
- }
-
- /**
- * Returns the zero-relative index of the item which is currently selected
- * in the receiver, or -1 if no item is selected. If cell selection is enabled,
- * returns the index of first item that contains at least one selected cell.
- *
- * @return the index of the selected item
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getSelectionIndex()
- {
- checkWidget();
-
- if (!cellSelectionEnabled)
- {
- if (selectedItems.size() == 0)
- {
- return -1;
- }
-
- return items.indexOf(selectedItems.get(0));
- }
- else
- {
- if (selectedCells.size() == 0)
- return -1;
-
- return ((Point)selectedCells.get(0)).y;
- }
- }
-
- /**
- * Returns the zero-relative indices of the items which are currently
- * selected in the receiver. The order of the indices is unspecified. The
- * array is empty if no items are selected.
- * <p>
- * Note: This is not the actual structure used by the receiver to maintain
- * its selection, so modifying the array will not affect the receiver.
- * <p>
- * If cell selection is enabled, returns the indices of any items which
- * contain at least one selected cell.
- *
- * @return the array of indices of the selected items
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int[] getSelectionIndices()
- {
- checkWidget();
-
- if (!cellSelectionEnabled)
- {
- int[] indices = new int[selectedItems.size()];
- int i = 0;
- for (Iterator itemIterator = selectedItems.iterator(); itemIterator.hasNext(); )
- {
- GridItem item = (GridItem) itemIterator.next();
- indices[i] = items.indexOf(item);
- i++;
- }
- return indices;
- }
- else
- {
- Vector selectedRows = new Vector();
- for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
- {
- Point cell = (Point)iter.next();
- GridItem item = getItem(cell.y);
- if (!selectedRows.contains(item))
- selectedRows.add(item);
- }
- int[] indices = new int[selectedRows.size()];
- int i = 0;
- for (Iterator itemIterator = selectedRows.iterator(); itemIterator.hasNext(); )
- {
- GridItem item = (GridItem) itemIterator.next();
- indices[i] = items.indexOf(item);
- i++;
- }
- return indices;
- }
- }
-
- /**
- * Returns the zero-relative index of the item which is currently at the top
- * of the receiver. This index can change when items are scrolled or new
- * items are added or removed.
- *
- * @return the index of the top item
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int getTopIndex()
- {
- checkWidget();
-
- if (topIndex != -1)
- return topIndex;
-
- if (!vScroll.getVisible())
- {
- topIndex = 0;
- }
- else
- {
- // figure out first visible row and last visible row
- int firstVisibleIndex = vScroll.getSelection();
-
- if (isTree)
- {
- Iterator itemsIter = items.iterator();
- int row = firstVisibleIndex + 1;
-
- while (row > 0 && itemsIter.hasNext())
- {
- GridItem item = (GridItem)itemsIter.next();
-
- if (item.isVisible())
- {
- row--;
- if (row == 0)
- {
- firstVisibleIndex = items.indexOf(item);
- }
- }
- }
- }
-
- topIndex = firstVisibleIndex;
-
- /*
- * MOPR here lies more potential for increasing performance
- * for the case (isTree || hasDifferingHeights)
- * the topIndex could be derived from the previous value
- * depending on a delta of the vScroll.getSelection()
- * instead of being calculated completely anew
- */
- }
-
- return topIndex;
- }
- /**
- * Returns the zero-relative index of the item which is currently at the bottom
- * of the receiver. This index can change when items are scrolled, expanded
- * or collapsed or new items are added or removed.
- * <p>
- * Note that the item with this index is often only partly visible; maybe only
- * a single line of pixels is visible. Use {@link #isShown(GridItem)} to find
- * out.
- * <p>
- * In extreme cases, getBottomIndex() may return the same value as
- * {@link #getTopIndex()}.
- *
- * @return the index of the bottom item
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- int getBottomIndex() {
- checkWidget();
-
- if (bottomIndex != -1)
- return bottomIndex;
-
- if (items.size() == 0)
- {
- bottomIndex = 0;
- }
- else if (getVisibleGridHeight()<1)
- {
- bottomIndex = getTopIndex();
- }
- else
- {
- RowRange range = getRowRange(getTopIndex(),getVisibleGridHeight(),false,false);
-
- bottomIndex = range.endIndex;
- bottomIndexShownCompletely = range.height <= getVisibleGridHeight();
- }
-
- return bottomIndex;
- }
- /**
- * Returns a {@link RowRange} ranging from
- * the grid item at startIndex to that at endIndex.
- * <p>
- * This is primarily used to measure the height
- * in pixel of such a range and to count the number
- * of visible grid items within the range.
- *
- * @param startIndex index of the first item in the range or -1 to the first visible item in this grid
- * @param endIndex index of the last item in the range or -1 to use the last visible item in this grid
- * @return
- */
- private RowRange getRowRange(int startIndex, int endIndex) {
-
- // parameter preparation
- if (startIndex == -1)
- {
- // search frist visible item
- do startIndex++; while (startIndex < items.size() && !((GridItem)items.get(startIndex)).isVisible());
- if (startIndex == items.size()) return null;
- }
- if (endIndex == -1)
- {
- // search last visible item
- endIndex = items.size();
- do endIndex--; while (endIndex >= 0 && !((GridItem)items.get(endIndex)).isVisible());
- if (endIndex == -1) return null;
- }
-
- // fail fast
- if (startIndex<0 || endIndex<0 || startIndex>=items.size() || endIndex>=items.size()
- || endIndex < startIndex
- || ((GridItem)items.get(startIndex)).isVisible()==false
- || ((GridItem)items.get(endIndex)).isVisible()==false)
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- RowRange range = new RowRange();
- range.startIndex = startIndex;
- range.endIndex = endIndex;
-
- if(isTree || hasDifferingHeights)
- {
- for (int idx=startIndex ; idx<=endIndex ; idx++ )
- {
- GridItem currItem = (GridItem)items.get(idx);
-
- if(currItem.isVisible())
- {
- if (range.rows>0)
- range.height++; // height of horizontal row separator
- range.height += currItem.getHeight();
- range.rows++;
- }
- }
- }
- else
- {
- range.rows = range.endIndex - range.startIndex + 1;
- range.height = ( getItemHeight() + 1 ) * range.rows - 1;
- }
-
- return range;
- }
- /**
- * This method can be used to build a range of grid rows
- * that is allowed to span a certain height in pixels.
- * <p>
- * It returns a {@link RowRange} that contains information
- * about the range, especially the index of the last
- * element in the range (or if inverse == true, then the
- * index of the first element).
- * <p>
- * Note: Even if 'forceEndCompletelyInside' is set to
- * true, the last item will not lie completely within
- * the availableHeight, if (height of item at startIndex < availableHeight).
- *
- * @param startIndex index of the first (if inverse==false) or
- * last (if inverse==true) item in the range
- * @param availableHeight height in pixels
- * @param forceEndCompletelyInside if true, the last item in the range will lie completely
- * within the availableHeight, otherwise it may lie partly outside this range
- * @param inverse if true, then the first item in the range will be searched, not the last
- * @return range of grid rows
- * @see RowRange
- */
- private RowRange getRowRange(int startIndex, int availableHeight,
- boolean forceEndCompletelyInside, boolean inverse) {
- // parameter preparation
- if (startIndex == -1)
- {
- if(!inverse)
- {
- // search frist visible item
- do startIndex++; while (startIndex < items.size() && !((GridItem)items.get(startIndex)).isVisible());
- if (startIndex == items.size()) return null;
- }
- else
- {
- // search last visible item
- startIndex = items.size();
- do startIndex--; while (startIndex >= 0 && !((GridItem)items.get(startIndex)).isVisible());
- if (startIndex == -1) return null;
- }
- }
-
- // fail fast
- if (startIndex < 0 || startIndex >= items.size()
- || ((GridItem)items.get(startIndex)).isVisible() == false)
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
-
- RowRange range = new RowRange();
-
- if (availableHeight <= 0)
- {
- // special case: empty range
- range.startIndex = startIndex;
- range.endIndex = startIndex;
- range.rows = 0;
- range.height = 0;
- return range;
- }
-
- if (isTree || hasDifferingHeights)
- {
- int otherIndex = startIndex; // tentative end index
- int consumedItems = 0;
- int consumedHeight = 0;
-
- // consume height for startEnd (note: no separator pixel added here)
- consumedItems++;
- consumedHeight += ((GridItem)items.get(otherIndex)).getHeight();
-
- // note: we use "+2" in next line, because we only try to add another row if there
- // is room for the separator line + at least one pixel row for the additional item
- while (consumedHeight+2 <= availableHeight)
- {
- // STEP 1:
- // try to find a visible item we can add
-
- int nextIndex = otherIndex;
- GridItem nextItem;
-
- do
- {
- if (!inverse)
- nextIndex++;
- else
- nextIndex--;
-
- if (nextIndex >= 0 && nextIndex < items.size())
- nextItem = (GridItem)items.get(nextIndex);
- else
- nextItem = null;
- }
- while (nextItem != null && !nextItem.isVisible());
-
-
- if (nextItem == null)
- {
- // no visible item found
- break;
- }
-
- if (forceEndCompletelyInside)
- {
- // must lie completely within the allowed height
- if(!(consumedHeight + 1 + nextItem.getHeight() <= availableHeight))
- break;
- }
-
- // we found one !!
-
- // STEP 2:
- // Consume height for this item
-
- consumedItems++;
- consumedHeight += 1; // height of separator line
- consumedHeight += nextItem.getHeight();
-
- // STEP 3:
- // make this item it the current guess for the other end
- otherIndex = nextIndex;
- }
-
- range.startIndex = !inverse ? startIndex : otherIndex;
- range.endIndex = !inverse ? otherIndex : startIndex;
- range.rows = consumedItems;
- range.height = consumedHeight;
- }
- else
- {
- int availableRows = ( availableHeight + 1 ) / ( getItemHeight() + 1 );
-
- if ((( getItemHeight() + 1 ) * range.rows - 1) + 1 < availableHeight)
- {
- // not all available space used yet
- // - so add another row if it need not be completely within availableHeight
- if (!forceEndCompletelyInside)
- availableRows++;
- }
-
- int otherIndex = startIndex + ((availableRows - 1) * (!inverse ? 1 : -1));
- if (otherIndex<0) otherIndex = 0;
- if (otherIndex>=items.size()) otherIndex = items.size() - 1 ;
-
- range.startIndex = !inverse ? startIndex : otherIndex;
- range.endIndex = !inverse ? otherIndex : startIndex;
- range.rows = range.endIndex - range.startIndex + 1;
- range.height = ( getItemHeight() + 1 ) * range.rows - 1;
- }
-
- return range;
- }
- /**
- * Returns the height of the plain grid in pixels.
- * <p>
- * This includes all rows for visible items (i.e. items that return true
- * on {@link GridItem#isVisible()} ; not only those currently visible on
- * screen) and the 1 pixel separator between rows.
- * <p>
- * This does <em>not</em> include the height of the column headers.
- *
- * @return height of plain grid
- */
- int getGridHeight() {
- RowRange range = getRowRange(-1,-1);
- return range != null ? range.height : 0;
- /*
- * MOPR currently this method is only used in #getTableSize() ;
- * if it will be used for more important things in the future
- * (e.g. the max value for vScroll.setValues() when doing pixel-by-pixel
- * vertical scrolling) then this value should at least be cached or
- * even updated incrementally when grid items are added/removed or
- * expaned/collapsed (similar as #currentVisibleItems).
- * (this is only necessary in the case (isTree || hasDifferingHeights))
- */
- }
-
- /**
- * Returns the height of the on-screen area that is available
- * for showing the grid's rows, i.e. the client area of the
- * scrollable minus the height of the column headers (if shown).
- *
- * @return height of visible grid in pixels
- */
- int getVisibleGridHeight() {
- return getClientArea().height - (columnHeadersVisible ? headerHeight : 0) - (columnFootersVisible ? footerHeight : 0);
- }
-
- /**
- * Returns the height of the screen area that is available for showing the grid columns
- * @return
- */
- int getVisibleGridWidth() {
- return getClientArea().width - ( rowHeaderVisible ? rowHeaderWidth : 0 );
- }
-
- /**
- * Gets the top left renderer.
- *
- * @return Returns the topLeftRenderer.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public IRenderer getTopLeftRenderer()
- {
- checkWidget();
- return topLeftRenderer;
- }
-
- /**
- * Gets the bottom left renderer.
- *
- * @return Returns the bottomLeftRenderer.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public IRenderer getBottomLeftRenderer()
- {
- checkWidget();
- return bottomLeftRenderer;
- }
-
- /**
- * Searches the receiver's list starting at the first column (index 0) until
- * a column is found that is equal to the argument, and returns the index of
- * that column. If no column is found, returns -1.
- *
- * @param column the search column
- * @return the index of the column
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the column is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int indexOf(GridColumn column)
- {
- checkWidget();
-
- if (column == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- if (column.getParent() != this) return -1;
-
- return columns.indexOf(column);
- }
-
- /**
- * Searches the receiver's list starting at the first item (index 0) until
- * an item is found that is equal to the argument, and returns the index of
- * that item. If no item is found, returns -1.
- *
- * @param item the search item
- * @return the index of the item
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public int indexOf(GridItem item)
- {
- checkWidget();
-
- if (item == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- if (item.getParent() != this) return -1;
-
- return items.indexOf(item);
- }
-
- /**
- * Returns {@code true} if the receiver's row header is visible, and
- * {@code false} otherwise.
- * <p>
- *
- * @return the receiver's row header's visibility state
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean isRowHeaderVisible()
- {
- checkWidget();
- return rowHeaderVisible;
- }
-
- /**
- * Returns {@code true} if the item is selected, and {@code false}
- * otherwise. Indices out of range are ignored. If cell selection is
- * enabled, returns true if the item at the given index contains at
- * least one selected cell.
- *
- * @param index the index of the item
- * @return the visibility state of the item at the index
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean isSelected(int index)
- {
- checkWidget();
-
- if (index < 0 || index >= items.size()) return false;
-
- if (!cellSelectionEnabled)
- {
- return isSelected((GridItem)items.get(index));
- }
- else
- {
- for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
- {
- Point cell = (Point)iter.next();
- if (cell.y == index) return true;
- }
- return false;
- }
- }
-
- /**
- * Returns true if the given item is selected. If cell selection is enabled,
- * returns true if the given item contains at least one selected cell.
- *
- * @param item item
- * @return true if the item is selected.
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean isSelected(GridItem item)
- {
- checkWidget();
- if (!cellSelectionEnabled)
- {
- return selectedItems.contains(item);
- }
- else
- {
- int index = indexOf(item);
- if (index == -1) return false;
- for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
- {
- Point cell = (Point)iter.next();
- if (cell.y == index) return true;
- }
- return false;
- }
- }
-
- /**
- * Returns true if the given cell is selected.
- *
- * @param cell cell
- * @return true if the cell is selected.
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the cell is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean isCellSelected(Point cell)
- {
- checkWidget();
-
- if (cell == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- return selectedCells.contains(cell);
- }
-
-
-
- /**
- * Removes the item from the receiver at the given zero-relative index.
- *
- * @param index the index for the item
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
- * of elements in the list minus 1 (inclusive)</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void remove(int index)
- {
- checkWidget();
- if (index < 0 || index > items.size() - 1)
- {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- GridItem item = (GridItem)items.get(index);
- item.dispose();
- redraw();
- }
-
- /**
- * 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
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0
- * and the number of elements in the list minus 1 (inclusive)</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void remove(int start, int end)
- {
- checkWidget();
-
- for (int i = end; i >= start; i--)
- {
- if (i < 0 || i > items.size() - 1)
- {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- GridItem item = (GridItem)items.get(i);
- item.dispose();
- }
- redraw();
- }
-
- /**
- * Removes the items from the receiver's list at the given zero-relative
- * indices.
- *
- * @param indices the array of indices of the items
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
- * of elements in the list minus 1 (inclusive)</li>
- * <li>ERROR_NULL_ARGUMENT - if the indices array is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void remove(int[] indices)
- {
- checkWidget();
-
- if (indices == null)
- {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
-
- GridItem[] removeThese = new GridItem[indices.length];
- for (int i = 0; i < indices.length; i++)
- {
- int j = indices[i];
- if (j < items.size() && j >= 0)
- {
- removeThese[i] = (GridItem)items.get(j);
- }
- else
- {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
-
- }
- for (int i = 0; i < removeThese.length; i++)
- {
- GridItem item = removeThese[i];
- item.dispose();
- }
- redraw();
- }
-
- /**
- * Removes all of the items from the receiver.
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * Call {@link Grid} disposeAllItems and clearItems.. Is faster
- */
- @Deprecated
- public void removeAll()
- {
- checkWidget();
-
- while (items.size() > 0)
- {
- ((GridItem)items.get(0)).dispose();
- }
- deselectAll();
- redraw();
- }
-
- /**
- * All items needs to call the disposeOnly method
- */
- public void disposeAllItems()
- {
- checkWidget();
-
- final GridItem[] items = getItems();
- for (final GridItem gridItem : items)
- {
- gridItem.disposeOnly();
- }
- clearItems();
- }
-
- /**
- * Removes the listener from the collection of listeners who will be
- * notified when the receiver's selection changes.
- *
- * @param listener the listener which should no longer be notified
- * @see SelectionListener
- * @see #addSelectionListener(SelectionListener)
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void removeSelectionListener(SelectionListener listener)
- {
- checkWidget();
- removeListener(SWT.Selection, listener);
- removeListener(SWT.DefaultSelection, listener);
- }
-
- /**
- * Removes the listener from the collection of listeners who will be
- * notified when the receiver's items changes.
- *
- * @param listener the listener which should no longer be notified
- * @see TreeListener
- * @see #addTreeListener(TreeListener)
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void removeTreeListener(TreeListener listener)
- {
- checkWidget();
- removeListener(SWT.Expand, listener);
- removeListener(SWT.Collapse, listener);
- }
-
- /**
- * Selects the item at the given zero-relative index in the receiver. If the
- * item at the index was already selected, it remains selected. Indices that
- * are out of range are ignored.
- * <p>
- * If cell selection is enabled, selects all cells at the given index.
- *
- * @param index the index of the item to select
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void select(int index)
- {
- checkWidget();
-
- if (!selectionEnabled) return;
-
- if (index < 0 || index >= items.size()) return;
-
- GridItem item = (GridItem)items.get(index);
-
- if (!cellSelectionEnabled)
- {
- if (selectionType == SWT.MULTI && selectedItems.contains(item)) return;
-
- if (selectionType == SWT.SINGLE) selectedItems.clear();
-
- selectedItems.add(item);
- }
- else
- {
- selectCells(getCells(item));
- }
-
- redraw();
- }
-
- /**
- * Selects the items in the range specified by the given zero-relative
- * indices in the receiver. The range of indices is inclusive. The current
- * selection is not cleared before the new items are selected.
- * <p>
- * If an item in the given range is not selected, it is selected. If an item
- * in the given range was already selected, it remains selected. Indices
- * that are out of range are ignored and no items will be selected if start
- * is greater than end. If the receiver is single-select and there is more
- * than one item in the given range, then all indices are ignored.
- * <p>
- * If cell selection is enabled, all cells within the given range are selected.
- *
- * @param start the start of the range
- * @param end the end of the range
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see Grid#setSelection(int,int)
- */
- public void select(int start, int end)
- {
- checkWidget();
-
- if (!selectionEnabled) return;
-
- if (selectionType == SWT.SINGLE && start != end) return;
-
- if (!cellSelectionEnabled)
- {
- if (selectionType == SWT.SINGLE) selectedItems.clear();
- }
-
- for (int i = start; i <= end; i++)
- {
- if (i < 0)
- {
- continue;
- }
- if (i > items.size() - 1)
- {
- break;
- }
-
- GridItem item = (GridItem)items.get(i);
-
- if (!cellSelectionEnabled)
- {
- if (!selectedItems.contains(item))
- selectedItems.add(item);
- }
- else
- {
- selectCells(getCells(item));
- }
- }
-
- redraw();
- }
-
- /**
- * Selects the items at the given zero-relative indices in the receiver. The
- * current selection is not cleared before the new items are selected.
- * <p>
- * 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.
- * <p>
- * If cell selection is enabled, all cells within the given indices are
- * selected.
- *
- * @param indices the array of indices for the items to select
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see Grid#setSelection(int[])
- */
- public void select(int[] indices)
- {
- checkWidget();
-
- if (indices == null)
- {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
-
- if (!selectionEnabled) return;
-
- if (selectionType == SWT.SINGLE && indices.length > 1) return;
-
- if (!cellSelectionEnabled)
- if (selectionType == SWT.SINGLE) selectedItems.clear();
-
- for (int i = 0; i < indices.length; i++)
- {
- int j = indices[i];
-
- if (j >= 0 && j < items.size())
- {
- GridItem item = (GridItem)items.get(j);
-
- if (!cellSelectionEnabled)
- {
- if (!selectedItems.contains(item))
- selectedItems.add(item);
- }
- else
- {
- selectCells(getCells(item));
- }
- }
- }
- redraw();
- }
-
- /**
- * Selects all of the items in the receiver.
- * <p>
- * If the receiver is single-select, do nothing. If cell selection is enabled,
- * all cells are selected.
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void selectAll()
- {
- checkWidget();
-
- if (!selectionEnabled) return;
-
- if (selectionType == SWT.SINGLE) return;
-
- if (cellSelectionEnabled)
- {
- selectAllCells();
- return;
- }
-
- selectedItems.clear();
- selectedItems.addAll(items);
- redraw();
- }
-
- /**
- * Sets the empty cell renderer.
- *
- * @param emptyCellRenderer The emptyCellRenderer to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setEmptyCellRenderer(GridCellRenderer emptyCellRenderer)
- {
- checkWidget();
- emptyCellRenderer.setDisplay(getDisplay());
- this.emptyCellRenderer = emptyCellRenderer;
- }
-
- /**
- * Sets the empty column header renderer.
- *
- * @param emptyColumnHeaderRenderer The emptyColumnHeaderRenderer to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setEmptyColumnHeaderRenderer(IRenderer emptyColumnHeaderRenderer)
- {
- checkWidget();
- emptyColumnHeaderRenderer.setDisplay(getDisplay());
- this.emptyColumnHeaderRenderer = emptyColumnHeaderRenderer;
- }
-
- /**
- * Sets the empty column footer renderer.
- *
- * @param emptyColumnFooterRenderer The emptyColumnFooterRenderer to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setEmptyColumnFooterRenderer(IRenderer emptyColumnFooterRenderer)
- {
- checkWidget();
- emptyColumnFooterRenderer.setDisplay(getDisplay());
- this.emptyColumnFooterRenderer = emptyColumnFooterRenderer;
- }
-
- /**
- * Sets the empty row header renderer.
- *
- * @param emptyRowHeaderRenderer The emptyRowHeaderRenderer to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setEmptyRowHeaderRenderer(IRenderer emptyRowHeaderRenderer)
- {
- checkWidget();
- emptyRowHeaderRenderer.setDisplay(getDisplay());
- this.emptyRowHeaderRenderer = emptyRowHeaderRenderer;
- }
-
- /**
- * Sets the external horizontal scrollbar. Allows the scrolling to be
- * managed externally from the table. This functionality is only intended
- * when SWT.H_SCROLL is not given.
- * <p>
- * Using this feature, a ScrollBar could be instantiated outside the table,
- * wrapped in IScrollBar and thus be 'connected' to the table.
- *
- * @param scroll The horizontal scrollbar to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- protected void setHorizontalScrollBarProxy(IScrollBarProxy scroll)
- {
- checkWidget();
- if (getHorizontalBar() != null)
- {
- return;
- }
- hScroll = scroll;
-
- hScroll.addSelectionListener(new SelectionListener() {
+ /**
+ * Returns the next visible item in the table.
+ *
+ * @param item item
+ * @return next visible item or null
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridItem getNextVisibleItem(GridItem item) {
+ checkWidget();
+
+ int index = items.indexOf(item);
+ if (items.size() == index + 1) {
+ return null;
+ }
+
+ GridItem nextItem = (GridItem) items.get(index + 1);
+
+ while (!nextItem.isVisible()) {
+ index++;
+ if (items.size() == index + 1) {
+ return null;
+ }
+
+ nextItem = (GridItem) items.get(index + 1);
+ }
+
+ return nextItem;
+ }
+
+ /**
+ * Returns the previous visible item in the table. Passing null for the item
+ * will return the last visible item in the table.
+ *
+ * @param item item or null
+ * @return previous visible item or if item==null last visible item
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridItem getPreviousVisibleItem(GridItem item) {
+ checkWidget();
+
+ int index = 0;
+ if (item == null) {
+ index = items.size();
+ }
+ else {
+ index = items.indexOf(item);
+ if (index == 0) {
+ return null;
+ }
+ }
+
+ GridItem prevItem = (GridItem) items.get(index - 1);
+
+ while (!prevItem.isVisible()) {
+ index--;
+ if (index == 0) {
+ return null;
+ }
+
+ prevItem = (GridItem) items.get(index - 1);
+ }
+
+ return prevItem;
+ }
+
+ /**
+ * Returns the previous visible column in the table.
+ *
+ * @param column column
+ * @return previous visible column or null
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridColumn getPreviousVisibleColumn(GridColumn column) {
+ checkWidget();
+
+ int index = displayOrderedColumns.indexOf(column);
+
+ if (index == 0)
+ return null;
+
+ index--;
+
+ GridColumn previous = (GridColumn) displayOrderedColumns.get(index);
+
+ while (!previous.isVisible()) {
+ if (index == 0)
+ return null;
+
+ index--;
+ previous = (GridColumn) displayOrderedColumns.get(index);
+ }
+
+ return previous;
+ }
+
+ /**
+ * Returns the next visible column in the table.
+ *
+ * @param column column
+ * @return next visible column or null
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridColumn getNextVisibleColumn(GridColumn column) {
+ checkWidget();
+
+ int index = displayOrderedColumns.indexOf(column);
+
+ if (index == displayOrderedColumns.size() - 1)
+ return null;
+
+ index++;
+
+ GridColumn next = (GridColumn) displayOrderedColumns.get(index);
+
+ while (!next.isVisible()) {
+ if (index == displayOrderedColumns.size() - 1)
+ return null;
+
+ index++;
+ next = (GridColumn) displayOrderedColumns.get(index);
+ }
+
+ return next;
+ }
+
+ /**
+ * Returns the number of root items contained in the receiver.
+ *
+ * @return the number of items
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getRootItemCount() {
+ checkWidget();
+ return rootItems.size();
+ }
+
+ /**
+ * Returns a (possibly empty) array of {@code GridItem}s which are
+ * the root items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its list of items, so modifying the array will not affect the receiver.
+ * </p>
+ *
+ * @return the root items in the receiver
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridItem[] getRootItems() {
+ checkWidget();
+
+ return (GridItem[]) rootItems.toArray(new GridItem[rootItems.size()]);
+ }
+
+ /**
+ * TODO: asl;fj
+ * @param index
+ * @return asdf
+ */
+ public GridItem getRootItem(int index) {
+ checkWidget();
+
+ if (index < 0 || index >= rootItems.size()) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+
+ return (GridItem) rootItems.get(index);
+ }
+
+ /**
+ * Gets the row header renderer.
+ *
+ * @return Returns the rowHeaderRenderer.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public IRenderer getRowHeaderRenderer() {
+ checkWidget();
+ return rowHeaderRenderer;
+ }
+
+ /**
+ * Returns a array of {@code GridItem}s that are currently selected in the
+ * receiver. The order of the items is unspecified. An empty array indicates
+ * that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its selection, so modifying the array will not affect the receiver.
+ * <p>
+ * If cell selection is enabled, any items which contain at least one selected
+ * cell are returned.
+ *
+ * @return an array representing the selection
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridItem[] getSelection() {
+ checkWidget();
+
+ if (!cellSelectionEnabled) {
+ return (GridItem[]) selectedItems.toArray(new GridItem[selectedItems.size()]);
+ }
+ else {
+ Vector items = new Vector();
+ int itemCount = getItemCount();
+
+ for (Iterator iter = selectedCells.iterator(); iter.hasNext();) {
+ Point cell = (Point) iter.next();
+ if (cell.y >= 0 && cell.y < itemCount) {
+ GridItem item = getItem(cell.y);
+ if (!items.contains(item))
+ items.add(item);
+ }
+ }
+ return (GridItem[]) items.toArray(new GridItem[] {});
+ }
+ }
+
+ /**
+ * Returns the number of selected items contained in the receiver. If cell selection
+ * is enabled, the number of items with at least one selected cell are returned.
+ *
+ * @return the number of selected items
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getSelectionCount() {
+ checkWidget();
+
+ if (!cellSelectionEnabled) {
+ return selectedItems.size();
+ }
+ else {
+ Vector items = new Vector();
+ for (Iterator iter = selectedCells.iterator(); iter.hasNext();) {
+ Point cell = (Point) iter.next();
+ GridItem item = getItem(cell.y);
+ if (!items.contains(item))
+ items.add(item);
+ }
+ return items.size();
+ }
+ }
+
+ /**
+ * Returns the number of selected cells contained in the receiver.
+ *
+ * @return the number of selected cells
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getCellSelectionCount() {
+ checkWidget();
+ return selectedCells.size();
+ }
+
+ /**
+ * Returns the zero-relative index of the item which is currently selected
+ * in the receiver, or -1 if no item is selected. If cell selection is enabled,
+ * returns the index of first item that contains at least one selected cell.
+ *
+ * @return the index of the selected item
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getSelectionIndex() {
+ checkWidget();
+
+ if (!cellSelectionEnabled) {
+ if (selectedItems.size() == 0) {
+ return -1;
+ }
+
+ return items.indexOf(selectedItems.get(0));
+ }
+ else {
+ if (selectedCells.size() == 0)
+ return -1;
+
+ return ((Point) selectedCells.get(0)).y;
+ }
+ }
+
+ /**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the receiver. The order of the indices is unspecified. The
+ * array is empty if no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver to maintain
+ * its selection, so modifying the array will not affect the receiver.
+ * <p>
+ * If cell selection is enabled, returns the indices of any items which
+ * contain at least one selected cell.
+ *
+ * @return the array of indices of the selected items
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int[] getSelectionIndices() {
+ checkWidget();
+
+ if (!cellSelectionEnabled) {
+ int[] indices = new int[selectedItems.size()];
+ int i = 0;
+ for (Iterator itemIterator = selectedItems.iterator(); itemIterator.hasNext();) {
+ GridItem item = (GridItem) itemIterator.next();
+ indices[i] = items.indexOf(item);
+ i++;
+ }
+ return indices;
+ }
+ else {
+ Vector selectedRows = new Vector();
+ for (Iterator iter = selectedCells.iterator(); iter.hasNext();) {
+ Point cell = (Point) iter.next();
+ GridItem item = getItem(cell.y);
+ if (!selectedRows.contains(item))
+ selectedRows.add(item);
+ }
+ int[] indices = new int[selectedRows.size()];
+ int i = 0;
+ for (Iterator itemIterator = selectedRows.iterator(); itemIterator.hasNext();) {
+ GridItem item = (GridItem) itemIterator.next();
+ indices[i] = items.indexOf(item);
+ i++;
+ }
+ return indices;
+ }
+ }
+
+ /**
+ * Returns the zero-relative index of the item which is currently at the top
+ * of the receiver. This index can change when items are scrolled or new
+ * items are added or removed.
+ *
+ * @return the index of the top item
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int getTopIndex() {
+ checkWidget();
+
+ if (topIndex != -1)
+ return topIndex;
+
+ if (!vScroll.getVisible()) {
+ topIndex = 0;
+ }
+ else {
+ // figure out first visible row and last visible row
+ int firstVisibleIndex = vScroll.getSelection();
+
+ if (isTree) {
+ Iterator itemsIter = items.iterator();
+ int row = firstVisibleIndex + 1;
+
+ while (row > 0 && itemsIter.hasNext()) {
+ GridItem item = (GridItem) itemsIter.next();
+
+ if (item.isVisible()) {
+ row--;
+ if (row == 0) {
+ firstVisibleIndex = items.indexOf(item);
+ }
+ }
+ }
+ }
+
+ topIndex = firstVisibleIndex;
+
+ /*
+ * MOPR here lies more potential for increasing performance
+ * for the case (isTree || hasDifferingHeights)
+ * the topIndex could be derived from the previous value
+ * depending on a delta of the vScroll.getSelection()
+ * instead of being calculated completely anew
+ */
+ }
+
+ return topIndex;
+ }
+
+ /**
+ * Returns the zero-relative index of the item which is currently at the bottom
+ * of the receiver. This index can change when items are scrolled, expanded
+ * or collapsed or new items are added or removed.
+ * <p>
+ * Note that the item with this index is often only partly visible; maybe only
+ * a single line of pixels is visible. Use {@link #isShown(GridItem)} to find
+ * out.
+ * <p>
+ * In extreme cases, getBottomIndex() may return the same value as
+ * {@link #getTopIndex()}.
+ *
+ * @return the index of the bottom item
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ int getBottomIndex() {
+ checkWidget();
+
+ if (bottomIndex != -1)
+ return bottomIndex;
+
+ if (items.size() == 0) {
+ bottomIndex = 0;
+ }
+ else if (getVisibleGridHeight() < 1) {
+ bottomIndex = getTopIndex();
+ }
+ else {
+ RowRange range = getRowRange(getTopIndex(), getVisibleGridHeight(), false, false);
+
+ bottomIndex = range.endIndex;
+ bottomIndexShownCompletely = range.height <= getVisibleGridHeight();
+ }
+
+ return bottomIndex;
+ }
+
+ /**
+ * Returns a {@link RowRange} ranging from
+ * the grid item at startIndex to that at endIndex.
+ * <p>
+ * This is primarily used to measure the height
+ * in pixel of such a range and to count the number
+ * of visible grid items within the range.
+ *
+ * @param startIndex index of the first item in the range or -1 to the first visible item in this grid
+ * @param endIndex index of the last item in the range or -1 to use the last visible item in this grid
+ * @return
+ */
+ private RowRange getRowRange(int startIndex, int endIndex) {
+
+ // parameter preparation
+ if (startIndex == -1) {
+ // search frist visible item
+ do
+ startIndex++;
+ while (startIndex < items.size() && !((GridItem) items.get(startIndex)).isVisible());
+ if (startIndex == items.size())
+ return null;
+ }
+ if (endIndex == -1) {
+ // search last visible item
+ endIndex = items.size();
+ do
+ endIndex--;
+ while (endIndex >= 0 && !((GridItem) items.get(endIndex)).isVisible());
+ if (endIndex == -1)
+ return null;
+ }
+
+ // fail fast
+ if (startIndex < 0 || endIndex < 0 || startIndex >= items.size() || endIndex >= items.size()
+ || endIndex < startIndex || ((GridItem) items.get(startIndex)).isVisible() == false
+ || ((GridItem) items.get(endIndex)).isVisible() == false)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ RowRange range = new RowRange();
+ range.startIndex = startIndex;
+ range.endIndex = endIndex;
+
+ if (isTree || hasDifferingHeights) {
+ for (int idx = startIndex; idx <= endIndex; idx++) {
+ GridItem currItem = (GridItem) items.get(idx);
+
+ if (currItem.isVisible()) {
+ if (range.rows > 0)
+ range.height++; // height of horizontal row separator
+ range.height += currItem.getHeight();
+ range.rows++;
+ }
+ }
+ }
+ else {
+ range.rows = range.endIndex - range.startIndex + 1;
+ range.height = (getItemHeight() + 1) * range.rows - 1;
+ }
+
+ return range;
+ }
+
+ /**
+ * This method can be used to build a range of grid rows
+ * that is allowed to span a certain height in pixels.
+ * <p>
+ * It returns a {@link RowRange} that contains information
+ * about the range, especially the index of the last
+ * element in the range (or if inverse == true, then the
+ * index of the first element).
+ * <p>
+ * Note: Even if 'forceEndCompletelyInside' is set to
+ * true, the last item will not lie completely within
+ * the availableHeight, if (height of item at startIndex < availableHeight).
+ *
+ * @param startIndex index of the first (if inverse==false) or
+ * last (if inverse==true) item in the range
+ * @param availableHeight height in pixels
+ * @param forceEndCompletelyInside if true, the last item in the range will lie completely
+ * within the availableHeight, otherwise it may lie partly outside this range
+ * @param inverse if true, then the first item in the range will be searched, not the last
+ * @return range of grid rows
+ * @see RowRange
+ */
+ private RowRange getRowRange(int startIndex, int availableHeight, boolean forceEndCompletelyInside, boolean inverse) {
+ // parameter preparation
+ if (startIndex == -1) {
+ if (!inverse) {
+ // search frist visible item
+ do
+ startIndex++;
+ while (startIndex < items.size() && !((GridItem) items.get(startIndex)).isVisible());
+ if (startIndex == items.size())
+ return null;
+ }
+ else {
+ // search last visible item
+ startIndex = items.size();
+ do
+ startIndex--;
+ while (startIndex >= 0 && !((GridItem) items.get(startIndex)).isVisible());
+ if (startIndex == -1)
+ return null;
+ }
+ }
+
+ // fail fast
+ if (startIndex < 0 || startIndex >= items.size() || ((GridItem) items.get(startIndex)).isVisible() == false)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ RowRange range = new RowRange();
+
+ if (availableHeight <= 0) {
+ // special case: empty range
+ range.startIndex = startIndex;
+ range.endIndex = startIndex;
+ range.rows = 0;
+ range.height = 0;
+ return range;
+ }
+
+ if (isTree || hasDifferingHeights) {
+ int otherIndex = startIndex; // tentative end index
+ int consumedItems = 0;
+ int consumedHeight = 0;
+
+ // consume height for startEnd (note: no separator pixel added here)
+ consumedItems++;
+ consumedHeight += ((GridItem) items.get(otherIndex)).getHeight();
+
+ // note: we use "+2" in next line, because we only try to add another row if there
+ // is room for the separator line + at least one pixel row for the additional item
+ while (consumedHeight + 2 <= availableHeight) {
+ // STEP 1:
+ // try to find a visible item we can add
+
+ int nextIndex = otherIndex;
+ GridItem nextItem;
+
+ do {
+ if (!inverse)
+ nextIndex++;
+ else
+ nextIndex--;
+
+ if (nextIndex >= 0 && nextIndex < items.size())
+ nextItem = (GridItem) items.get(nextIndex);
+ else
+ nextItem = null;
+ }
+ while (nextItem != null && !nextItem.isVisible());
+
+ if (nextItem == null) {
+ // no visible item found
+ break;
+ }
+
+ if (forceEndCompletelyInside) {
+ // must lie completely within the allowed height
+ if (!(consumedHeight + 1 + nextItem.getHeight() <= availableHeight))
+ break;
+ }
+
+ // we found one !!
+
+ // STEP 2:
+ // Consume height for this item
+
+ consumedItems++;
+ consumedHeight += 1; // height of separator line
+ consumedHeight += nextItem.getHeight();
+
+ // STEP 3:
+ // make this item it the current guess for the other end
+ otherIndex = nextIndex;
+ }
+
+ range.startIndex = !inverse ? startIndex : otherIndex;
+ range.endIndex = !inverse ? otherIndex : startIndex;
+ range.rows = consumedItems;
+ range.height = consumedHeight;
+ }
+ else {
+ int availableRows = (availableHeight + 1) / (getItemHeight() + 1);
+
+ if (((getItemHeight() + 1) * range.rows - 1) + 1 < availableHeight) {
+ // not all available space used yet
+ // - so add another row if it need not be completely within availableHeight
+ if (!forceEndCompletelyInside)
+ availableRows++;
+ }
+
+ int otherIndex = startIndex + ((availableRows - 1) * (!inverse ? 1 : -1));
+ if (otherIndex < 0)
+ otherIndex = 0;
+ if (otherIndex >= items.size())
+ otherIndex = items.size() - 1;
+
+ range.startIndex = !inverse ? startIndex : otherIndex;
+ range.endIndex = !inverse ? otherIndex : startIndex;
+ range.rows = range.endIndex - range.startIndex + 1;
+ range.height = (getItemHeight() + 1) * range.rows - 1;
+ }
+
+ return range;
+ }
+
+ /**
+ * Returns the height of the plain grid in pixels.
+ * <p>
+ * This includes all rows for visible items (i.e. items that return true
+ * on {@link GridItem#isVisible()} ; not only those currently visible on
+ * screen) and the 1 pixel separator between rows.
+ * <p>
+ * This does <em>not</em> include the height of the column headers.
+ *
+ * @return height of plain grid
+ */
+ int getGridHeight() {
+ RowRange range = getRowRange(-1, -1);
+ return range != null ? range.height : 0;
+ /*
+ * MOPR currently this method is only used in #getTableSize() ;
+ * if it will be used for more important things in the future
+ * (e.g. the max value for vScroll.setValues() when doing pixel-by-pixel
+ * vertical scrolling) then this value should at least be cached or
+ * even updated incrementally when grid items are added/removed or
+ * expaned/collapsed (similar as #currentVisibleItems).
+ * (this is only necessary in the case (isTree || hasDifferingHeights))
+ */
+ }
+
+ /**
+ * Returns the height of the on-screen area that is available
+ * for showing the grid's rows, i.e. the client area of the
+ * scrollable minus the height of the column headers (if shown).
+ *
+ * @return height of visible grid in pixels
+ */
+ int getVisibleGridHeight() {
+ return getClientArea().height - (columnHeadersVisible ? headerHeight : 0)
+ - (columnFootersVisible ? footerHeight : 0);
+ }
+
+ /**
+ * Returns the height of the screen area that is available for showing the grid columns
+ * @return
+ */
+ int getVisibleGridWidth() {
+ return getClientArea().width - (rowHeaderVisible ? rowHeaderWidth : 0);
+ }
+
+ /**
+ * Gets the top left renderer.
+ *
+ * @return Returns the topLeftRenderer.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public IRenderer getTopLeftRenderer() {
+ checkWidget();
+ return topLeftRenderer;
+ }
+
+ /**
+ * Gets the bottom left renderer.
+ *
+ * @return Returns the bottomLeftRenderer.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public IRenderer getBottomLeftRenderer() {
+ checkWidget();
+ return bottomLeftRenderer;
+ }
+
+ /**
+ * Searches the receiver's list starting at the first column (index 0) until
+ * a column is found that is equal to the argument, and returns the index of
+ * that column. If no column is found, returns -1.
+ *
+ * @param column the search column
+ * @return the index of the column
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the column is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int indexOf(GridColumn column) {
+ checkWidget();
+
+ if (column == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ if (column.getParent() != this)
+ return -1;
+
+ return columns.indexOf(column);
+ }
+
+ /**
+ * Searches the receiver's list starting at the first item (index 0) until
+ * an item is found that is equal to the argument, and returns the index of
+ * that item. If no item is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public int indexOf(GridItem item) {
+ checkWidget();
+
+ if (item == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ if (item.getParent() != this)
+ return -1;
+
+ return items.indexOf(item);
+ }
+
+ /**
+ * Returns {@code true} if the receiver's row header is visible, and
+ * {@code false} otherwise.
+ * <p>
+ *
+ * @return the receiver's row header's visibility state
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean isRowHeaderVisible() {
+ checkWidget();
+ return rowHeaderVisible;
+ }
+
+ /**
+ * Returns {@code true} if the item is selected, and {@code false}
+ * otherwise. Indices out of range are ignored. If cell selection is
+ * enabled, returns true if the item at the given index contains at
+ * least one selected cell.
+ *
+ * @param index the index of the item
+ * @return the visibility state of the item at the index
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean isSelected(int index) {
+ checkWidget();
+
+ if (index < 0 || index >= items.size())
+ return false;
+
+ if (!cellSelectionEnabled) {
+ return isSelected((GridItem) items.get(index));
+ }
+ else {
+ for (Iterator iter = selectedCells.iterator(); iter.hasNext();) {
+ Point cell = (Point) iter.next();
+ if (cell.y == index)
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the given item is selected. If cell selection is enabled,
+ * returns true if the given item contains at least one selected cell.
+ *
+ * @param item item
+ * @return true if the item is selected.
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean isSelected(GridItem item) {
+ checkWidget();
+ if (!cellSelectionEnabled) {
+ return selectedItems.contains(item);
+ }
+ else {
+ int index = indexOf(item);
+ if (index == -1)
+ return false;
+ for (Iterator iter = selectedCells.iterator(); iter.hasNext();) {
+ Point cell = (Point) iter.next();
+ if (cell.y == index)
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the given cell is selected.
+ *
+ * @param cell cell
+ * @return true if the cell is selected.
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the cell is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean isCellSelected(Point cell) {
+ checkWidget();
+
+ if (cell == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ return selectedCells.contains(cell);
+ }
+
+ /**
+ * Removes the item from the receiver at the given zero-relative index.
+ *
+ * @param index the index for the item
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
+ * of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void remove(int index) {
+ checkWidget();
+ if (index < 0 || index > items.size() - 1) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ GridItem item = (GridItem) items.get(index);
+ item.dispose();
+ redraw();
+ }
+
+ /**
+ * 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
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0
+ * and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void remove(int start, int end) {
+ checkWidget();
+
+ for (int i = end; i >= start; i--) {
+ if (i < 0 || i > items.size() - 1) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ GridItem item = (GridItem) items.get(i);
+ item.dispose();
+ }
+ redraw();
+ }
+
+ /**
+ * Removes the items from the receiver's list at the given zero-relative
+ * indices.
+ *
+ * @param indices the array of indices of the items
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number
+ * of elements in the list minus 1 (inclusive)</li>
+ * <li>ERROR_NULL_ARGUMENT - if the indices array is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void remove(int[] indices) {
+ checkWidget();
+
+ if (indices == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ GridItem[] removeThese = new GridItem[indices.length];
+ for (int i = 0; i < indices.length; i++) {
+ int j = indices[i];
+ if (j < items.size() && j >= 0) {
+ removeThese[i] = (GridItem) items.get(j);
+ }
+ else {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+
+ }
+ for (int i = 0; i < removeThese.length; i++) {
+ GridItem item = removeThese[i];
+ item.dispose();
+ }
+ redraw();
+ }
+
+ /**
+ * Removes all of the items from the receiver.
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * Call {@link Grid} disposeAllItems and clearItems.. Is faster
+ */
+ @Deprecated
+ public void removeAll() {
+ checkWidget();
+
+ while (items.size() > 0) {
+ ((GridItem) items.get(0)).dispose();
+ }
+ deselectAll();
+ redraw();
+ }
+
+ /**
+ * All items needs to call the disposeOnly method
+ */
+ public void disposeAllItems() {
+ checkWidget();
+
+ final GridItem[] items = getItems();
+ for (final GridItem gridItem : items) {
+ gridItem.disposeOnly();
+ }
+ clearItems();
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the receiver's selection changes.
+ *
+ * @param listener the listener which should no longer be notified
+ * @see SelectionListener
+ * @see #addSelectionListener(SelectionListener)
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ removeListener(SWT.Selection, listener);
+ removeListener(SWT.DefaultSelection, listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be
+ * notified when the receiver's items changes.
+ *
+ * @param listener the listener which should no longer be notified
+ * @see TreeListener
+ * @see #addTreeListener(TreeListener)
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void removeTreeListener(TreeListener listener) {
+ checkWidget();
+ removeListener(SWT.Expand, listener);
+ removeListener(SWT.Collapse, listener);
+ }
+
+ /**
+ * Selects the item at the given zero-relative index in the receiver. If the
+ * item at the index was already selected, it remains selected. Indices that
+ * are out of range are ignored.
+ * <p>
+ * If cell selection is enabled, selects all cells at the given index.
+ *
+ * @param index the index of the item to select
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void select(int index) {
+ checkWidget();
+
+ if (!selectionEnabled)
+ return;
+
+ if (index < 0 || index >= items.size())
+ return;
+
+ GridItem item = (GridItem) items.get(index);
+
+ if (!cellSelectionEnabled) {
+ if (selectionType == SWT.MULTI && selectedItems.contains(item))
+ return;
+
+ if (selectionType == SWT.SINGLE)
+ selectedItems.clear();
+
+ selectedItems.add(item);
+ }
+ else {
+ selectCells(getCells(item));
+ }
+
+ redraw();
+ }
+
+ /**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive. The current
+ * selection is not cleared before the new items are selected.
+ * <p>
+ * If an item in the given range is not selected, it is selected. If an item
+ * in the given range was already selected, it remains selected. Indices
+ * that are out of range are ignored and no items will be selected if start
+ * is greater than end. If the receiver is single-select and there is more
+ * than one item in the given range, then all indices are ignored.
+ * <p>
+ * If cell selection is enabled, all cells within the given range are selected.
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see Grid#setSelection(int,int)
+ */
+ public void select(int start, int end) {
+ checkWidget();
+
+ if (!selectionEnabled)
+ return;
+
+ if (selectionType == SWT.SINGLE && start != end)
+ return;
+
+ if (!cellSelectionEnabled) {
+ if (selectionType == SWT.SINGLE)
+ selectedItems.clear();
+ }
+
+ for (int i = start; i <= end; i++) {
+ if (i < 0) {
+ continue;
+ }
+ if (i > items.size() - 1) {
+ break;
+ }
+
+ GridItem item = (GridItem) items.get(i);
+
+ if (!cellSelectionEnabled) {
+ if (!selectedItems.contains(item))
+ selectedItems.add(item);
+ }
+ else {
+ selectCells(getCells(item));
+ }
+ }
+
+ redraw();
+ }
+
+ /**
+ * Selects the items at the given zero-relative indices in the receiver. The
+ * current selection is not cleared before the new items are selected.
+ * <p>
+ * 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.
+ * <p>
+ * If cell selection is enabled, all cells within the given indices are
+ * selected.
+ *
+ * @param indices the array of indices for the items to select
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see Grid#setSelection(int[])
+ */
+ public void select(int[] indices) {
+ checkWidget();
+
+ if (indices == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ if (!selectionEnabled)
+ return;
+
+ if (selectionType == SWT.SINGLE && indices.length > 1)
+ return;
+
+ if (!cellSelectionEnabled)
+ if (selectionType == SWT.SINGLE)
+ selectedItems.clear();
+
+ for (int i = 0; i < indices.length; i++) {
+ int j = indices[i];
+
+ if (j >= 0 && j < items.size()) {
+ GridItem item = (GridItem) items.get(j);
+
+ if (!cellSelectionEnabled) {
+ if (!selectedItems.contains(item))
+ selectedItems.add(item);
+ }
+ else {
+ selectCells(getCells(item));
+ }
+ }
+ }
+ redraw();
+ }
+
+ /**
+ * Selects all of the items in the receiver.
+ * <p>
+ * If the receiver is single-select, do nothing. If cell selection is enabled,
+ * all cells are selected.
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void selectAll() {
+ checkWidget();
+
+ if (!selectionEnabled)
+ return;
+
+ if (selectionType == SWT.SINGLE)
+ return;
+
+ if (cellSelectionEnabled) {
+ selectAllCells();
+ return;
+ }
+
+ selectedItems.clear();
+ selectedItems.addAll(items);
+ redraw();
+ }
+
+ /**
+ * Sets the empty cell renderer.
+ *
+ * @param emptyCellRenderer The emptyCellRenderer to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setEmptyCellRenderer(GridCellRenderer emptyCellRenderer) {
+ checkWidget();
+ emptyCellRenderer.setDisplay(getDisplay());
+ this.emptyCellRenderer = emptyCellRenderer;
+ }
+
+ /**
+ * Sets the empty column header renderer.
+ *
+ * @param emptyColumnHeaderRenderer The emptyColumnHeaderRenderer to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setEmptyColumnHeaderRenderer(IRenderer emptyColumnHeaderRenderer) {
+ checkWidget();
+ emptyColumnHeaderRenderer.setDisplay(getDisplay());
+ this.emptyColumnHeaderRenderer = emptyColumnHeaderRenderer;
+ }
+
+ /**
+ * Sets the empty column footer renderer.
+ *
+ * @param emptyColumnFooterRenderer The emptyColumnFooterRenderer to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setEmptyColumnFooterRenderer(IRenderer emptyColumnFooterRenderer) {
+ checkWidget();
+ emptyColumnFooterRenderer.setDisplay(getDisplay());
+ this.emptyColumnFooterRenderer = emptyColumnFooterRenderer;
+ }
+
+ /**
+ * Sets the empty row header renderer.
+ *
+ * @param emptyRowHeaderRenderer The emptyRowHeaderRenderer to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setEmptyRowHeaderRenderer(IRenderer emptyRowHeaderRenderer) {
+ checkWidget();
+ emptyRowHeaderRenderer.setDisplay(getDisplay());
+ this.emptyRowHeaderRenderer = emptyRowHeaderRenderer;
+ }
+
+ /**
+ * Sets the external horizontal scrollbar. Allows the scrolling to be
+ * managed externally from the table. This functionality is only intended
+ * when SWT.H_SCROLL is not given.
+ * <p>
+ * Using this feature, a ScrollBar could be instantiated outside the table,
+ * wrapped in IScrollBar and thus be 'connected' to the table.
+ *
+ * @param scroll The horizontal scrollbar to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ protected void setHorizontalScrollBarProxy(IScrollBarProxy scroll) {
+ checkWidget();
+ if (getHorizontalBar() != null) {
+ return;
+ }
+ hScroll = scroll;
+
+ hScroll.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
onScrollSelection();
@@ -3615,9 +3410,9 @@ public class Grid extends Canvas
public void widgetDefaultSelected(SelectionEvent e) {
}
});
- }
+ }
- /**
+ /**
* Sets the external vertical scrollbar. Allows the scrolling to be managed
* externally from the table. This functionality is only intended when
* SWT.V_SCROLL is not given.
@@ -3635,16 +3430,14 @@ public class Grid extends Canvas
* thread that created the receiver</li>
* </ul>
*/
- protected void setlVerticalScrollBarProxy(IScrollBarProxy scroll)
- {
- checkWidget();
- if (getVerticalBar() != null)
- {
- return;
- }
- vScroll = scroll;
+ protected void setlVerticalScrollBarProxy(IScrollBarProxy scroll) {
+ checkWidget();
+ if (getVerticalBar() != null) {
+ return;
+ }
+ vScroll = scroll;
- vScroll.addSelectionListener(new SelectionListener() {
+ vScroll.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
onScrollSelection();
@@ -3654,4468 +3447,3885 @@ public class Grid extends Canvas
public void widgetDefaultSelected(SelectionEvent e) {
}
});
- }
-
- /**
- * Sets the focus renderer.
- *
- * @param focusRenderer The focusRenderer to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setFocusRenderer(IRenderer focusRenderer)
- {
- checkWidget();
- this.focusRenderer = focusRenderer;
- }
-
- /**
- * Marks the receiver's header as visible if the argument is {@code true},
- * and marks it invisible otherwise.
- *
- * @param show the new visibility state
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setHeaderVisible(boolean show)
- {
- checkWidget();
- this.columnHeadersVisible = show;
- redraw();
- }
-
- /**
- * Marks the receiver's footer as visible if the argument is {@code true},
- * and marks it invisible otherwise.
- *
- * @param show the new visibility state
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setFooterVisible(boolean show)
- {
- checkWidget();
- this.columnFootersVisible = show;
- redraw();
- }
-
- /**
- * Sets the line color.
- *
- * @param lineColor The lineColor to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setLineColor(Color lineColor)
- {
- checkWidget();
- this.lineColor = lineColor;
- }
-
- /**
- * Sets the line visibility.
- *
- * @param linesVisible Te linesVisible to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setLinesVisible(boolean linesVisible)
- {
- checkWidget();
- this.linesVisible = linesVisible;
- redraw();
- }
+ }
+
+ /**
+ * Sets the focus renderer.
+ *
+ * @param focusRenderer The focusRenderer to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setFocusRenderer(IRenderer focusRenderer) {
+ checkWidget();
+ this.focusRenderer = focusRenderer;
+ }
+
+ /**
+ * Marks the receiver's header as visible if the argument is {@code true},
+ * and marks it invisible otherwise.
+ *
+ * @param show the new visibility state
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setHeaderVisible(boolean show) {
+ checkWidget();
+ this.columnHeadersVisible = show;
+ redraw();
+ }
+
+ /**
+ * Marks the receiver's footer as visible if the argument is {@code true},
+ * and marks it invisible otherwise.
+ *
+ * @param show the new visibility state
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setFooterVisible(boolean show) {
+ checkWidget();
+ this.columnFootersVisible = show;
+ redraw();
+ }
+
+ /**
+ * Sets the line color.
+ *
+ * @param lineColor The lineColor to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setLineColor(Color lineColor) {
+ checkWidget();
+ this.lineColor = lineColor;
+ }
+
+ /**
+ * Sets the line visibility.
+ *
+ * @param linesVisible Te linesVisible to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setLinesVisible(boolean linesVisible) {
+ checkWidget();
+ this.linesVisible = linesVisible;
+ redraw();
+ }
/**
* Sets the tree line visibility.
*
* @param treeLinesVisible
* @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
*/
public void setTreeLinesVisible(boolean treeLinesVisible) {
checkWidget();
this.treeLinesVisible = treeLinesVisible;
- redraw();
- }
-
- /**
- * Sets the row header renderer.
- *
- * @param rowHeaderRenderer The rowHeaderRenderer to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setRowHeaderRenderer(IRenderer rowHeaderRenderer)
- {
- checkWidget();
- rowHeaderRenderer.setDisplay(getDisplay());
- this.rowHeaderRenderer = rowHeaderRenderer;
- }
-
- /**
- * Marks the receiver's row header as visible if the argument is
- * {@code true}, and marks it invisible otherwise. When row headers are
- * visible, horizontal scrolling is always done by column rather than by
- * pixel.
- *
- * @param show the new visibility state
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setRowHeaderVisible(boolean show)
- {
- checkWidget();
- this.rowHeaderVisible = show;
- setColumnScrolling(true);
-
- if (show && isAutoWidth())
- {
- rowHeaderWidth = 1;
-
- for (Iterator iter = items.iterator(); iter.hasNext();)
- {
- GridItem iterItem = (GridItem)iter.next();
- rowHeaderWidth = Math.max(rowHeaderWidth,rowHeaderRenderer.computeSize(sizingGC, SWT.DEFAULT,SWT.DEFAULT,iterItem).x);
- }
- }
-
- redraw();
- }
-
- /**
- * Selects the item at the given zero-relative index in the receiver. The
- * current selection is first cleared, then the new item is selected.
- * <p>
- * If cell selection is enabled, all cells within the item at the given index
- * are selected.
- *
- * @param index the index of the item to select
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setSelection(int index)
- {
- checkWidget();
-
- if (!selectionEnabled) return;
-
- if (index >= 0 && index < items.size())
- {
- if (!cellSelectionEnabled)
- {
- selectedItems.clear();
- selectedItems.add(items.get(index));
- redraw();
- }
- else
- {
- selectedCells.clear();
- selectCells(getCells((GridItem)items.get(index)));
- }
- }
- }
-
- /**
- * Selects the items in the range specified by the given zero-relative
- * indices in the receiver. The range of indices is inclusive. The current
- * selection is cleared before the new items are selected.
- * <p>
- * Indices that are out of range are ignored and no items will be selected
- * if start is greater than end. If the receiver is single-select and there
- * is more than one item in the given range, then all indices are ignored.
- * <p>
- * If cell selection is enabled, all cells within the given range are selected.
- *
- * @param start the start index of the items to select
- * @param end the end index of the items to select
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see Grid#deselectAll()
- * @see Grid#select(int,int)
- */
- public void setSelection(int start, int end)
- {
- checkWidget();
-
- if (!selectionEnabled) return;
-
- if (selectionType == SWT.SINGLE && start != end) return;
-
- if (!cellSelectionEnabled)
- {
- selectedItems.clear();
- }
- else
- {
- selectedCells.clear();
- }
-
- for (int i = start; i <= end; i++)
- {
- if (i < 0)
- {
- continue;
- }
- if (i > items.size() - 1)
- {
- break;
- }
-
- GridItem item = (GridItem)items.get(i);
-
- if (!cellSelectionEnabled)
- {
- selectedItems.add(item);
- }
- else
- {
- selectCells(getCells(item));
- }
- }
- redraw();
- }
-
- /**
- * Selects the items at the given zero-relative indices in the receiver. The
- * current selection is cleared before the new items are selected.
- * <p>
- * 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.
- * <p>
- * If cell selection is enabled, all cells within the given indices are selected.
- *
- * @param indices the indices of the items to select
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see Grid#deselectAll()
- * @see Grid#select(int[])
- */
- public void setSelection(int[] indices)
- {
- checkWidget();
-
- if (!selectionEnabled) return;
-
- if (selectionType == SWT.SINGLE && indices.length > 1) return;
-
- if (!cellSelectionEnabled)
- {
- selectedItems.clear();
- }
- else
- {
- selectedCells.clear();
- }
-
- for (int i = 0; i < indices.length; i++)
- {
- int j = indices[i];
-
- if (j < 0)
- {
- continue;
- }
- if (j > items.size() - 1)
- {
- break;
- }
-
- GridItem item = (GridItem)items.get(j);
-
- if (!cellSelectionEnabled)
- {
- selectedItems.add(item);
- }
- else
- {
- selectCells(getCells(item));
- }
- }
- redraw();
- }
-
- /**
- * Sets the receiver's selection to be the given array of items. The current
- * selection is cleared before the new items are selected.
- * <p>
- * 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. If cell selection is enabled, all cells within the given items
- * are selected.
- *
- * @param _items the array of items
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the array of items is null</li>
- * <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- * @see Grid#deselectAll()
- * @see Grid#select(int[])
- * @see Grid#setSelection(int[])
- */
- public void setSelection(GridItem[] _items)
- {
- checkWidget();
-
- if (!selectionEnabled) return;
-
- if (_items == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- if (selectionType == SWT.SINGLE && _items.length > 1) return;
-
- if (!cellSelectionEnabled)
- {
- selectedItems.clear();
- }
- else
- {
- selectedCells.clear();
- }
-
- for (int i = 0; i < _items.length; i++)
- {
- GridItem item = _items[i];
- if (item == null) continue;
- if (item.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- if (item.getParent() != this) continue;
-
- if (!cellSelectionEnabled)
- {
- selectedItems.add(item);
- }
- else
- {
- selectCells(getCells(item));
- }
- }
-
- redraw();
- }
-
- /**
- * Sets the zero-relative index of the item which is currently at the top of
- * the receiver. This index can change when items are scrolled or new items
- * are added and removed.
- *
- * @param index the index of the top item
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setTopIndex(int index)
- {
- checkWidget();
- if (index < 0 || index >= items.size())
- {
- return;
- }
-
- GridItem item = (GridItem)items.get(index);
- if (!item.isVisible())
- {
- return;
- }
-
- if (!vScroll.getVisible())
- {
- return;
- }
-
- int vScrollAmount = 0;
-
- for (int i = 0; i < index; i++)
- {
- if (((GridItem)items.get(i)).isVisible())
- {
- vScrollAmount++;
- }
- }
-
- vScroll.setSelection(vScrollAmount);
- topIndex = -1;
- bottomIndex = -1;
- redraw();
- }
-
- /**
- * Sets the top left renderer.
- *
- * @param topLeftRenderer The topLeftRenderer to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setTopLeftRenderer(IRenderer topLeftRenderer)
- {
- checkWidget();
- topLeftRenderer.setDisplay(getDisplay());
- this.topLeftRenderer = topLeftRenderer;
- }
-
- /**
- * Sets the bottom left renderer.
- *
- * @param bottomLeftRenderer The topLeftRenderer to set.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setBottomLeftRenderer(IRenderer bottomLeftRenderer)
- {
- checkWidget();
- bottomLeftRenderer.setDisplay(getDisplay());
- this.bottomLeftRenderer = bottomLeftRenderer;
- }
-
- /**
- * Shows the column. If the column is already showing in the receiver, this
- * method simply returns. Otherwise, the columns are scrolled until the
- * column is visible.
- *
- * @param col the column to be shown
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void showColumn(GridColumn col)
- {
- checkWidget();
-
- if (!col.isVisible())
- {
- GridColumnGroup group = col.getColumnGroup();
- group.setExpanded(!group.getExpanded());
- if (group.getExpanded())
- {
- group.notifyListeners(SWT.Expand,new Event());
- }
- else
- {
- group.notifyListeners(SWT.Collapse,new Event());
- }
- }
-
- if (!hScroll.getVisible())
- {
- return;
- }
-
- int x = getColumnHeaderXPosition(col);
-
- int firstVisibleX = 0;
- if (rowHeaderVisible)
- {
- firstVisibleX = rowHeaderWidth;
- }
-
- // if its visible just return
- if (x >= firstVisibleX
- && (x + col.getWidth()) <= (firstVisibleX + (getClientArea().width - firstVisibleX)))
- {
- return;
- }
-
- if (!getColumnScrolling())
- {
- if (x < firstVisibleX)
- {
- hScroll.setSelection(getHScrollSelectionInPixels() - (firstVisibleX - x));
- }
- else
- {
- if (col.getWidth() > getClientArea().width - firstVisibleX)
- {
- hScroll.setSelection(getHScrollSelectionInPixels() + (x - firstVisibleX));
- }
- else
- {
- x -= getClientArea().width - firstVisibleX - col.getWidth();
- hScroll.setSelection(getHScrollSelectionInPixels() + (x - firstVisibleX));
- }
- }
- }
- else
- {
- if (x < firstVisibleX || col.getWidth() > getClientArea().width - firstVisibleX)
- {
- int sel = displayOrderedColumns.indexOf(col);
- hScroll.setSelection(sel);
- }
- else
- {
- int availableWidth = getClientArea().width - firstVisibleX - col.getWidth();
-
- GridColumn prevCol = getPreviousVisibleColumn(col);
- GridColumn currentScrollTo = col;
-
- while (true)
- {
- if (prevCol == null || prevCol.getWidth() > availableWidth)
- {
- int sel = displayOrderedColumns.indexOf(currentScrollTo);
- hScroll.setSelection(sel);
- break;
- }
- else
- {
- availableWidth -= prevCol.getWidth();
- currentScrollTo = prevCol;
- prevCol = getPreviousVisibleColumn(prevCol);
- }
- }
- }
- }
-
- redraw();
- }
-
- /**
- * Returns true if 'item' is currently being <em>completely</em>
- * shown in this <code>Grid</code>'s visible on-screen area.
- *
- * <p>Here, "completely" only refers to the item's height, not its
- * width. This means this method returns true also if some cells
- * are horizontally scrolled away.
- *
- * @param item
- * @return true if 'item' is shown
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * <li>ERROR_INVALID_ARGUMENT - if 'item' is not contained in the receiver</li>
- * </ul>
- */
- boolean isShown(GridItem item)
- {
- checkWidget();
-
- if(!item.isVisible())
- return false;
-
- int itemIndex = items.indexOf(item);
-
- if (itemIndex == -1)
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
-
- int firstVisibleIndex = getTopIndex();
- int lastVisibleIndex = getBottomIndex();
-
- return (itemIndex >= firstVisibleIndex && itemIndex < lastVisibleIndex)
- ||
- (itemIndex == lastVisibleIndex && bottomIndexShownCompletely);
- }
- /**
- * 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
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * <li>ERROR_INVALID_ARGUMENT - if 'item' is not contained in the receiver</li>
- * </ul>
- */
- public void showItem(GridItem item)
- {
- checkWidget();
-
- updateScrollbars();
-
- // if no items are visible on screen then abort
- if (getVisibleGridHeight()<1)
- {
- return;
- }
-
- // if its visible just return
- if (isShown(item))
- {
- return;
- }
-
- if (!item.isVisible())
- {
- GridItem parent = item.getParentItem();
- do
- {
- if (!parent.isExpanded())
- {
- parent.setExpanded(true);
- parent.fireEvent(SWT.Expand);
- }
- parent = parent.getParentItem();
- }
- while (parent != null);
- }
-
- int newTopIndex = items.indexOf(item);
-
- if (newTopIndex >= getBottomIndex())
- {
- RowRange range = getRowRange(newTopIndex,getVisibleGridHeight(),true,true); // note: inverse==true
- newTopIndex = range.startIndex; // note: use startIndex because of inverse==true
- }
-
- setTopIndex(newTopIndex);
- }
-
- /**
- * 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.
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void showSelection()
- {
- checkWidget();
-
- if (scrollValuesObsolete)
- updateScrollbars();
-
- GridItem item = null;
-
- if (!cellSelectionEnabled)
- {
- if (selectedItems.size() == 0)
- {
- return;
- }
-
- item = (GridItem)selectedItems.get(0);
- showItem(item);
- }
- else
- {
- if (selectedCells.size() == 0) return;
-
- Point cell = (Point)selectedCells.get(0);
- item = getItem(cell.y);
- showItem(item);
- GridColumn col = getColumn(cell.x);
- showColumn(col);
- }
-
- }
-
- /**
- * Enables selection highlighting if the argument is <code>true</code>.
- *
- * @param selectionEnabled the selection enabled state
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setSelectionEnabled(boolean selectionEnabled)
- {
- checkWidget();
-
- if (!selectionEnabled)
- {
- selectedItems.clear();
- redraw();
- }
-
- this.selectionEnabled = selectionEnabled;
- }
-
- /**
- * Returns <code>true</code> if selection is enabled, false otherwise.
- *
- * @return the selection enabled state
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean getSelectionEnabled()
- {
- checkWidget();
- return selectionEnabled;
- }
-
-
- /**
- * Computes and sets the height of the header row. This method will ask for
- * the preferred size of all the column headers and use the max.
- *
- * @param gc GC for font metrics, etc.
- */
- private void computeHeaderHeight(GC gc)
- {
-
- int colHeaderHeight = 0;
- for (Iterator columnsIterator = columns.iterator(); columnsIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnsIterator.next();
- colHeaderHeight = Math
- .max(column.getHeaderRenderer().computeSize(gc, column.getWidth(), SWT.DEFAULT,
- column).y, colHeaderHeight);
- }
-
- int groupHeight = 0;
- for (int groupIndex = 0; groupIndex < columnGroups.length; groupIndex++)
- {
- GridColumnGroup group = columnGroups[groupIndex];
- groupHeight = Math.max(group.getHeaderRenderer().computeSize(gc, SWT.DEFAULT,
- SWT.DEFAULT, group).y,
- groupHeight);
- }
-
- headerHeight = colHeaderHeight + groupHeight;
- groupHeaderHeight = groupHeight;
- }
-
- private void computeFooterHeight(GC gc)
- {
-
- int colFooterHeight = 0;
- for (Iterator columnsIterator = columns.iterator(); columnsIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnsIterator.next();
- colFooterHeight = Math
- .max(column.getFooterRenderer().computeSize(gc, column.getWidth(), SWT.DEFAULT,
- column).y, colFooterHeight);
- }
-
- footerHeight = colFooterHeight;
- }
-
- /**
- * Returns the computed default item height. Currently this method just gets the
- * preferred size of all the cells in the given row and returns that (it is
- * then used as the height of all rows with items having a height of -1).
- *
- * @param item item to use for sizing
- * @param gc GC used to perform font metrics,etc.
- * @return the row height
- */
- private int computeItemHeight(GridItem item, GC gc)
- {
- int height = 1;
-
- if (columns.size() == 0 || items.size() == 0)
- {
- return height;
- }
-
- for (Iterator columnsIterator = columns.iterator(); columnsIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnsIterator.next();
- column.getCellRenderer().setColumn(indexOf(column));
- height = Math.max(height, column.getCellRenderer().computeSize(gc, SWT.DEFAULT,
- SWT.DEFAULT,
- item).y);
- }
-
- if( rowHeaderVisible && rowHeaderRenderer != null ) {
- height = Math.max(height, rowHeaderRenderer.computeSize(gc, SWT.DEFAULT,
- SWT.DEFAULT, item).y);
- }
-
- return height <= 0 ? 16 : height;
- }
-
- /**
- * Returns the x position of the given column. Takes into account scroll
- * position.
- *
- * @param column given column
- * @return x position
- */
- private int getColumnHeaderXPosition(GridColumn column)
- {
- if (!column.isVisible())
- {
- return -1;
- }
-
- int x = 0;
-
- x -= getHScrollSelectionInPixels();
-
- if (rowHeaderVisible)
- {
- x += rowHeaderWidth;
- }
- for (Iterator column2Iterator = displayOrderedColumns.iterator(); column2Iterator.hasNext(); )
- {
- GridColumn column2 = (GridColumn) column2Iterator.next();
-
- if (!column2.isVisible())
- {
- continue;
- }
-
- if (column2 == column)
- {
- break;
- }
-
- x += column2.getWidth();
- }
-
- return x;
- }
-
- /**
- * Returns the hscroll selection in pixels. This method abstracts away the
- * differences between column by column scrolling and pixel based scrolling.
- *
- * @return the horizontal scroll selection in pixels
- */
- private int getHScrollSelectionInPixels()
- {
- int selection = hScroll.getSelection();
- if (columnScrolling)
- {
- int pixels = 0;
- for (int i = 0; i < selection; i++)
- {
- pixels += ((GridColumn)displayOrderedColumns.get(i)).getWidth();
- }
- selection = pixels;
- }
- return selection;
- }
-
- /**
- * Returns the size of the preferred size of the inner table.
- *
- * @return the preferred size of the table.
- */
- private Point getTableSize()
- {
- int x = 0;
- int y = 0;
-
- if (columnHeadersVisible)
- {
- y += headerHeight;
- }
-
- if(columnFootersVisible) {
- y += footerHeight;
- }
-
- y += getGridHeight();
-
- if (rowHeaderVisible)
- {
- x += rowHeaderWidth;
- }
-
- for (Iterator columnIterator = columns.iterator(); columnIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnIterator.next();
- if (column.isVisible())
- {
- x += column.getWidth();
- }
- }
-
- return new Point(x, y);
- }
-
- /**
- * Manages the header column dragging and calculates the drop point,
- * triggers a redraw.
- *
- * @param x mouse x
- * @return true if this event has been consumed.
- */
- private boolean handleColumnDragging(int x)
- {
-
- GridColumn local_dragDropBeforeColumn = null;
- GridColumn local_dragDropAfterColumn = null;
-
- int x2 = 1;
-
- if (rowHeaderVisible)
- {
- x2 += rowHeaderWidth + 1;
- }
-
- x2 -= getHScrollSelectionInPixels();
-
- int i = 0;
- GridColumn previousVisibleCol = null;
- boolean nextVisibleColumnIsBeforeCol = false;
- GridColumn firstVisibleCol = null;
- GridColumn lastVisibleCol = null;
-
- if (x < x2)
- {
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnIterator.next();
- if (!column.isVisible())
- {
- continue;
- }
- local_dragDropBeforeColumn = column;
- break;
- }
- local_dragDropAfterColumn = null;
- }
- else
- {
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnIterator.next();
- if (!column.isVisible())
- {
- continue;
- }
-
- i++;
-
- if (firstVisibleCol == null)
- {
- firstVisibleCol = column;
- }
- lastVisibleCol = column;
-
- if (nextVisibleColumnIsBeforeCol)
- {
- local_dragDropBeforeColumn = column;
- nextVisibleColumnIsBeforeCol = false;
- }
-
- if (x >= x2 && x <= (x2 + column.getWidth()))
- {
- if (x <= (x2 + column.getWidth() / 2))
- {
- local_dragDropBeforeColumn = column;
- local_dragDropAfterColumn = previousVisibleCol;
- }
- else
- {
- local_dragDropAfterColumn = column;
-
- // the next visible column is the before col
- nextVisibleColumnIsBeforeCol = true;
- }
- }
-
- x2 += column.getWidth();
- previousVisibleCol = column;
- }
-
- if (local_dragDropBeforeColumn == null)
- {
- local_dragDropAfterColumn = lastVisibleCol;
- }
- }
-
- currentHeaderDragX = x;
-
- if (local_dragDropBeforeColumn != dragDropBeforeColumn
- || (dragDropBeforeColumn == null && dragDropAfterColumn == null))
- {
- dragDropPointValid = true;
-
- // Determine if valid drop point
- if (columnGroups.length != 0)
- {
-
- if (columnBeingPushed.getColumnGroup() == null)
- {
- if (local_dragDropBeforeColumn != null
- && local_dragDropAfterColumn != null
- && local_dragDropBeforeColumn.getColumnGroup() != null
- && local_dragDropBeforeColumn.getColumnGroup() == local_dragDropAfterColumn
- .getColumnGroup())
- {
- // Dont move a column w/o a group in between two columns
- // in the same group
- dragDropPointValid = false;
- }
- }
- else
- {
- if (!(local_dragDropBeforeColumn != null && local_dragDropBeforeColumn
- .getColumnGroup() == columnBeingPushed.getColumnGroup())
- && !(local_dragDropAfterColumn != null && local_dragDropAfterColumn
- .getColumnGroup() == columnBeingPushed.getColumnGroup()))
- {
- // Dont move a column with a group
- dragDropPointValid = false;
- }
- }
- }
- else
- {
- dragDropPointValid = true;
- }
- }
-
- dragDropBeforeColumn = local_dragDropBeforeColumn;
- dragDropAfterColumn = local_dragDropAfterColumn;
-
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- return true;
- }
-
- /**
- * Handles the moving of columns after a column is dropped.
- */
- private void handleColumnDrop()
- {
- draggingColumn = false;
-
- if ((dragDropBeforeColumn != columnBeingPushed && dragDropAfterColumn != columnBeingPushed)
- && (columnGroups.length == 0 || dragDropPointValid))
- {
-
- int notifyFrom = displayOrderedColumns.indexOf(columnBeingPushed);
- int notifyTo = notifyFrom;
-
- displayOrderedColumns.remove(columnBeingPushed);
-
- if (dragDropBeforeColumn == null)
- {
-
- notifyTo = displayOrderedColumns.size();
- displayOrderedColumns.add(columnBeingPushed);
- }
- else if (dragDropAfterColumn == null)
- {
- displayOrderedColumns.add(0, columnBeingPushed);
- notifyFrom = 0;
- }
- else
- {
- int insertAtIndex = 0;
-
- if (columnGroups.length != 0)
- {
- // ensure that we aren't putting this column into a group,
- // this is possible if
- // there are invisible columns between the after and before
- // cols
-
- if (dragDropBeforeColumn.getColumnGroup() == columnBeingPushed.getColumnGroup())
- {
- insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
- }
- else if (dragDropAfterColumn.getColumnGroup() == columnBeingPushed
- .getColumnGroup())
- {
- insertAtIndex = displayOrderedColumns.indexOf(dragDropAfterColumn) + 1;
- }
- else
- {
- if (dragDropBeforeColumn.getColumnGroup() == null)
- {
- insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
- }
- else
- {
- GridColumnGroup beforeGroup = dragDropBeforeColumn.getColumnGroup();
- insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
- while (insertAtIndex > 0
- && ((GridColumn)displayOrderedColumns.get(insertAtIndex -1)).getColumnGroup() == beforeGroup)
- {
- insertAtIndex--;
- }
-
- }
- }
- }
- else
- {
- insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
- }
- displayOrderedColumns.add(insertAtIndex, columnBeingPushed);
- notifyFrom = Math.min(notifyFrom, insertAtIndex);
- notifyTo = Math.max(notifyTo, insertAtIndex);
- }
-
- for (int i = notifyFrom; i <= notifyTo; i++)
- {
- ((GridColumn)displayOrderedColumns.get(i)).fireMoved();
- }
- }
-
- redraw();
- }
-
- /**
- * Determines if the mouse is pushing the header but has since move out of
- * the header bounds and therefore should be drawn unpushed. Also initiates
- * a column header drag when appropriate.
- *
- * @param x mouse x
- * @param y mouse y
- * @return true if this event has been consumed.
- */
- private boolean handleColumnHeaderHoverWhilePushing(int x, int y)
- {
- GridColumn overThis = overColumnHeader(x, y);
-
- if ((overThis == columnBeingPushed) != pushingAndHovering)
- {
- pushingAndHovering = (overThis == columnBeingPushed);
- redraw();
- }
- if (columnBeingPushed.getMoveable())
- {
-
- if (pushingAndHovering && Math.abs(startHeaderPushX - x) > 3)
- {
-
- // stop pushing
- pushingColumn = false;
- columnBeingPushed.getHeaderRenderer().setMouseDown(false);
- columnBeingPushed.getHeaderRenderer().setHover(false);
-
- // now dragging
- draggingColumn = true;
- columnBeingPushed.getHeaderRenderer().setMouseDown(false);
-
- startHeaderDragX = x;
-
- dragDropAfterColumn = null;
- dragDropBeforeColumn = null;
- dragDropPointValid = true;
-
- handleColumnDragging(x);
- }
- }
-
- return true;
- }
-
- /**
- * Determines if a column group header has been clicked and forwards the
- * event to the header renderer.
- *
- * @param x mouse x
- * @param y mouse y
- * @return true if this event has been consumed.
- */
- private boolean handleColumnGroupHeaderClick(int x, int y)
- {
-
- if (!columnHeadersVisible)
- {
- return false;
- }
-
- GridColumnGroup overThis = overColumnGroupHeader(x, y);
-
- if (overThis == null)
- {
- return false;
- }
-
- int headerX = 0;
- if (rowHeaderVisible)
- {
- headerX += rowHeaderWidth;
- }
-
- int width = 0;
- boolean firstCol = false;
-
- for (Iterator colIterator = displayOrderedColumns.iterator(); colIterator.hasNext(); )
- {
- GridColumn col = (GridColumn) colIterator.next();
- if (col.getColumnGroup() == overThis && col.isVisible())
- {
- firstCol = true;
- width += col.getWidth();
- }
- if (!firstCol && col.isVisible())
- {
- headerX += col.getWidth();
- }
- }
-
- overThis.getHeaderRenderer().setBounds(headerX - getHScrollSelectionInPixels(), 0, width,
- groupHeaderHeight);
- return overThis.getHeaderRenderer()
- .notify(IInternalWidget.LeftMouseButtonDown, new Point(x, y), overThis);
- }
-
- /**
- * Determines if a column header has been clicked, updates the renderer
- * state and triggers a redraw if necesary.
- *
- * @param x mouse x
- * @param y mouse y
- * @return true if this event has been consumed.
- */
- private boolean handleColumnHeaderPush(int x, int y)
- {
- if (!columnHeadersVisible)
- {
- return false;
- }
-
- GridColumn overThis = overColumnHeader(x, y);
-
- if (overThis == null)
- {
- return false;
- }
-
- columnBeingPushed = overThis;
-
- // draw pushed
- columnBeingPushed.getHeaderRenderer().setMouseDown(true);
- columnBeingPushed.getHeaderRenderer().setHover(true);
- pushingAndHovering = true;
- redraw();
-
- startHeaderPushX = x;
- pushingColumn = true;
-
- setCapture(true);
-
- return true;
- }
-
- private boolean handleColumnFooterPush(int x, int y)
- {
- if(!columnFootersVisible) {
- return false;
- }
-
- GridColumn overThis = overColumnFooter(x, y);
-
- if (overThis == null)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * Sets the new width of the column being resized and fires the appropriate
- * listeners.
- *
- * @param x mouse x
- */
- private void handleColumnResizerDragging(int x)
- {
- int newWidth = resizingColumnStartWidth + (x - resizingStartX);
- if (newWidth < MIN_COLUMN_HEADER_WIDTH)
- {
- newWidth = MIN_COLUMN_HEADER_WIDTH;
- }
-
- if (columnScrolling)
- {
- int maxWidth = getClientArea().width;
- if (rowHeaderVisible)
- maxWidth -= rowHeaderWidth;
- if (newWidth > maxWidth)
- newWidth = maxWidth;
- }
-
- if (newWidth == columnBeingResized.getWidth())
- {
- return;
- }
-
- columnBeingResized.setWidth(newWidth,false);
- scrollValuesObsolete = true;
-
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- columnBeingResized.fireResized();
-
- for (int index = displayOrderedColumns.indexOf(columnBeingResized) + 1; index < displayOrderedColumns.size(); index ++)
- {
- GridColumn col = (GridColumn)displayOrderedColumns.get(index);
- if (col.isVisible()) col.fireMoved();
- }
- }
- /**
- * Sets the new height of the item of the row being resized and fires the appropriate
- * listeners.
- *
- * @param x mouse x
- */
- private void handleRowResizerDragging(int y)
- {
- int newHeight = resizingRowStartHeight + (y - resizingStartY);
- if (newHeight < MIN_ROW_HEADER_HEIGHT)
- {
- newHeight = MIN_ROW_HEADER_HEIGHT;
- }
-
- if (newHeight > getClientArea().height)
- {
- newHeight = getClientArea().height;
- }
-
- if (newHeight == rowBeingResized.getHeight())
- {
- return;
- }
-
- Event e = new Event();
- e.item = rowBeingResized;
- e.widget = this;
- e.detail = newHeight;
-
- rowBeingResized.notifyListeners(SWT.Resize, e);
-
- if (e.doit == false)
- return;
-
- newHeight = e.detail;
-
- if (newHeight < MIN_ROW_HEADER_HEIGHT)
- {
- newHeight = MIN_ROW_HEADER_HEIGHT;
- }
-
- if (newHeight > getClientArea().height)
- {
- newHeight = getClientArea().height;
- }
-
- rowBeingResized.setHeight(newHeight);
- scrollValuesObsolete = true;
-
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
- }
-
- /**
- * Determines if the mouse is hovering on a column resizer and changes the
- * pointer and sets field appropriately.
- *
- * @param x mouse x
- * @param y mouse y
- * @return true if this event has been consumed.
- */
- private boolean handleHoverOnColumnResizer(int x, int y)
- {
- boolean over = false;
- if (y <= headerHeight)
- {
- int x2 = 0;
-
- if (rowHeaderVisible)
- {
- x2 += rowHeaderWidth;
- }
-
- x2 -= getHScrollSelectionInPixels();
-
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnIterator.next();
- if (!column.isVisible())
- {
- continue;
- }
- x2 += column.getWidth();
-
- if (x2 >= (x - COLUMN_RESIZER_THRESHOLD) && x2 <= (x + COLUMN_RESIZER_THRESHOLD))
- {
- if (column.getResizeable())
- {
- if (column.getColumnGroup() != null && y <= groupHeaderHeight)
- {
- // if this is not the last column
- if (column != column.getColumnGroup().getLastVisibleColumn())
- {
- break;
- }
- }
-
- over = true;
- columnBeingResized = column;
- }
- break;
- }
- }
- }
-
- if (over != hoveringOnColumnResizer)
- {
- if (over)
- {
- setCursor(getDisplay().getSystemCursor(SWT.CURSOR_SIZEWE));
- }
- else
- {
- columnBeingResized = null;
- setCursor(null);
- }
- hoveringOnColumnResizer = over;
- }
- return over;
- }
-
- /**
- * Determines if the mouse is hovering on a row resizer and changes the
- * pointer and sets field appropriately.
- *
- * @param x mouse x
- * @param y mouse y
- * @return true if this event has been consumed.
- */
- private boolean handleHoverOnRowResizer(int x, int y)
- {
- rowBeingResized = null;
- boolean over = false;
- if (x <= rowHeaderWidth)
- {
- int y2 = 0;
-
- if (columnHeadersVisible)
- {
- y2 += headerHeight;
- }
-
- int row=getTopIndex();
- while(row<items.size() && y2<=getClientArea().height)
- {
- GridItem currItem = (GridItem)items.get(row);
- if (currItem.isVisible())
- {
- y2 += currItem.getHeight() +1;
-
- if (y2 >= (y - ROW_RESIZER_THRESHOLD) && y2 <= (y + ROW_RESIZER_THRESHOLD))
- {
-// if (currItem.isResizeable())
- {
- over = true;
- rowBeingResized = currItem;
- }
- // do not brake here, because in case of overlapping
- // row resizers we need to find the last one
- }
- else
- {
- if(rowBeingResized != null)
- {
- // we have passed all (overlapping) row resizers, so break
- break;
- }
- }
- }
- row++;
- }
- }
-
- if (over != hoveringOnRowResizer)
- {
- if (over)
- {
- setCursor(getDisplay().getSystemCursor(SWT.CURSOR_SIZENS));
- }
- else
- {
- rowBeingResized = null;
- setCursor(null);
- }
- hoveringOnRowResizer = over;
- }
- return over;
- }
-
- /**
- * Returns the cell at the given point in the receiver or null if no such
- * cell exists. The point is in the coordinate system of the receiver.
- *
- * @param point the point used to locate the item
- * @return the cell at the given point
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public Point getCell(Point point)
- {
- checkWidget();
-
- if (point == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- if (point.x < 0 || point.x > getClientArea().width) return null;
-
- GridItem item = getItem(point);
- GridColumn column = getColumn(point);
-
- if (item!=null && column!=null)
- {
- return new Point(columns.indexOf(column),items.indexOf(item));
- }
- else
- {
- return null;
- }
- }
-
- /**
- * Paints.
- *
- * @param e paint event
- */
- private void onPaint(PaintEvent e)
- {
- int insertMarkPosX1 = -1; // we will populate these values while drawing the cells
- int insertMarkPosX2 = -1;
- int insertMarkPosY = -1;
- boolean insertMarkPosFound = false;
-
- GridCellSpanManager cellSpanManager = new GridCellSpanManager();
-
- e.gc.setBackground(getBackground());
- this.drawBackground(e.gc,0,0,getSize().x,getSize().y);
-
- if (scrollValuesObsolete)
- {
- updateScrollbars();
- scrollValuesObsolete = false;
- }
-
- int x = 0;
- int y = 0;
-
- if (columnHeadersVisible)
- {
- paintHeader(e.gc);
- y += headerHeight;
- }
-
- int availableHeight = getClientArea().height-y;
- int visibleRows = availableHeight / getItemHeight() + 1;
- if (items.size()>0 && availableHeight>0)
- {
- RowRange range = getRowRange(getTopIndex(),availableHeight,false,false);
- if (range.height >= availableHeight)
- visibleRows = range.rows;
- else
- visibleRows = range.rows + (availableHeight-range.height) / getItemHeight() + 1;
- }
-
- int firstVisibleIndex = getTopIndex();
- int firstItemToDraw = firstVisibleIndex;
-
- if(hasSpanning) {
- // We need to find the first Item to draw. An earlier item can row-span the first visible item.
- for(int rowIndex = 0; rowIndex < firstVisibleIndex; rowIndex++)
- {
- GridItem itemForRow = (GridItem)items.get(rowIndex);
- int colIndex = 0;
-
- int maxRowSpanForItem = 0;
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnIterator.next();
-
- if (!column.isVisible())
- {
- colIndex++;
- continue;
- }
-
- int rowSpan = itemForRow.getRowSpan(colIndex);
- maxRowSpanForItem = rowSpan > maxRowSpanForItem ? rowSpan : maxRowSpanForItem;
- colIndex++;
- }
-
- if(rowIndex + maxRowSpanForItem >= firstVisibleIndex) {
- firstItemToDraw = rowIndex;
- break;
- } else {
- rowIndex += maxRowSpanForItem;
- }
- }
-
- for(int rowIndex = firstItemToDraw; rowIndex < firstVisibleIndex; rowIndex++)
- {
- GridItem itemForRow = (GridItem)items.get(rowIndex);
- y = y - itemForRow.getHeight() - 1;
- }
- }
-
- int row = firstItemToDraw;
-
- for (int i = 0; i < visibleRows + (firstVisibleIndex - firstItemToDraw); i++)
- {
-
- x = 0;
-
- x -= getHScrollSelectionInPixels();
-
- // get the item to draw
- GridItem item = null;
- if (row < items.size())
- {
- item = (GridItem)items.get(row);
-
- while (!item.isVisible() && row < items.size() - 1)
- {
- row++;
- item = (GridItem)items.get(row);
- }
- }
- if (item != null && !item.isVisible())
- {
- item = null;
- }
-
- if (item != null)
- {
- boolean cellInRowSelected = false;
-
-
- if (rowHeaderVisible)
- {
-
- // row header is actually painted later
- x += rowHeaderWidth;
- }
-
- int focusY = y;
-
- int colIndex = 0;
-
- // draw regular cells for each column
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
- {
-
- GridColumn column = (GridColumn) columnIterator.next();
- boolean skipCell = cellSpanManager.skipCell(colIndex, row);
+ redraw();
+ }
+
+ /**
+ * Sets the row header renderer.
+ *
+ * @param rowHeaderRenderer The rowHeaderRenderer to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setRowHeaderRenderer(IRenderer rowHeaderRenderer) {
+ checkWidget();
+ rowHeaderRenderer.setDisplay(getDisplay());
+ this.rowHeaderRenderer = rowHeaderRenderer;
+ }
+
+ /**
+ * Marks the receiver's row header as visible if the argument is
+ * {@code true}, and marks it invisible otherwise. When row headers are
+ * visible, horizontal scrolling is always done by column rather than by
+ * pixel.
+ *
+ * @param show the new visibility state
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setRowHeaderVisible(boolean show) {
+ checkWidget();
+ this.rowHeaderVisible = show;
+ setColumnScrolling(true);
+
+ if (show && isAutoWidth()) {
+ rowHeaderWidth = 1;
+
+ for (Iterator iter = items.iterator(); iter.hasNext();) {
+ GridItem iterItem = (GridItem) iter.next();
+ rowHeaderWidth = Math.max(rowHeaderWidth,
+ rowHeaderRenderer.computeSize(sizingGC, SWT.DEFAULT, SWT.DEFAULT, iterItem).x);
+ }
+ }
+
+ redraw();
+ }
+
+ /**
+ * Selects the item at the given zero-relative index in the receiver. The
+ * current selection is first cleared, then the new item is selected.
+ * <p>
+ * If cell selection is enabled, all cells within the item at the given index
+ * are selected.
+ *
+ * @param index the index of the item to select
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setSelection(int index) {
+ checkWidget();
+
+ if (!selectionEnabled)
+ return;
+
+ if (index >= 0 && index < items.size()) {
+ if (!cellSelectionEnabled) {
+ selectedItems.clear();
+ selectedItems.add(items.get(index));
+ redraw();
+ }
+ else {
+ selectedCells.clear();
+ selectCells(getCells((GridItem) items.get(index)));
+ }
+ }
+ }
+
+ /**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive. The current
+ * selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end. If the receiver is single-select and there
+ * is more than one item in the given range, then all indices are ignored.
+ * <p>
+ * If cell selection is enabled, all cells within the given range are selected.
+ *
+ * @param start the start index of the items to select
+ * @param end the end index of the items to select
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see Grid#deselectAll()
+ * @see Grid#select(int,int)
+ */
+ public void setSelection(int start, int end) {
+ checkWidget();
+
+ if (!selectionEnabled)
+ return;
+
+ if (selectionType == SWT.SINGLE && start != end)
+ return;
+
+ if (!cellSelectionEnabled) {
+ selectedItems.clear();
+ }
+ else {
+ selectedCells.clear();
+ }
+
+ for (int i = start; i <= end; i++) {
+ if (i < 0) {
+ continue;
+ }
+ if (i > items.size() - 1) {
+ break;
+ }
+
+ GridItem item = (GridItem) items.get(i);
+
+ if (!cellSelectionEnabled) {
+ selectedItems.add(item);
+ }
+ else {
+ selectCells(getCells(item));
+ }
+ }
+ redraw();
+ }
+
+ /**
+ * Selects the items at the given zero-relative indices in the receiver. The
+ * current selection is cleared before the new items are selected.
+ * <p>
+ * 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.
+ * <p>
+ * If cell selection is enabled, all cells within the given indices are selected.
+ *
+ * @param indices the indices of the items to select
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of indices is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see Grid#deselectAll()
+ * @see Grid#select(int[])
+ */
+ public void setSelection(int[] indices) {
+ checkWidget();
+
+ if (!selectionEnabled)
+ return;
+
+ if (selectionType == SWT.SINGLE && indices.length > 1)
+ return;
+
+ if (!cellSelectionEnabled) {
+ selectedItems.clear();
+ }
+ else {
+ selectedCells.clear();
+ }
+
+ for (int i = 0; i < indices.length; i++) {
+ int j = indices[i];
+
+ if (j < 0) {
+ continue;
+ }
+ if (j > items.size() - 1) {
+ break;
+ }
+
+ GridItem item = (GridItem) items.get(j);
+
+ if (!cellSelectionEnabled) {
+ selectedItems.add(item);
+ }
+ else {
+ selectCells(getCells(item));
+ }
+ }
+ redraw();
+ }
+
+ /**
+ * Sets the receiver's selection to be the given array of items. The current
+ * selection is cleared before the new items are selected.
+ * <p>
+ * 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. If cell selection is enabled, all cells within the given items
+ * are selected.
+ *
+ * @param _items the array of items
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the array of items is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ * @see Grid#deselectAll()
+ * @see Grid#select(int[])
+ * @see Grid#setSelection(int[])
+ */
+ public void setSelection(GridItem[] _items) {
+ checkWidget();
+
+ if (!selectionEnabled)
+ return;
+
+ if (_items == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ if (selectionType == SWT.SINGLE && _items.length > 1)
+ return;
+
+ if (!cellSelectionEnabled) {
+ selectedItems.clear();
+ }
+ else {
+ selectedCells.clear();
+ }
+
+ for (int i = 0; i < _items.length; i++) {
+ GridItem item = _items[i];
+ if (item == null)
+ continue;
+ if (item.isDisposed())
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (item.getParent() != this)
+ continue;
+
+ if (!cellSelectionEnabled) {
+ selectedItems.add(item);
+ }
+ else {
+ selectCells(getCells(item));
+ }
+ }
+
+ redraw();
+ }
+
+ /**
+ * Sets the zero-relative index of the item which is currently at the top of
+ * the receiver. This index can change when items are scrolled or new items
+ * are added and removed.
+ *
+ * @param index the index of the top item
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setTopIndex(int index) {
+ checkWidget();
+ if (index < 0 || index >= items.size()) {
+ return;
+ }
+
+ GridItem item = (GridItem) items.get(index);
+ if (!item.isVisible()) {
+ return;
+ }
+
+ if (!vScroll.getVisible()) {
+ return;
+ }
+
+ int vScrollAmount = 0;
+
+ for (int i = 0; i < index; i++) {
+ if (((GridItem) items.get(i)).isVisible()) {
+ vScrollAmount++;
+ }
+ }
+
+ vScroll.setSelection(vScrollAmount);
+ topIndex = -1;
+ bottomIndex = -1;
+ redraw();
+ }
+
+ /**
+ * Sets the top left renderer.
+ *
+ * @param topLeftRenderer The topLeftRenderer to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setTopLeftRenderer(IRenderer topLeftRenderer) {
+ checkWidget();
+ topLeftRenderer.setDisplay(getDisplay());
+ this.topLeftRenderer = topLeftRenderer;
+ }
+
+ /**
+ * Sets the bottom left renderer.
+ *
+ * @param bottomLeftRenderer The topLeftRenderer to set.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setBottomLeftRenderer(IRenderer bottomLeftRenderer) {
+ checkWidget();
+ bottomLeftRenderer.setDisplay(getDisplay());
+ this.bottomLeftRenderer = bottomLeftRenderer;
+ }
+
+ /**
+ * Shows the column. If the column is already showing in the receiver, this
+ * method simply returns. Otherwise, the columns are scrolled until the
+ * column is visible.
+ *
+ * @param col the column to be shown
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void showColumn(GridColumn col) {
+ checkWidget();
+
+ if (!col.isVisible()) {
+ GridColumnGroup group = col.getColumnGroup();
+ group.setExpanded(!group.getExpanded());
+ if (group.getExpanded()) {
+ group.notifyListeners(SWT.Expand, new Event());
+ }
+ else {
+ group.notifyListeners(SWT.Collapse, new Event());
+ }
+ }
+
+ if (!hScroll.getVisible()) {
+ return;
+ }
+
+ int x = getColumnHeaderXPosition(col);
+
+ int firstVisibleX = 0;
+ if (rowHeaderVisible) {
+ firstVisibleX = rowHeaderWidth;
+ }
+
+ // if its visible just return
+ if (x >= firstVisibleX && (x + col.getWidth()) <= (firstVisibleX + (getClientArea().width - firstVisibleX))) {
+ return;
+ }
+
+ if (!getColumnScrolling()) {
+ if (x < firstVisibleX) {
+ hScroll.setSelection(getHScrollSelectionInPixels() - (firstVisibleX - x));
+ }
+ else {
+ if (col.getWidth() > getClientArea().width - firstVisibleX) {
+ hScroll.setSelection(getHScrollSelectionInPixels() + (x - firstVisibleX));
+ }
+ else {
+ x -= getClientArea().width - firstVisibleX - col.getWidth();
+ hScroll.setSelection(getHScrollSelectionInPixels() + (x - firstVisibleX));
+ }
+ }
+ }
+ else {
+ if (x < firstVisibleX || col.getWidth() > getClientArea().width - firstVisibleX) {
+ int sel = displayOrderedColumns.indexOf(col);
+ hScroll.setSelection(sel);
+ }
+ else {
+ int availableWidth = getClientArea().width - firstVisibleX - col.getWidth();
+
+ GridColumn prevCol = getPreviousVisibleColumn(col);
+ GridColumn currentScrollTo = col;
+
+ while (true) {
+ if (prevCol == null || prevCol.getWidth() > availableWidth) {
+ int sel = displayOrderedColumns.indexOf(currentScrollTo);
+ hScroll.setSelection(sel);
+ break;
+ }
+ else {
+ availableWidth -= prevCol.getWidth();
+ currentScrollTo = prevCol;
+ prevCol = getPreviousVisibleColumn(prevCol);
+ }
+ }
+ }
+ }
+
+ redraw();
+ }
+
+ /**
+ * Returns true if 'item' is currently being <em>completely</em>
+ * shown in this <code>Grid</code>'s visible on-screen area.
+ *
+ * <p>Here, "completely" only refers to the item's height, not its
+ * width. This means this method returns true also if some cells
+ * are horizontally scrolled away.
+ *
+ * @param item
+ * @return true if 'item' is shown
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * <li>ERROR_INVALID_ARGUMENT - if 'item' is not contained in the receiver</li>
+ * </ul>
+ */
+ boolean isShown(GridItem item) {
+ checkWidget();
+
+ if (!item.isVisible())
+ return false;
+
+ int itemIndex = items.indexOf(item);
+
+ if (itemIndex == -1)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ int firstVisibleIndex = getTopIndex();
+ int lastVisibleIndex = getBottomIndex();
+
+ return (itemIndex >= firstVisibleIndex && itemIndex < lastVisibleIndex)
+ || (itemIndex == lastVisibleIndex && bottomIndexShownCompletely);
+ }
+
+ /**
+ * 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
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * <li>ERROR_INVALID_ARGUMENT - if 'item' is not contained in the receiver</li>
+ * </ul>
+ */
+ public void showItem(GridItem item) {
+ checkWidget();
+
+ updateScrollbars();
+
+ // if no items are visible on screen then abort
+ if (getVisibleGridHeight() < 1) {
+ return;
+ }
+
+ // if its visible just return
+ if (isShown(item)) {
+ return;
+ }
+
+ if (!item.isVisible()) {
+ GridItem parent = item.getParentItem();
+ do {
+ if (!parent.isExpanded()) {
+ parent.setExpanded(true);
+ parent.fireEvent(SWT.Expand);
+ }
+ parent = parent.getParentItem();
+ }
+ while (parent != null);
+ }
+
+ int newTopIndex = items.indexOf(item);
+
+ if (newTopIndex >= getBottomIndex()) {
+ RowRange range = getRowRange(newTopIndex, getVisibleGridHeight(), true, true); // note: inverse==true
+ newTopIndex = range.startIndex; // note: use startIndex because of inverse==true
+ }
+
+ setTopIndex(newTopIndex);
+ }
+
+ /**
+ * 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.
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void showSelection() {
+ checkWidget();
+
+ if (scrollValuesObsolete)
+ updateScrollbars();
+
+ GridItem item = null;
+
+ if (!cellSelectionEnabled) {
+ if (selectedItems.size() == 0) {
+ return;
+ }
+
+ item = (GridItem) selectedItems.get(0);
+ showItem(item);
+ }
+ else {
+ if (selectedCells.size() == 0)
+ return;
+
+ Point cell = (Point) selectedCells.get(0);
+ item = getItem(cell.y);
+ showItem(item);
+ GridColumn col = getColumn(cell.x);
+ showColumn(col);
+ }
+
+ }
+
+ /**
+ * Enables selection highlighting if the argument is <code>true</code>.
+ *
+ * @param selectionEnabled the selection enabled state
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setSelectionEnabled(boolean selectionEnabled) {
+ checkWidget();
+
+ if (!selectionEnabled) {
+ selectedItems.clear();
+ redraw();
+ }
+
+ this.selectionEnabled = selectionEnabled;
+ }
+
+ /**
+ * Returns <code>true</code> if selection is enabled, false otherwise.
+ *
+ * @return the selection enabled state
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean getSelectionEnabled() {
+ checkWidget();
+ return selectionEnabled;
+ }
+
+ /**
+ * Computes and sets the height of the header row. This method will ask for
+ * the preferred size of all the column headers and use the max.
+ *
+ * @param gc GC for font metrics, etc.
+ */
+ private void computeHeaderHeight(GC gc) {
+
+ int colHeaderHeight = 0;
+ for (Iterator columnsIterator = columns.iterator(); columnsIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnsIterator.next();
+ colHeaderHeight = Math.max(
+ column.getHeaderRenderer().computeSize(gc, column.getWidth(), SWT.DEFAULT, column).y,
+ colHeaderHeight);
+ }
+
+ int groupHeight = 0;
+ for (int groupIndex = 0; groupIndex < columnGroups.length; groupIndex++) {
+ GridColumnGroup group = columnGroups[groupIndex];
+ groupHeight = Math.max(group.getHeaderRenderer().computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, group).y,
+ groupHeight);
+ }
+
+ headerHeight = colHeaderHeight + groupHeight;
+ groupHeaderHeight = groupHeight;
+ }
+
+ private void computeFooterHeight(GC gc) {
+
+ int colFooterHeight = 0;
+ for (Iterator columnsIterator = columns.iterator(); columnsIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnsIterator.next();
+ colFooterHeight = Math.max(
+ column.getFooterRenderer().computeSize(gc, column.getWidth(), SWT.DEFAULT, column).y,
+ colFooterHeight);
+ }
+
+ footerHeight = colFooterHeight;
+ }
+
+ /**
+ * Returns the computed default item height. Currently this method just gets the
+ * preferred size of all the cells in the given row and returns that (it is
+ * then used as the height of all rows with items having a height of -1).
+ *
+ * @param item item to use for sizing
+ * @param gc GC used to perform font metrics,etc.
+ * @return the row height
+ */
+ private int computeItemHeight(GridItem item, GC gc) {
+ int height = 1;
+
+ if (columns.size() == 0 || items.size() == 0) {
+ return height;
+ }
+
+ for (Iterator columnsIterator = columns.iterator(); columnsIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnsIterator.next();
+ column.getCellRenderer().setColumn(indexOf(column));
+ height = Math.max(height, column.getCellRenderer().computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, item).y);
+ }
+
+ if (rowHeaderVisible && rowHeaderRenderer != null) {
+ height = Math.max(height, rowHeaderRenderer.computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, item).y);
+ }
+
+ return height <= 0 ? 16 : height;
+ }
+
+ /**
+ * Returns the x position of the given column. Takes into account scroll
+ * position.
+ *
+ * @param column given column
+ * @return x position
+ */
+ private int getColumnHeaderXPosition(GridColumn column) {
+ if (!column.isVisible()) {
+ return -1;
+ }
+
+ int x = 0;
+
+ x -= getHScrollSelectionInPixels();
+
+ if (rowHeaderVisible) {
+ x += rowHeaderWidth;
+ }
+ for (Iterator column2Iterator = displayOrderedColumns.iterator(); column2Iterator.hasNext();) {
+ GridColumn column2 = (GridColumn) column2Iterator.next();
+
+ if (!column2.isVisible()) {
+ continue;
+ }
+
+ if (column2 == column) {
+ break;
+ }
+
+ x += column2.getWidth();
+ }
+
+ return x;
+ }
+
+ /**
+ * Returns the hscroll selection in pixels. This method abstracts away the
+ * differences between column by column scrolling and pixel based scrolling.
+ *
+ * @return the horizontal scroll selection in pixels
+ */
+ private int getHScrollSelectionInPixels() {
+ int selection = hScroll.getSelection();
+ if (columnScrolling) {
+ int pixels = 0;
+ for (int i = 0; i < selection; i++) {
+ pixels += ((GridColumn) displayOrderedColumns.get(i)).getWidth();
+ }
+ selection = pixels;
+ }
+ return selection;
+ }
+
+ /**
+ * Returns the size of the preferred size of the inner table.
+ *
+ * @return the preferred size of the table.
+ */
+ private Point getTableSize() {
+ int x = 0;
+ int y = 0;
+
+ if (columnHeadersVisible) {
+ y += headerHeight;
+ }
+
+ if (columnFootersVisible) {
+ y += footerHeight;
+ }
+
+ y += getGridHeight();
+
+ if (rowHeaderVisible) {
+ x += rowHeaderWidth;
+ }
+
+ for (Iterator columnIterator = columns.iterator(); columnIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnIterator.next();
+ if (column.isVisible()) {
+ x += column.getWidth();
+ }
+ }
+
+ return new Point(x, y);
+ }
+
+ /**
+ * Manages the header column dragging and calculates the drop point,
+ * triggers a redraw.
+ *
+ * @param x mouse x
+ * @return true if this event has been consumed.
+ */
+ private boolean handleColumnDragging(int x) {
+
+ GridColumn local_dragDropBeforeColumn = null;
+ GridColumn local_dragDropAfterColumn = null;
+
+ int x2 = 1;
+
+ if (rowHeaderVisible) {
+ x2 += rowHeaderWidth + 1;
+ }
+
+ x2 -= getHScrollSelectionInPixels();
+
+ int i = 0;
+ GridColumn previousVisibleCol = null;
+ boolean nextVisibleColumnIsBeforeCol = false;
+ GridColumn firstVisibleCol = null;
+ GridColumn lastVisibleCol = null;
+
+ if (x < x2) {
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnIterator.next();
+ if (!column.isVisible()) {
+ continue;
+ }
+ local_dragDropBeforeColumn = column;
+ break;
+ }
+ local_dragDropAfterColumn = null;
+ }
+ else {
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnIterator.next();
+ if (!column.isVisible()) {
+ continue;
+ }
+
+ i++;
+
+ if (firstVisibleCol == null) {
+ firstVisibleCol = column;
+ }
+ lastVisibleCol = column;
+
+ if (nextVisibleColumnIsBeforeCol) {
+ local_dragDropBeforeColumn = column;
+ nextVisibleColumnIsBeforeCol = false;
+ }
+
+ if (x >= x2 && x <= (x2 + column.getWidth())) {
+ if (x <= (x2 + column.getWidth() / 2)) {
+ local_dragDropBeforeColumn = column;
+ local_dragDropAfterColumn = previousVisibleCol;
+ }
+ else {
+ local_dragDropAfterColumn = column;
+
+ // the next visible column is the before col
+ nextVisibleColumnIsBeforeCol = true;
+ }
+ }
+
+ x2 += column.getWidth();
+ previousVisibleCol = column;
+ }
+
+ if (local_dragDropBeforeColumn == null) {
+ local_dragDropAfterColumn = lastVisibleCol;
+ }
+ }
+
+ currentHeaderDragX = x;
+
+ if (local_dragDropBeforeColumn != dragDropBeforeColumn
+ || (dragDropBeforeColumn == null && dragDropAfterColumn == null)) {
+ dragDropPointValid = true;
+
+ // Determine if valid drop point
+ if (columnGroups.length != 0) {
+
+ if (columnBeingPushed.getColumnGroup() == null) {
+ if (local_dragDropBeforeColumn != null
+ && local_dragDropAfterColumn != null
+ && local_dragDropBeforeColumn.getColumnGroup() != null
+ && local_dragDropBeforeColumn.getColumnGroup() == local_dragDropAfterColumn
+ .getColumnGroup()) {
+ // Dont move a column w/o a group in between two columns
+ // in the same group
+ dragDropPointValid = false;
+ }
+ }
+ else {
+ if (!(local_dragDropBeforeColumn != null && local_dragDropBeforeColumn.getColumnGroup() == columnBeingPushed
+ .getColumnGroup())
+ && !(local_dragDropAfterColumn != null && local_dragDropAfterColumn.getColumnGroup() == columnBeingPushed
+ .getColumnGroup())) {
+ // Dont move a column with a group
+ dragDropPointValid = false;
+ }
+ }
+ }
+ else {
+ dragDropPointValid = true;
+ }
+ }
+
+ dragDropBeforeColumn = local_dragDropBeforeColumn;
+ dragDropAfterColumn = local_dragDropAfterColumn;
+
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ return true;
+ }
+
+ /**
+ * Handles the moving of columns after a column is dropped.
+ */
+ private void handleColumnDrop() {
+ draggingColumn = false;
+
+ if ((dragDropBeforeColumn != columnBeingPushed && dragDropAfterColumn != columnBeingPushed)
+ && (columnGroups.length == 0 || dragDropPointValid)) {
+
+ int notifyFrom = displayOrderedColumns.indexOf(columnBeingPushed);
+ int notifyTo = notifyFrom;
+
+ displayOrderedColumns.remove(columnBeingPushed);
+
+ if (dragDropBeforeColumn == null) {
+
+ notifyTo = displayOrderedColumns.size();
+ displayOrderedColumns.add(columnBeingPushed);
+ }
+ else if (dragDropAfterColumn == null) {
+ displayOrderedColumns.add(0, columnBeingPushed);
+ notifyFrom = 0;
+ }
+ else {
+ int insertAtIndex = 0;
+
+ if (columnGroups.length != 0) {
+ // ensure that we aren't putting this column into a group,
+ // this is possible if
+ // there are invisible columns between the after and before
+ // cols
+
+ if (dragDropBeforeColumn.getColumnGroup() == columnBeingPushed.getColumnGroup()) {
+ insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
+ }
+ else if (dragDropAfterColumn.getColumnGroup() == columnBeingPushed.getColumnGroup()) {
+ insertAtIndex = displayOrderedColumns.indexOf(dragDropAfterColumn) + 1;
+ }
+ else {
+ if (dragDropBeforeColumn.getColumnGroup() == null) {
+ insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
+ }
+ else {
+ GridColumnGroup beforeGroup = dragDropBeforeColumn.getColumnGroup();
+ insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
+ while (insertAtIndex > 0
+ && ((GridColumn) displayOrderedColumns.get(insertAtIndex - 1)).getColumnGroup() == beforeGroup) {
+ insertAtIndex--;
+ }
+
+ }
+ }
+ }
+ else {
+ insertAtIndex = displayOrderedColumns.indexOf(dragDropBeforeColumn);
+ }
+ displayOrderedColumns.add(insertAtIndex, columnBeingPushed);
+ notifyFrom = Math.min(notifyFrom, insertAtIndex);
+ notifyTo = Math.max(notifyTo, insertAtIndex);
+ }
+
+ for (int i = notifyFrom; i <= notifyTo; i++) {
+ ((GridColumn) displayOrderedColumns.get(i)).fireMoved();
+ }
+ }
+
+ redraw();
+ }
+
+ /**
+ * Determines if the mouse is pushing the header but has since move out of
+ * the header bounds and therefore should be drawn unpushed. Also initiates
+ * a column header drag when appropriate.
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return true if this event has been consumed.
+ */
+ private boolean handleColumnHeaderHoverWhilePushing(int x, int y) {
+ GridColumn overThis = overColumnHeader(x, y);
+
+ if ((overThis == columnBeingPushed) != pushingAndHovering) {
+ pushingAndHovering = (overThis == columnBeingPushed);
+ redraw();
+ }
+ if (columnBeingPushed.getMoveable()) {
+
+ if (pushingAndHovering && Math.abs(startHeaderPushX - x) > 3) {
+
+ // stop pushing
+ pushingColumn = false;
+ columnBeingPushed.getHeaderRenderer().setMouseDown(false);
+ columnBeingPushed.getHeaderRenderer().setHover(false);
+
+ // now dragging
+ draggingColumn = true;
+ columnBeingPushed.getHeaderRenderer().setMouseDown(false);
+
+ startHeaderDragX = x;
+
+ dragDropAfterColumn = null;
+ dragDropBeforeColumn = null;
+ dragDropPointValid = true;
+
+ handleColumnDragging(x);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Determines if a column group header has been clicked and forwards the
+ * event to the header renderer.
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return true if this event has been consumed.
+ */
+ private boolean handleColumnGroupHeaderClick(int x, int y) {
+
+ if (!columnHeadersVisible) {
+ return false;
+ }
+
+ GridColumnGroup overThis = overColumnGroupHeader(x, y);
+
+ if (overThis == null) {
+ return false;
+ }
+
+ int headerX = 0;
+ if (rowHeaderVisible) {
+ headerX += rowHeaderWidth;
+ }
+
+ int width = 0;
+ boolean firstCol = false;
+
+ for (Iterator colIterator = displayOrderedColumns.iterator(); colIterator.hasNext();) {
+ GridColumn col = (GridColumn) colIterator.next();
+ if (col.getColumnGroup() == overThis && col.isVisible()) {
+ firstCol = true;
+ width += col.getWidth();
+ }
+ if (!firstCol && col.isVisible()) {
+ headerX += col.getWidth();
+ }
+ }
+
+ overThis.getHeaderRenderer().setBounds(headerX - getHScrollSelectionInPixels(), 0, width, groupHeaderHeight);
+ return overThis.getHeaderRenderer().notify(IInternalWidget.LeftMouseButtonDown, new Point(x, y), overThis);
+ }
+
+ /**
+ * Determines if a column header has been clicked, updates the renderer
+ * state and triggers a redraw if necesary.
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return true if this event has been consumed.
+ */
+ private boolean handleColumnHeaderPush(int x, int y) {
+ if (!columnHeadersVisible) {
+ return false;
+ }
+
+ GridColumn overThis = overColumnHeader(x, y);
+
+ if (overThis == null) {
+ return false;
+ }
+
+ columnBeingPushed = overThis;
+
+ // draw pushed
+ columnBeingPushed.getHeaderRenderer().setMouseDown(true);
+ columnBeingPushed.getHeaderRenderer().setHover(true);
+ pushingAndHovering = true;
+ redraw();
+
+ startHeaderPushX = x;
+ pushingColumn = true;
+
+ setCapture(true);
+
+ return true;
+ }
+
+ private boolean handleColumnFooterPush(int x, int y) {
+ if (!columnFootersVisible) {
+ return false;
+ }
+
+ GridColumn overThis = overColumnFooter(x, y);
+
+ if (overThis == null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the new width of the column being resized and fires the appropriate
+ * listeners.
+ *
+ * @param x mouse x
+ */
+ private void handleColumnResizerDragging(int x) {
+ int newWidth = resizingColumnStartWidth + (x - resizingStartX);
+ if (newWidth < MIN_COLUMN_HEADER_WIDTH) {
+ newWidth = MIN_COLUMN_HEADER_WIDTH;
+ }
+
+ if (columnScrolling) {
+ int maxWidth = getClientArea().width;
+ if (rowHeaderVisible)
+ maxWidth -= rowHeaderWidth;
+ if (newWidth > maxWidth)
+ newWidth = maxWidth;
+ }
+
+ if (newWidth == columnBeingResized.getWidth()) {
+ return;
+ }
+
+ columnBeingResized.setWidth(newWidth, false);
+ scrollValuesObsolete = true;
+
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ columnBeingResized.fireResized();
+
+ for (int index = displayOrderedColumns.indexOf(columnBeingResized) + 1; index < displayOrderedColumns.size(); index++) {
+ GridColumn col = (GridColumn) displayOrderedColumns.get(index);
+ if (col.isVisible())
+ col.fireMoved();
+ }
+ }
+
+ /**
+ * Sets the new height of the item of the row being resized and fires the appropriate
+ * listeners.
+ *
+ * @param x mouse x
+ */
+ private void handleRowResizerDragging(int y) {
+ int newHeight = resizingRowStartHeight + (y - resizingStartY);
+ if (newHeight < MIN_ROW_HEADER_HEIGHT) {
+ newHeight = MIN_ROW_HEADER_HEIGHT;
+ }
+
+ if (newHeight > getClientArea().height) {
+ newHeight = getClientArea().height;
+ }
+
+ if (newHeight == rowBeingResized.getHeight()) {
+ return;
+ }
+
+ Event e = new Event();
+ e.item = rowBeingResized;
+ e.widget = this;
+ e.detail = newHeight;
+
+ rowBeingResized.notifyListeners(SWT.Resize, e);
+
+ if (e.doit == false)
+ return;
+
+ newHeight = e.detail;
+
+ if (newHeight < MIN_ROW_HEADER_HEIGHT) {
+ newHeight = MIN_ROW_HEADER_HEIGHT;
+ }
+
+ if (newHeight > getClientArea().height) {
+ newHeight = getClientArea().height;
+ }
+
+ rowBeingResized.setHeight(newHeight);
+ scrollValuesObsolete = true;
+
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+ }
+
+ /**
+ * Determines if the mouse is hovering on a column resizer and changes the
+ * pointer and sets field appropriately.
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return true if this event has been consumed.
+ */
+ private boolean handleHoverOnColumnResizer(int x, int y) {
+ boolean over = false;
+ if (y <= headerHeight) {
+ int x2 = 0;
+
+ if (rowHeaderVisible) {
+ x2 += rowHeaderWidth;
+ }
+
+ x2 -= getHScrollSelectionInPixels();
+
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnIterator.next();
+ if (!column.isVisible()) {
+ continue;
+ }
+ x2 += column.getWidth();
+
+ if (x2 >= (x - COLUMN_RESIZER_THRESHOLD) && x2 <= (x + COLUMN_RESIZER_THRESHOLD)) {
+ if (column.getResizeable()) {
+ if (column.getColumnGroup() != null && y <= groupHeaderHeight) {
+ // if this is not the last column
+ if (column != column.getColumnGroup().getLastVisibleColumn()) {
+ break;
+ }
+ }
+
+ over = true;
+ columnBeingResized = column;
+ }
+ break;
+ }
+ }
+ }
+
+ if (over != hoveringOnColumnResizer) {
+ if (over) {
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_SIZEWE));
+ }
+ else {
+ columnBeingResized = null;
+ setCursor(null);
+ }
+ hoveringOnColumnResizer = over;
+ }
+ return over;
+ }
+
+ /**
+ * Determines if the mouse is hovering on a row resizer and changes the
+ * pointer and sets field appropriately.
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return true if this event has been consumed.
+ */
+ private boolean handleHoverOnRowResizer(int x, int y) {
+ rowBeingResized = null;
+ boolean over = false;
+ if (x <= rowHeaderWidth) {
+ int y2 = 0;
+
+ if (columnHeadersVisible) {
+ y2 += headerHeight;
+ }
+
+ int row = getTopIndex();
+ while (row < items.size() && y2 <= getClientArea().height) {
+ GridItem currItem = (GridItem) items.get(row);
+ if (currItem.isVisible()) {
+ y2 += currItem.getHeight() + 1;
+
+ if (y2 >= (y - ROW_RESIZER_THRESHOLD) && y2 <= (y + ROW_RESIZER_THRESHOLD)) {
+ // if (currItem.isResizeable())
+ {
+ over = true;
+ rowBeingResized = currItem;
+ }
+ // do not brake here, because in case of overlapping
+ // row resizers we need to find the last one
+ }
+ else {
+ if (rowBeingResized != null) {
+ // we have passed all (overlapping) row resizers, so break
+ break;
+ }
+ }
+ }
+ row++;
+ }
+ }
+
+ if (over != hoveringOnRowResizer) {
+ if (over) {
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_SIZENS));
+ }
+ else {
+ rowBeingResized = null;
+ setCursor(null);
+ }
+ hoveringOnRowResizer = over;
+ }
+ return over;
+ }
+
+ /**
+ * Returns the cell at the given point in the receiver or null if no such
+ * cell exists. The point is in the coordinate system of the receiver.
+ *
+ * @param point the point used to locate the item
+ * @return the cell at the given point
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public Point getCell(Point point) {
+ checkWidget();
+
+ if (point == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ if (point.x < 0 || point.x > getClientArea().width)
+ return null;
+
+ GridItem item = getItem(point);
+ GridColumn column = getColumn(point);
+
+ if (item != null && column != null) {
+ return new Point(columns.indexOf(column), items.indexOf(item));
+ }
+ else {
+ return null;
+ }
+ }
+
+ /**
+ * Paints.
+ *
+ * @param e paint event
+ */
+ private void onPaint(PaintEvent e) {
+ int insertMarkPosX1 = -1; // we will populate these values while drawing the cells
+ int insertMarkPosX2 = -1;
+ int insertMarkPosY = -1;
+ boolean insertMarkPosFound = false;
+
+ GridCellSpanManager cellSpanManager = new GridCellSpanManager();
+
+ e.gc.setBackground(getBackground());
+ this.drawBackground(e.gc, 0, 0, getSize().x, getSize().y);
+
+ if (scrollValuesObsolete) {
+ updateScrollbars();
+ scrollValuesObsolete = false;
+ }
+
+ int x = 0;
+ int y = 0;
+
+ if (columnHeadersVisible) {
+ paintHeader(e.gc);
+ y += headerHeight;
+ }
+
+ int availableHeight = getClientArea().height - y;
+ int visibleRows = availableHeight / getItemHeight() + 1;
+ if (items.size() > 0 && availableHeight > 0) {
+ RowRange range = getRowRange(getTopIndex(), availableHeight, false, false);
+ if (range.height >= availableHeight)
+ visibleRows = range.rows;
+ else
+ visibleRows = range.rows + (availableHeight - range.height) / getItemHeight() + 1;
+ }
+
+ int firstVisibleIndex = getTopIndex();
+ int firstItemToDraw = firstVisibleIndex;
+
+ if (hasSpanning) {
+ // We need to find the first Item to draw. An earlier item can row-span the first visible item.
+ for (int rowIndex = 0; rowIndex < firstVisibleIndex; rowIndex++) {
+ GridItem itemForRow = (GridItem) items.get(rowIndex);
+ int colIndex = 0;
+
+ int maxRowSpanForItem = 0;
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnIterator.next();
+
+ if (!column.isVisible()) {
+ colIndex++;
+ continue;
+ }
+
+ int rowSpan = itemForRow.getRowSpan(colIndex);
+ maxRowSpanForItem = rowSpan > maxRowSpanForItem ? rowSpan : maxRowSpanForItem;
+ colIndex++;
+ }
+
+ if (rowIndex + maxRowSpanForItem >= firstVisibleIndex) {
+ firstItemToDraw = rowIndex;
+ break;
+ }
+ else {
+ rowIndex += maxRowSpanForItem;
+ }
+ }
+
+ for (int rowIndex = firstItemToDraw; rowIndex < firstVisibleIndex; rowIndex++) {
+ GridItem itemForRow = (GridItem) items.get(rowIndex);
+ y = y - itemForRow.getHeight() - 1;
+ }
+ }
+
+ int row = firstItemToDraw;
+
+ for (int i = 0; i < visibleRows + (firstVisibleIndex - firstItemToDraw); i++) {
+
+ x = 0;
+
+ x -= getHScrollSelectionInPixels();
+
+ // get the item to draw
+ GridItem item = null;
+ if (row < items.size()) {
+ item = (GridItem) items.get(row);
+
+ while (!item.isVisible() && row < items.size() - 1) {
+ row++;
+ item = (GridItem) items.get(row);
+ }
+ }
+ if (item != null && !item.isVisible()) {
+ item = null;
+ }
+
+ if (item != null) {
+ boolean cellInRowSelected = false;
+
+ if (rowHeaderVisible) {
+
+ // row header is actually painted later
+ x += rowHeaderWidth;
+ }
+
+ int focusY = y;
+
+ int colIndex = 0;
+
+ // draw regular cells for each column
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+
+ GridColumn column = (GridColumn) columnIterator.next();
+ boolean skipCell = cellSpanManager.skipCell(colIndex, row);
int indexOfColumn = indexOf(column);
- if (!column.isVisible())
- {
- colIndex++;
- if(skipCell)
- {
- cellSpanManager.consumeCell(colIndex, row);
- }
- continue;
- }
-
- int width = item.getCellSize(indexOfColumn).x;
-
- if(skipCell == false)
- {
-
- int nrRowsToSpan = item.getRowSpan(indexOfColumn);
- int nrColumnsToSpan = item.getColumnSpan(indexOfColumn);
-
- if(nrRowsToSpan > 0 || nrColumnsToSpan > 0)
- {
- cellSpanManager.addCellSpanInfo(colIndex, row, nrColumnsToSpan, nrRowsToSpan);
- }
-
- if (x + width >= 0 && x < getClientArea().width )
- {
- Point sizeOfColumn = item.getCellSize(indexOfColumn);
-
- column.getCellRenderer().setBounds(x, y, width, sizeOfColumn.y);
- int cellInHeaderDelta = columnHeadersVisible ? headerHeight - y : 0;
- if(cellInHeaderDelta > 0)
- {
- e.gc.setClipping(new Rectangle(x -1,y + cellInHeaderDelta, width +1, sizeOfColumn.y + 2 - cellInHeaderDelta));
- }
- else
- {
- e.gc.setClipping(new Rectangle(x -1,y -1,width +1, sizeOfColumn.y + 2));
- }
-
- column.getCellRenderer().setRow(i + 1);
-
- column.getCellRenderer().setSelected(selectedItems.contains(item));
- column.getCellRenderer().setFocus(this.isFocusControl());
- column.getCellRenderer().setRowFocus(focusItem == item);
- column.getCellRenderer().setCellFocus(cellSelectionEnabled && focusItem == item && focusColumn == column);
-
- column.getCellRenderer().setRowHover(hoveringItem == item);
- column.getCellRenderer().setColumnHover(hoveringColumn == column);
-
- column.getCellRenderer().setColumn(indexOfColumn);
-
- if (selectedCells.contains(new Point(indexOfColumn,row)))
- {
- column.getCellRenderer().setCellSelected(true);
- cellInRowSelected = true;
- }
- else
- {
- column.getCellRenderer().setCellSelected(false);
- }
-
- if (hoveringItem == item && hoveringColumn == column)
- {
- column.getCellRenderer().setHoverDetail(hoveringDetail);
- }
- else
- {
- column.getCellRenderer().setHoverDetail("");
- }
-
- column.getCellRenderer().paint(e.gc, item);
-
- e.gc.setClipping((Rectangle)null);
-
- // collect the insertMark position
- if (!insertMarkPosFound && insertMarkItem == item && (insertMarkColumn == null || insertMarkColumn == column))
- {
- // y-pos
- insertMarkPosY = y - 1;
- if (!insertMarkBefore)
- insertMarkPosY += item.getHeight() + 1;
- // x1-pos
- insertMarkPosX1 = x;
- if (column.isTree())
- {
- insertMarkPosX1 += Math.min(
- width,
- column.getCellRenderer().getTextBounds(item, false).x);
- }
-
- // x2-pos
- if (insertMarkColumn == null)
- {
- insertMarkPosX2 = getClientArea().x + getClientArea().width;
- }
- else
- {
- insertMarkPosX2 = x + width;
- }
-
- insertMarkPosFound = true;
- }
- }
- }
- else
- {
- cellSpanManager.consumeCell(colIndex, row);
- }
-
- x += column.getWidth();
- colIndex++;
-
- }
-
- if (x < getClientArea().width)
- {
- // insertMarkPos needs correction
- if(insertMarkPosFound && insertMarkColumn == null)
- insertMarkPosX2 = x;
-
- emptyCellRenderer.setSelected(selectedItems.contains(item));
- emptyCellRenderer.setFocus(this.isFocusControl());
- emptyCellRenderer.setRow(i + 1);
- emptyCellRenderer.setBounds(x, y, getClientArea().width - x + 1, item.getHeight());
- emptyCellRenderer.setColumn(getColumnCount());
- emptyCellRenderer.paint(e.gc, item);
- }
-
- x = 0;
-
- if (rowHeaderVisible)
- {
-
- if (!cellSelectionEnabled)
- {
- rowHeaderRenderer.setSelected(selectedItems.contains(item));
- }
- else
- {
- rowHeaderRenderer.setSelected(cellInRowSelected);
- }
- if(y >= headerHeight)
- {
- rowHeaderRenderer.setBounds(0, y, rowHeaderWidth, item.getHeight() + 1);
- rowHeaderRenderer.paint(e.gc, item);
- }
- x += rowHeaderWidth;
- }
-
- // focus
- if (isFocusControl() && !cellSelectionEnabled)
- {
- if (item == focusItem)
- {
- if (focusRenderer != null)
- {
- int focusX = 0;
- if (rowHeaderVisible)
- {
- focusX = rowHeaderWidth;
- }
- focusRenderer
- .setBounds(focusX, focusY - 1, getClientArea().width - focusX - 1,
- item.getHeight() + 1);
- focusRenderer.paint(e.gc, item);
- }
- }
- }
-
- y += item.getHeight() + 1;
- }
- else
- {
-
- if (rowHeaderVisible)
- {
- //row header is actually painted later
- x += rowHeaderWidth;
- }
-
- emptyCellRenderer.setBounds(x, y, getClientArea().width - x, getItemHeight());
- emptyCellRenderer.setFocus(false);
- emptyCellRenderer.setSelected(false);
- emptyCellRenderer.setRow(i + 1);
-
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
- {
- GridColumn column = (GridColumn) columnIterator.next();
-
- if (column.isVisible())
- {
- emptyCellRenderer.setBounds(x, y, column.getWidth(), getItemHeight());
- emptyCellRenderer.setColumn(indexOf(column));
- emptyCellRenderer.paint(e.gc, this);
-
- x += column.getWidth();
- }
- }
-
- if (x < getClientArea().width)
- {
- emptyCellRenderer.setBounds(x, y, getClientArea().width - x + 1, getItemHeight());
- emptyCellRenderer.setColumn(getColumnCount());
- emptyCellRenderer.paint(e.gc, this);
- }
-
-
- x = 0;
-
- if (rowHeaderVisible)
- {
- emptyRowHeaderRenderer.setBounds(x, y, rowHeaderWidth, getItemHeight() + 1);
- emptyRowHeaderRenderer.paint(e.gc, this);
-
- x += rowHeaderWidth;
- }
-
- y += getItemHeight() + 1;
- }
-
- row++;
- }
-
- // draw drop point
- if (draggingColumn)
- {
- if ((dragDropAfterColumn != null || dragDropBeforeColumn != null)
- && (dragDropAfterColumn != columnBeingPushed && dragDropBeforeColumn != columnBeingPushed)
- && dragDropPointValid)
- {
- if (dragDropBeforeColumn != null)
- {
- x = getColumnHeaderXPosition(dragDropBeforeColumn);
- }
- else
- {
- x = getColumnHeaderXPosition(dragDropAfterColumn)
- + dragDropAfterColumn.getWidth();
- }
-
- Point size = dropPointRenderer.computeSize(e.gc, SWT.DEFAULT, SWT.DEFAULT, null);
- x -= size.x / 2;
- if (x < 0)
- {
- x = 0;
- }
- dropPointRenderer.setBounds(x - 1, headerHeight + DROP_POINT_LOWER_OFFSET, size.x,
- size.y);
- dropPointRenderer.paint(e.gc, null);
- }
- }
-
- // draw insertion mark
- if (insertMarkPosFound)
- {
- e.gc.setClipping(
- rowHeaderVisible ? rowHeaderWidth : 0,
- columnHeadersVisible ? headerHeight : 0,
- getClientArea().width,
- getClientArea().height);
- insertMarkRenderer.paint(e.gc, new Rectangle(insertMarkPosX1, insertMarkPosY, insertMarkPosX2 - insertMarkPosX1, 0));
- }
-
- if (columnFootersVisible)
- {
- paintFooter(e.gc);
- }
- }
-
- /**
- * Returns a column reference if the x,y coordinates are over a column
- * header (header only).
- *
- * @param x mouse x
- * @param y mouse y
- * @return column reference which mouse is over, or null.
- */
- private GridColumn overColumnHeader(int x, int y)
- {
- GridColumn col = null;
-
- if (y <= headerHeight && y > 0)
- {
- col = getColumn(new Point(x, y));
- if (col != null && col.getColumnGroup() != null)
- {
- if (y <= groupHeaderHeight)
- {
- return null;
- }
- }
- }
-
- return col;
- }
-
- /**
- * Returns a column reference if the x,y coordinates are over a column
- * header (header only).
- *
- * @param x mouse x
- * @param y mouse y
- * @return column reference which mouse is over, or null.
- */
- private GridColumn overColumnFooter(int x, int y)
- {
- GridColumn col = null;
-
- if (y >= getClientArea().height - footerHeight )
- {
- col = getColumn(new Point(x, y));
- }
-
- return col;
- }
-
- /**
- * Returns a column group reference if the x,y coordinates are over a column
- * group header (header only).
- *
- * @param x mouse x
- * @param y mouse y
- * @return column group reference which mouse is over, or null.
- */
- private GridColumnGroup overColumnGroupHeader(int x, int y)
- {
- GridColumnGroup group = null;
-
- if (y <= groupHeaderHeight && y > 0)
- {
- GridColumn col = getColumn(new Point(x, y));
- if (col != null)
- {
- group = col.getColumnGroup();
- }
- }
-
- return group;
- }
-
- /**
- * Paints the header.
- *
- * @param gc gc from paint event
- */
- private void paintHeader(GC gc)
- {
- int x = 0;
- int y = 0;
-
- x -= getHScrollSelectionInPixels();
-
- if (rowHeaderVisible)
- {
- // paint left corner
- // topLeftRenderer.setBounds(0, y, rowHeaderWidth, headerHeight);
- // topLeftRenderer.paint(gc, null);
- x += rowHeaderWidth;
- }
-
- GridColumnGroup previousPaintedGroup = null;
-
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); )
- {
- if (x > getClientArea().width)
- break;
-
- GridColumn column = (GridColumn) columnIterator.next();
- int height = 0;
-
- if (!column.isVisible())
- {
- continue;
- }
-
- if (column.getColumnGroup() != null)
- {
-
- if (column.getColumnGroup() != previousPaintedGroup)
- {
- int width = column.getWidth();
-
- GridColumn nextCol = null;
- if (displayOrderedColumns.indexOf(column) + 1 < displayOrderedColumns.size())
- {
- nextCol = (GridColumn)displayOrderedColumns
- .get(displayOrderedColumns.indexOf(column) + 1);
- }
-
- while (nextCol != null && nextCol.getColumnGroup() == column.getColumnGroup())
- {
-
- if ((nextCol.getColumnGroup().getExpanded() && !nextCol.isDetail())
- || (!nextCol.getColumnGroup().getExpanded() && !nextCol.isSummary()))
- {
- }
- else if( nextCol.isVisible() )
- {
- width += nextCol.getWidth();
- }
-
- if (displayOrderedColumns.indexOf(nextCol) + 1 < displayOrderedColumns
- .size())
- {
- nextCol = (GridColumn)displayOrderedColumns.get(displayOrderedColumns
- .indexOf(nextCol) + 1);
- }
- else
- {
- nextCol = null;
- }
- }
-
- boolean selected = true;
-
- for (int i = 0; i < column.getColumnGroup().getColumns().length; i++)
- {
- GridColumn col = column.getColumnGroup().getColumns()[i];
- if (col.isVisible() && (column.getMoveable() || !selectedColumns.contains(col)))
- {
- selected = false;
- break;
- }
- }
-
-
- column.getColumnGroup().getHeaderRenderer().setSelected(selected);
- column.getColumnGroup().getHeaderRenderer()
- .setHover(hoverColumnGroupHeader == column.getColumnGroup());
- column.getColumnGroup().getHeaderRenderer().setHoverDetail(hoveringDetail);
-
- column.getColumnGroup().getHeaderRenderer().setBounds(x, 0, width,
- groupHeaderHeight);
-
- column.getColumnGroup().getHeaderRenderer().paint(gc, column.getColumnGroup());
-
- previousPaintedGroup = column.getColumnGroup();
- }
-
- height = headerHeight - groupHeaderHeight;
- y = groupHeaderHeight;
- }
- else
- {
- height = headerHeight;
- y = 0;
- }
-
- if (pushingColumn)
- {
- column.getHeaderRenderer().setHover(
- columnBeingPushed == column
- && pushingAndHovering);
- }
- else
- {
- column.getHeaderRenderer().setHover(hoveringColumnHeader == column);
- }
-
- column.getHeaderRenderer().setHoverDetail(hoveringDetail);
-
- column.getHeaderRenderer().setBounds(x, y, column.getWidth(), height);
-
- if (cellSelectionEnabled)
- column.getHeaderRenderer().setSelected(selectedColumns.contains(column));
-
- if (x + column.getWidth() >= 0)
- {
- column.getHeaderRenderer().paint(gc, column);
- }
-
- x += column.getWidth();
- }
-
- if (x < getClientArea().width)
- {
- emptyColumnHeaderRenderer.setBounds(x, 0, getClientArea().width - x, headerHeight);
- emptyColumnHeaderRenderer.paint(gc, null);
- }
-
- x = 0;
-
- if (rowHeaderVisible)
- {
- // paint left corner
- topLeftRenderer.setBounds(0, 0, rowHeaderWidth, headerHeight);
- topLeftRenderer.paint(gc, this);
- x += rowHeaderWidth;
- }
-
- if (draggingColumn)
- {
-
- gc.setAlpha(COLUMN_DRAG_ALPHA);
-
- columnBeingPushed.getHeaderRenderer().setSelected(false);
-
- int height = 0;
-
- if (columnBeingPushed.getColumnGroup() != null)
- {
- height = headerHeight - groupHeaderHeight;
- y = groupHeaderHeight;
- }
- else
- {
- height = headerHeight;
- y = 0;
- }
-
- columnBeingPushed.getHeaderRenderer()
- .setBounds(
- getColumnHeaderXPosition(columnBeingPushed)
- + (currentHeaderDragX - startHeaderDragX), y,
- columnBeingPushed.getWidth(), height);
- columnBeingPushed.getHeaderRenderer().paint(gc, columnBeingPushed);
- columnBeingPushed.getHeaderRenderer().setSelected(false);
-
- gc.setAlpha(-1);
- gc.setAdvanced(false);
- }
-
- }
-
- private void paintFooter(GC gc) {
- int x = 0;
- int y = 0;
-
- x -= getHScrollSelectionInPixels();
-
- if (rowHeaderVisible)
- {
- // paint left corner
- // topLeftRenderer.setBounds(0, y, rowHeaderWidth, headerHeight);
- // topLeftRenderer.paint(gc, null);
- x += rowHeaderWidth;
- }
-
- for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext(); ) {
- if (x > getClientArea().width)
- break;
-
- GridColumn column = (GridColumn) columnIterator.next();
- int height = 0;
-
- if (!column.isVisible())
- {
- continue;
- }
-
- height = footerHeight;
- y = getClientArea().height - height;
-
- column.getFooterRenderer().setBounds(x, y, column.getWidth(), height);
- if (x + column.getWidth() >= 0)
- {
- column.getFooterRenderer().paint(gc, column);
- }
-
- x += column.getWidth();
- }
-
- if (x < getClientArea().width)
- {
- emptyColumnFooterRenderer.setBounds(x, getClientArea().height - footerHeight, getClientArea().width - x, footerHeight);
- emptyColumnFooterRenderer.paint(gc, null);
- }
-
- if (rowHeaderVisible)
- {
- // paint left corner
- bottomLeftRenderer.setBounds(0, getClientArea().height-footerHeight, rowHeaderWidth, footerHeight);
- bottomLeftRenderer.paint(gc, this);
- x += rowHeaderWidth;
- }
- }
-
- /**
- * Manages the state of the scrollbars when new items are added or the
- * bounds are changed.
- */
- private void updateScrollbars()
- {
- Point preferredSize = getTableSize();
-
- Rectangle clientArea = getClientArea();
-
- // First, figure out if the scrollbars should be visible and turn them
- // on right away
- // this will allow the computations further down to accommodate the
- // correct client
- // area
-
- // Turn the scrollbars on if necessary and do it all over again if
- // necessary. This ensures
- // that if a scrollbar is turned on/off, the other scrollbar's
- // visibility may be affected (more
- // area may have been added/removed.
- for (int doublePass = 1; doublePass <= 2; doublePass++)
- {
-
- if (preferredSize.y > clientArea.height)
- {
- vScroll.setVisible(true);
- }
- else
- {
- vScroll.setVisible(false);
- vScroll.setValues(0, 0, 1, 1, 1, 1);
- }
- if (preferredSize.x > clientArea.width)
- {
- hScroll.setVisible(true);
- }
- else
- {
- hScroll.setVisible(false);
- hScroll.setValues(0, 0, 1, 1, 1, 1);
- }
-
- // get the clientArea again with the now visible/invisible
- // scrollbars
- clientArea = getClientArea();
- }
-
- // if the scrollbar is visible set its values
- if (vScroll.getVisible())
- {
- int max = currentVisibleItems;
- int thumb = 1;
-
- if(!hasDifferingHeights)
- {
- // in this case, the number of visible rows on screen is constant,
- // so use this as thumb
- thumb = ( getVisibleGridHeight() + 1 ) / ( getItemHeight() + 1 );
- }
- else
- {
- // in this case, the number of visible rows on screen is variable,
- // so we have to use 1 as thumb and decrease max by the number of
- // rows on the last page
- if(getVisibleGridHeight()>=1) {
- RowRange range = getRowRange(-1,getVisibleGridHeight(),true,true);
- max -= range.rows - 1;
- }
- }
-
- // if possible, remember selection, if selection is too large, just
- // make it the max you can
- int selection = Math.min(vScroll.getSelection(), max);
-
- vScroll.setValues(selection, 0, max, thumb, 1, thumb);
- }
-
- // if the scrollbar is visible set its values
- if (hScroll.getVisible())
- {
-
- if (!columnScrolling)
- {
- // horizontal scrolling works pixel by pixel
-
- int hiddenArea = preferredSize.x - clientArea.width + 1;
-
- // if possible, remember selection, if selection is too large,
- // just
- // make it the max you can
- int selection = Math.min(hScroll.getSelection(), hiddenArea - 1);
-
- hScroll.setValues(selection, 0, hiddenArea + clientArea.width - 1, clientArea.width,
- HORZ_SCROLL_INCREMENT, clientArea.width);
- }
- else
- {
- // horizontal scrolling is column by column
-
- int hiddenArea = preferredSize.x - clientArea.width + 1;
-
- int max = 0;
- int i = 0;
-
- while (hiddenArea > 0 && i < getColumnCount())
- {
- GridColumn col = (GridColumn)displayOrderedColumns.get(i);
-
- i++;
-
- if (col.isVisible())
- {
- hiddenArea -= col.getWidth();
- max++;
- }
- }
-
- max++;
-
- // max should never be greater than the number of visible cols
- int visCols = 0;
- for (Iterator iter = columns.iterator(); iter.hasNext();)
- {
- GridColumn element = (GridColumn)iter.next();
- if (element.isVisible())
- {
- visCols++;
- }
- }
- max = Math.min(visCols, max);
-
- // if possible, remember selection, if selection is too large,
- // just
- // make it the max you can
- int selection = Math.min(hScroll.getSelection(), max);
-
- hScroll.setValues(selection, 0, max, 1, 1, 1);
- }
- }
-
- }
-
- /**
- * Adds/removes items from the selected items list based on the
- * selection/deselection of the given item.
- *
- * @param item item being selected/unselected
- * @param stateMask key state during selection
- *
- * @return selection event that needs to be fired or null
- */
- private Event updateSelection(GridItem item, int stateMask)
- {
- if (!selectionEnabled)
- {
- return null;
- }
-
- Event selectionEvent = null;
-
- if (selectionType == SWT.SINGLE)
- {
- if (selectedItems.contains(item))
- {
- // Deselect when pressing CTRL
- if ((stateMask & SWT.MOD1) == SWT.MOD1)
- {
- selectedItems.clear();
- }
- }
- else
- {
- selectedItems.clear();
- selectedItems.add(item);
- }
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- selectionEvent = new Event();
- selectionEvent.item = item;
- }
- else if (selectionType == SWT.MULTI)
- {
- boolean shift = false;
- boolean ctrl = false;
-
- if ((stateMask & SWT.MOD2) == SWT.MOD2)
- {
- shift = true;
- }
-
- if ((stateMask & SWT.MOD1) == SWT.MOD1)
- {
- ctrl = true;
- }
-
- if (!shift && !ctrl)
- {
- if (selectedItems.size() == 1 && selectedItems.contains(item)) return null;
-
- selectedItems.clear();
-
- selectedItems.add(item);
-
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- shiftSelectionAnchorItem = null;
-
- selectionEvent = new Event();
- selectionEvent.item = item;
- }
- else if (shift)
- {
-
- if (shiftSelectionAnchorItem == null)
- {
- shiftSelectionAnchorItem = focusItem;
- }
-
-// if (shiftSelectionAnchorItem == item)
-// {
-// return;
-// }
-
- boolean maintainAnchorSelection = false;
-
- if (!ctrl)
- {
- if (selectedItems.contains(shiftSelectionAnchorItem))
- {
- maintainAnchorSelection = true;
- }
- selectedItems.clear();
- }
-
- int anchorIndex = items.indexOf(shiftSelectionAnchorItem);
- int itemIndex = items.indexOf(item);
-
- int min = 0;
- int max = 0;
-
- if (anchorIndex < itemIndex)
- {
- if (maintainAnchorSelection)
- {
- min = anchorIndex;
- }
- else
- {
- min = anchorIndex + 1;
- }
- max = itemIndex;
- }
- else
- {
- if (maintainAnchorSelection)
- {
- max = anchorIndex;
- }
- else
- {
- max = anchorIndex - 1;
- }
- min = itemIndex;
- }
-
- for (int i = min; i <= max; i++)
- {
- if (!selectedItems.contains(items.get(i)) && ((GridItem)items.get(i)).isVisible())
- {
- selectedItems.add(items.get(i));
- }
- }
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- selectionEvent = new Event();
- }
- else if (ctrl)
- {
- if (selectedItems.contains(item))
- {
- selectedItems.remove(item);
- }
- else
- {
- selectedItems.add(item);
- }
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- shiftSelectionAnchorItem = null;
-
- selectionEvent = new Event();
- selectionEvent.item = item;
- }
- }
-
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- return selectionEvent;
- }
-
- /**
- * Updates cell selection.
- *
- * @param newCell newly clicked, navigated to cell.
- * @param stateMask statemask during preceeding mouse or key event.
- * @param dragging true if the user is dragging.
- * @param reverseDuplicateSelections true if the user is reversing selection rather than adding to.
- *
- * @return selection event that will need to be fired or null.
- */
- private Event updateCellSelection(Point newCell, int stateMask, boolean dragging, boolean reverseDuplicateSelections)
- {
- Vector v = new Vector();
- v.add(newCell);
- return updateCellSelection(v, stateMask, dragging, reverseDuplicateSelections);
- }
-
- /**
- * Updates cell selection.
- *
- * @param newCell newly clicked, navigated to cells.
- * @param stateMask statemask during preceeding mouse or key event.
- * @param dragging true if the user is dragging.
- * @param reverseDuplicateSelections true if the user is reversing selection rather than adding to.
- *
- * @return selection event that will need to be fired or null.
- */
- private Event updateCellSelection(Vector newCells, int stateMask, boolean dragging, boolean reverseDuplicateSelections)
- {
- boolean shift = false;
- boolean ctrl = false;
-
- if ((stateMask & SWT.MOD2) == SWT.MOD2)
- {
- shift = true;
- }
- else
- {
- shiftSelectionAnchorColumn = null;
- shiftSelectionAnchorItem = null;
- }
-
- if ((stateMask & SWT.MOD1) == SWT.MOD1)
- {
- ctrl = true;
- }
-
- if (!shift && !ctrl)
- {
- if (newCells.equals(selectedCells)) return null;
-
- selectedCells.clear();
- for (int i = 0; i < newCells.size(); i++)
- {
- addToCellSelection((Point)newCells.get(i));
- }
-
- }
- else if (shift)
- {
-
- Point newCell = (Point)newCells.get(0); //shift selection should only occur with one
- //cell, ignoring others
-
- if ((focusColumn == null) || (focusItem == null))
- {
- return null;
- }
-
- shiftSelectionAnchorColumn = getColumn(newCell.x);
- shiftSelectionAnchorItem = getItem(newCell.y);
-
- if (ctrl)
- {
- selectedCells.clear();
- selectedCells.addAll(selectedCellsBeforeRangeSelect);
- }
- else
- {
- selectedCells.clear();
- }
-
-
-
-
- GridColumn currentColumn = focusColumn;
- GridItem currentItem = focusItem;
-
- GridColumn endColumn = getColumn(newCell.x);
- GridItem endItem = getItem(newCell.y);
-
- Point newRange = getSelectionRange(currentItem,currentColumn,endItem,endColumn);
-
- currentColumn = getColumn(newRange.x);
- endColumn = getColumn(newRange.y);
-
- GridColumn startCol = currentColumn;
-
- if (indexOf(currentItem) > indexOf(endItem))
- {
- GridItem temp = currentItem;
- currentItem = endItem;
- endItem = temp;
- }
-
- boolean firstLoop = true;
-
- do
- {
- if (!firstLoop)
- {
- currentItem = getNextVisibleItem(currentItem);
- }
-
- firstLoop = false;
-
- boolean firstLoop2 = true;
-
- currentColumn = startCol;
-
- do
- {
- if (!firstLoop2)
- {
- int index = displayOrderedColumns.indexOf(currentColumn) + 1;
-
- if (index < displayOrderedColumns.size())
- {
- currentColumn = getVisibleColumn_DegradeRight(currentItem,(GridColumn)displayOrderedColumns.get(index));
- }
- else
- {
- currentColumn = null;
- }
-
- if (currentColumn!= null)
- if (displayOrderedColumns.indexOf(currentColumn) > displayOrderedColumns.indexOf(endColumn))
- currentColumn = null;
- }
-
- firstLoop2 = false;
-
- if (currentColumn != null)
- {
- Point cell = new Point(indexOf(currentColumn),indexOf(currentItem));
- addToCellSelection(cell);
- }
- } while (currentColumn != endColumn && currentColumn != null);
- } while (currentItem != endItem);
- }
- else if (ctrl)
- {
- boolean reverse = reverseDuplicateSelections;
- if (!selectedCells.containsAll(newCells))
- reverse = false;
-
- if (dragging)
- {
- selectedCells.clear();
- selectedCells.addAll(selectedCellsBeforeRangeSelect);
- }
-
- if (reverse)
- {
- selectedCells.removeAll(newCells);
- }
- else
- {
- for (int i = 0; i < newCells.size(); i++)
- {
- addToCellSelection((Point)newCells.get(i));
- }
- }
- }
-
- updateColumnSelection();
-
- Event e = new Event();
- if (dragging)
- {
- e.detail = SWT.DRAG;
- followupCellSelectionEventOwed = true;
- }
-
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- return e;
- }
-
- private void addToCellSelection(Point newCell)
- {
- if (newCell.x < 0 || newCell.x >= columns.size())
- return;
-
- if (newCell.y < 0 || newCell.y >= items.size())
- return;
-
- if (getColumn(newCell.x).getCellSelectionEnabled())
- {
- Iterator it = selectedCells.iterator();
- boolean found = false;
- while( it.hasNext() ) {
- Point p = (Point) it.next();
- if( newCell.equals(p) ) {
- found = true;
- break;
- }
- }
-
- if( ! found ) {
- selectedCells.add(newCell);
- }
- }
- }
-
- void updateColumnSelection()
- {
- //Update the list of which columns have all their cells selected
- selectedColumns.clear();
-
- for (Iterator iter = selectedCells.iterator(); iter.hasNext();)
- {
- Point cell = (Point)iter.next();
-
- GridColumn col = getColumn(cell.x);
-
- selectedColumns.add(col);
- }
- }
-
- /**
- * Initialize all listeners.
- */
- private void initListeners()
- {
- disposeListener = new Listener()
- {
- @Override
- public void handleEvent(Event e)
- {
- onDispose(e);
- }
- };
- addListener(SWT.Dispose,disposeListener);
-
- addPaintListener(new PaintListener()
- {
- @Override
- public void paintControl(PaintEvent e)
- {
- onPaint(e);
- }
- });
-
- addListener(SWT.Resize, new Listener()
- {
- @Override
- public void handleEvent(Event e)
- {
- onResize();
- }
- });
-
- if (getVerticalBar() != null)
- {
- getVerticalBar().addListener(SWT.Selection, new Listener()
- {
- @Override
- public void handleEvent(Event e)
- {
- onScrollSelection();
- }
- });
- }
-
- if (getHorizontalBar() != null)
- {
- getHorizontalBar().addListener(SWT.Selection, new Listener()
- {
- @Override
- public void handleEvent(Event e)
- {
- onScrollSelection();
- }
- });
- }
-
- addListener(SWT.KeyDown, new Listener()
- {
- @Override
- public void handleEvent(Event e)
- {
- onKeyDown(e);
- }
- });
-
- addTraverseListener(new TraverseListener()
- {
- @Override
- public void keyTraversed(TraverseEvent e)
- {
- e.doit = true;
- }
- });
-
- addMouseListener(new MouseListener()
- {
- @Override
- public void mouseDoubleClick(MouseEvent e)
- {
- onMouseDoubleClick(e);
- }
-
- @Override
- public void mouseDown(MouseEvent e)
- {
- onMouseDown(e);
- }
-
- @Override
- public void mouseUp(MouseEvent e)
- {
- onMouseUp(e);
- }
- });
-
- addMouseMoveListener(new MouseMoveListener()
- {
- @Override
- public void mouseMove(MouseEvent e)
- {
- onMouseMove(e);
- }
- });
-
- addMouseTrackListener(new MouseTrackListener()
- {
- @Override
- public void mouseEnter(MouseEvent e)
- {
- }
-
- @Override
- public void mouseExit(MouseEvent e)
- {
- onMouseExit(e);
- }
-
- @Override
- public void mouseHover(MouseEvent e)
- {
- }
- });
-
- addFocusListener(new FocusListener()
- {
- @Override
- public void focusGained(FocusEvent e)
- {
- onFocusIn();
- redraw();
- }
-
- @Override
- public void focusLost(FocusEvent e)
- {
- redraw();
- }
- });
-
- // Special code to reflect mouse wheel events if using an external
- // scroller
- addListener(SWT.MouseWheel, new Listener()
- {
- @Override
- public void handleEvent(Event e)
- {
- onMouseWheel(e);
- }
- });
- }
-
- private void onFocusIn()
- {
- if (!items.isEmpty() && focusItem == null)
- {
- focusItem = (GridItem) items.get(0);
- }
- }
-
- private void onDispose(Event event)
- {
- //We only want to dispose of our items and such *after* anybody else who may have been
- //listening to the dispose has had a chance to do whatever.
- removeListener(SWT.Dispose, disposeListener);
- notifyListeners(SWT.Dispose, event);
- event.type = SWT.None;
-
- disposing = true;
-
- cellHeaderSelectionBackground.dispose();
-
- for (Iterator iterator = items.iterator(); iterator.hasNext();)
- {
- GridItem item = (GridItem)iterator.next();
- item.dispose();
- }
-
- for (int i = 0; i < columnGroups.length; i++)
- {
- columnGroups[i].dispose();
- }
-
- for (Iterator iterator = columns.iterator(); iterator.hasNext();)
- {
- GridColumn col = (GridColumn)iterator.next();
- col.dispose();
- }
-
- sizingGC.dispose();
- }
-
- /**
- * Mouse wheel event handler.
- *
- * @param e event
- */
- private void onMouseWheel(Event e)
- {
- if (vScroll.getVisible())
- {
- vScroll.handleMouseWheel(e);
- if (getVerticalBar() == null)
- e.doit = false;
- }
- else if (hScroll.getVisible())
- {
- hScroll.handleMouseWheel(e);
- if (getHorizontalBar() == null)
- e.doit = false;
- }
- }
-
- /**
- * Mouse down event handler.
- *
- * @param e event
- */
- private void onMouseDown(MouseEvent e)
- {
- // for some reason, SWT prefers the children to get focus if
- // there are any children
- // the setFocus method on Composite will not set focus to the
- // Composite if one of its
- // children can get focus instead. This only affects the table
- // when an editor is open
- // and therefore the table has a child. The solution is to
- // forceFocus()
- if ((getStyle() & SWT.NO_FOCUS) != SWT.NO_FOCUS)
- {
- forceFocus();
- }
-
- hideToolTip();
-
- //if populated will be fired at end of method.
- Event selectionEvent = null;
-
- cellSelectedOnLastMouseDown = false;
- cellRowSelectedOnLastMouseDown = false;
- cellColumnSelectedOnLastMouseDown = false;
-
- if (hoveringOnColumnResizer)
- {
- if (e.button == 1)
- {
- resizingColumn = true;
- resizingStartX = e.x;
- resizingColumnStartWidth = columnBeingResized.getWidth();
- }
- return;
- }
- if (rowsResizeable && hoveringOnRowResizer)
- {
- if (e.button == 1)
- {
- resizingRow = true;
- resizingStartY = e.y;
- resizingRowStartHeight = rowBeingResized.getHeight();
- }
- return;
- }
-
-
- if (e.button == 1 && handleColumnHeaderPush(e.x, e.y))
- {
- return;
- }
-
- if (e.button == 1 && handleColumnGroupHeaderClick(e.x, e.y))
- {
- return;
- }
-
- if(e.button == 1 && handleColumnFooterPush(e.x,e.y)) {
- return;
- }
-
- GridItem item = getItem(new Point(e.x, e.y));
-
- if (e.button == 1 && item != null && handleCellClick(item,e.x, e.y))
- {
- return;
- }
-
- if (isListening(SWT.DragDetect))
- {
- if ((cellSelectionEnabled && hoveringOnSelectionDragArea) ||
- (!cellSelectionEnabled && item != null && selectedItems.contains(item)))
- {
- if(dragDetect(e))
- {
- return;
- }
- }
- }
-
- if (item != null)
- {
- if (cellSelectionEnabled)
- {
- GridColumn col = getColumn(new Point(e.x, e.y));
- boolean isSelectedCell = false;
- if (col != null)
- isSelectedCell = selectedCells.contains(new Point(indexOf(col),indexOf(item)));
-
- if (e.button == 1 || (e.button == 3 && col != null && !isSelectedCell))
- {
- if (col != null)
- {
- selectionEvent = updateCellSelection(new Point(indexOf(col),indexOf(item)), e.stateMask, false, true);
- cellSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
-
- if (e.stateMask != SWT.MOD2)
- {
- focusColumn = col;
- focusItem = item;
- }
- //showColumn(col);
- showItem(item);
- redraw();
- }
- else if (rowHeaderVisible)
- {
- if (e.x <= rowHeaderWidth)
- {
-
- boolean shift = ((e.stateMask & SWT.MOD2) != 0);
- boolean ctrl = false;
- if (!shift)
- {
- ctrl = ((e.stateMask & SWT.MOD1) != 0);
- }
-
- Vector cells = new Vector();
-
- if (shift)
- {
- getCells(item,focusItem,cells);
- }
- else
- {
- getCells(item,cells);
- }
-
- int newStateMask = SWT.NONE;
- if (ctrl) newStateMask = SWT.MOD1;
-
- selectionEvent = updateCellSelection(cells, newStateMask, shift, ctrl);
- cellRowSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
-
- if (!shift)
- {
- //set focus back to the first visible column
- focusColumn = getColumn(new Point(rowHeaderWidth + 1,e.y));
-
- focusItem = item;
- }
- showItem(item);
- redraw();
- }
- }
- intendedFocusColumn = focusColumn;
- }
- }
- else
- {
- if (e.button == 2 || e.button > 3)
- {
- return;
- }
-
- if (e.button == 3 && selectionType == SWT.MULTI)
- {
- if ((e.stateMask & SWT.MOD2) == SWT.MOD2)
- {
- return;
- }
-
- if ((e.stateMask & SWT.MOD1) == SWT.MOD1)
- {
- return;
- }
-
- if (selectedItems.contains(item))
- {
- return;
- }
- }
- selectionEvent = updateSelection(item, e.stateMask);
-
-
- focusItem = item;
- showItem(item);
- redraw();
- }
- }
- else if (e.button == 1 && rowHeaderVisible && e.x <= rowHeaderWidth && e.y < headerHeight)
- {
- // Nothing to select
- if(items.size() == 0) {
- return;
- }
- if (cellSelectionEnabled)
- {
- //click on the top left corner means select everything
- selectionEvent = selectAllCellsInternal();
-
- focusColumn = getColumn(new Point(rowHeaderWidth + 1,1));
- }
- else
- {
- //click on the top left corner means select everything
- selectionEvent = selectAllRowsInternal();
- }
- focusItem = getItem(getTopIndex());
- }
- else if (cellSelectionEnabled && e.button == 1 && columnHeadersVisible && e.y <= headerHeight)
- {
- //column cell selection
- GridColumn col = getColumn(new Point(e.x,e.y));
-
- if (col == null) return;
-
- if (getItemCount() == 0)
- return;
-
- Vector cells = new Vector();
-
- GridColumnGroup group = col.getColumnGroup();
- if (group != null && e.y < groupHeaderHeight) {
- getCells(group, cells);
- } else {
- getCells(col, cells);
- }
-
- selectionEvent = updateCellSelection(cells, e.stateMask, false, true);
- cellColumnSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
-
- GridItem newFocusItem = getItem(0);
-
- while (newFocusItem != null && getSpanningColumn(newFocusItem, col) != null)
- {
- newFocusItem = getNextVisibleItem(newFocusItem);
- }
-
- if (newFocusItem != null)
- {
- focusColumn = col;
- focusItem = newFocusItem;
- }
-
- showColumn(col);
- redraw();
- }
-
- if (selectionEvent != null)
- {
- selectionEvent.stateMask = e.stateMask;
- selectionEvent.button = e.button;
- selectionEvent.item = item;
- selectionEvent.x = e.x;
- selectionEvent.y = e.y;
- notifyListeners(SWT.Selection, selectionEvent);
-
- if (!cellSelectionEnabled)
- {
- if (isListening(SWT.DragDetect))
- {
- dragDetect(e);
- }
- }
- }
-
-
- }
-
- /**
- * Mouse double click event handler.
- *
- * @param e event
- */
- private void onMouseDoubleClick(MouseEvent e)
- {
- if (e.button == 1)
- {
-
- if (hoveringOnColumnResizer)
- {
- columnBeingResized.pack();
- columnBeingResized.fireResized();
- for (int index = displayOrderedColumns.indexOf(columnBeingResized) + 1; index < displayOrderedColumns.size(); index ++)
- {
- GridColumn col = (GridColumn)displayOrderedColumns.get(index);
- if (col.isVisible()) col.fireMoved();
- }
- resizingColumn = false;
- handleHoverOnColumnResizer(e.x, e.y);
- return;
- }
- else if (rowsResizeable && hoveringOnRowResizer) {
- List sel = Arrays.asList(getSelection());
- if(sel.contains(rowBeingResized))
- {
- // the user double-clicked a row resizer of a selected row
- // so update all selected rows
- for(int cnt=0;cnt<sel.size();cnt++)
- ((GridItem)sel.get(cnt)).pack();
- redraw();
- }
- else
- {
- // otherwise only update the row the user double-clicked
- rowBeingResized.pack();
- }
-
- resizingRow = false;
- handleHoverOnRowResizer(e.x, e.y);
- return;
- }
-
- GridItem item = getItem(new Point(e.x, e.y));
- if (item != null)
- {
- if (isListening(SWT.DefaultSelection))
- {
- Event newEvent = new Event();
- newEvent.item = item;
-
- notifyListeners(SWT.DefaultSelection, newEvent);
- }
- else if (item.getItemCount() > 0)
- {
- item.setExpanded(!item.isExpanded());
-
- if (item.isExpanded())
- {
- item.fireEvent(SWT.Expand);
- }
- else
- {
- item.fireEvent(SWT.Collapse);
- }
- }
- }
- }
- }
-
- /**
- * Mouse up handler.
- *
- * @param e event
- */
- private void onMouseUp(MouseEvent e)
- {
- cellSelectedOnLastMouseDown = false;
-
- if (resizingColumn)
- {
- resizingColumn = false;
- handleHoverOnColumnResizer(e.x, e.y); // resets cursor if
- // necessary
- return;
- }
- if (resizingRow)
- {
- resizingRow = false;
- handleHoverOnRowResizer(e.x, e.y); // resets cursor if
- // necessary
- return;
- }
-
- if (pushingColumn)
- {
- pushingColumn = false;
- columnBeingPushed.getHeaderRenderer().setMouseDown(false);
- columnBeingPushed.getHeaderRenderer().setHover(false);
- redraw();
- if (pushingAndHovering)
- {
- columnBeingPushed.fireListeners();
- }
- setCapture(false);
- return;
- }
-
- if (draggingColumn)
- {
- handleColumnDrop();
- return;
- }
-
- if (cellDragSelectionOccuring || cellRowDragSelectionOccuring || cellColumnDragSelectionOccuring)
- {
- cellDragSelectionOccuring = false;
- cellRowDragSelectionOccuring = false;
- cellColumnDragSelectionOccuring = false;
- setCursor(null);
-
- if (followupCellSelectionEventOwed)
- {
- Event se = new Event();
- se.button = e.button;
- se.item = getItem(new Point(e.x, e.y));
- se.stateMask = e.stateMask;
- se.x = e.x;
- se.y = e.y;
-
- notifyListeners(SWT.Selection, se);
- followupCellSelectionEventOwed = false;
- }
- }
- }
-
- /**
- * Mouse move event handler.
- *
- * @param e event
- */
- private void onMouseMove(MouseEvent e)
- {
- //check to see if the mouse is outside the grid
- //this should only happen when the mouse is captured for inplace
- //tooltips - see bug 203364
- if (inplaceTooltipCapture && (e.x < 0 || e.y < 0 || e.x >= getBounds().width || e.y >= getBounds().height))
- {
- setCapture(false);
- inplaceTooltipCapture = false;
- return; //a mouseexit event should occur immediately
- }
-
-
- //if populated will be fired at end of method.
- Event selectionEvent = null;
-
-
- if ((e.stateMask & SWT.BUTTON1) == 0)
- {
- handleHovering(e.x, e.y);
- }
- else
- {
- if (draggingColumn)
- {
- handleColumnDragging(e.x);
- return;
- }
-
- if (resizingColumn)
- {
- handleColumnResizerDragging(e.x);
- return;
- }
- if (resizingRow)
- {
- handleRowResizerDragging(e.y);
- return;
- }
- if (pushingColumn)
- {
- handleColumnHeaderHoverWhilePushing(e.x, e.y);
- return;
- }
- if (cellSelectionEnabled)
- {
- if (!cellDragSelectionOccuring && cellSelectedOnLastMouseDown)
- {
- cellDragSelectionOccuring = true;
- //XXX: make this user definable
- setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
- cellDragCTRL = ((e.stateMask & SWT.MOD1) != 0);
- if (cellDragCTRL)
- {
- selectedCellsBeforeRangeSelect.clear();
- selectedCellsBeforeRangeSelect.addAll(selectedCells);
- }
- }
- if (!cellRowDragSelectionOccuring && cellRowSelectedOnLastMouseDown)
- {
- cellRowDragSelectionOccuring = true;
- setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
- cellDragCTRL = ((e.stateMask & SWT.MOD1) != 0);
- if (cellDragCTRL)
- {
- selectedCellsBeforeRangeSelect.clear();
- selectedCellsBeforeRangeSelect.addAll(selectedCells);
- }
- }
-
- if (!cellColumnDragSelectionOccuring && cellColumnSelectedOnLastMouseDown)
- {
- cellColumnDragSelectionOccuring = true;
- setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
- cellDragCTRL = ((e.stateMask & SWT.MOD1) != 0);
- if (cellDragCTRL)
- {
- selectedCellsBeforeRangeSelect.clear();
- selectedCellsBeforeRangeSelect.addAll(selectedCells);
- }
- }
-
- int ctrlFlag = (cellDragCTRL ? SWT.MOD1 : SWT.NONE);
-
- if (cellDragSelectionOccuring && handleCellHover(e.x, e.y))
- {
- GridColumn intentColumn = hoveringColumn;
- GridItem intentItem = hoveringItem;
-
- if (hoveringItem == null)
- {
- if (e.y > headerHeight)
- {
- //then we must be hovering way to the bottom
- intentItem = getPreviousVisibleItem(null);
- }
- else
- {
- intentItem = (GridItem)items.get(0);
- }
- }
-
-
- if (hoveringColumn == null)
- {
- if (e.x > rowHeaderWidth)
- {
- //then we must be hovering way to the right
- intentColumn = getVisibleColumn_DegradeLeft(intentItem,(GridColumn)displayOrderedColumns.get(displayOrderedColumns.size() - 1));
- }
- else
- {
- GridColumn firstCol = (GridColumn)displayOrderedColumns.get(0);
- if (!firstCol.isVisible())
- {
- firstCol = getNextVisibleColumn(firstCol);
- }
- intentColumn = firstCol;
- }
- }
-
- showColumn(intentColumn);
- showItem(intentItem);
- selectionEvent = updateCellSelection(new Point(indexOf(intentColumn),indexOf(intentItem)),ctrlFlag | SWT.MOD2, true, false);
- }
- if (cellRowDragSelectionOccuring && handleCellHover(e.x, e.y))
- {
- GridItem intentItem = hoveringItem;
-
- if (hoveringItem == null)
- {
- if (e.y > headerHeight)
- {
- //then we must be hovering way to the bottom
- intentItem = getPreviousVisibleItem(null);
- }
- else
- {
- if (getTopIndex() > 0)
- {
- intentItem = getPreviousVisibleItem((GridItem)items.get(getTopIndex()));
- }
- else
- {
- intentItem = (GridItem)items.get(0);
- }
- }
- }
-
- Vector cells = new Vector();
-
- getCells(intentItem,focusItem,cells);
-
- showItem(intentItem);
- selectionEvent = updateCellSelection(cells,ctrlFlag, true, false);
- }
- if (cellColumnDragSelectionOccuring && handleCellHover(e.x, e.y))
- {
- GridColumn intentCol = hoveringColumn;
-
- if (intentCol == null)
- {
- if (e.y < rowHeaderWidth)
- {
- //TODO: get the first col to the left
- }
- else
- {
- //TODO: get the first col to the right
- }
- }
-
- if (intentCol == null) return; //temporary
-
- GridColumn iterCol = intentCol;
-
- Vector newSelected = new Vector();
-
- boolean decreasing = (displayOrderedColumns.indexOf(iterCol) > displayOrderedColumns.indexOf(focusColumn));
-
- do
- {
- getCells(iterCol, newSelected);
-
- if (iterCol == focusColumn)
- {
- break;
- }
-
- if (decreasing)
- {
- iterCol = getPreviousVisibleColumn(iterCol);
- }
- else
- {
- iterCol = getNextVisibleColumn(iterCol);
- }
-
- } while (true);
-
- selectionEvent = updateCellSelection(newSelected, ctrlFlag, true, false);
- }
-
- }
- }
-
- if (selectionEvent != null)
- {
- selectionEvent.stateMask = e.stateMask;
- selectionEvent.button = e.button;
- selectionEvent.item = getItem(new Point(e.x, e.y));
- selectionEvent.x = e.x;
- selectionEvent.y = e.y;
- notifyListeners(SWT.Selection, selectionEvent);
- }
- }
-
- /**
- * Handles the assignment of the correct values to the hover* field
- * variables that let the painting code now what to paint as hovered.
- *
- * @param x mouse x coordinate
- * @param y mouse y coordinate
- */
- private void handleHovering(int x, int y)
- {
- // TODO: need to clean up and refactor hover code
- handleCellHover(x, y);
-
- // Is this Grid a DragSource ??
- if (cellSelectionEnabled && getData("DragSource") != null) {
- if (handleHoverOnSelectionDragArea(x, y))
- {
- return;
- }
- }
-
- if (columnHeadersVisible)
- {
- if (handleHoverOnColumnResizer(x, y))
- {
-// if (hoveringItem != null || !hoveringDetail.equals("") || hoveringColumn != null
-// || hoveringColumnHeader != null || hoverColumnGroupHeader != null)
-// {
-// hoveringItem = null;
-// hoveringDetail = "";
-// hoveringColumn = null;
-// hoveringColumnHeader = null;
-// hoverColumnGroupHeader = null;
-//
-// Rectangle clientArea = getClientArea();
-// redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-// }
- return;
- }
- }
- if (rowsResizeable && rowHeaderVisible)
- {
- if (handleHoverOnRowResizer(x, y))
- {
- return;
- }
- }
-
- // handleCellHover(x, y);
- }
-
- /**
- * Refreshes the hover* variables according to the mouse location and
- * current state of the table. This is useful is some method call, caused
- * the state of the table to change and therefore the hover effects may have
- * become out of date.
- */
- protected void refreshHoverState()
- {
- Point p = getDisplay().map(null, this, getDisplay().getCursorLocation());
- handleHovering(p.x, p.y);
- }
-
- /**
- * Mouse exit event handler.
- *
- * @param e event
- */
- private void onMouseExit(MouseEvent e)
- {
- hoveringItem = null;
- hoveringDetail = "";
- hoveringColumn = null;
- hoveringOverText = false;
- hideToolTip();
- redraw();
- }
-
- /**
- * Key down event handler.
- *
- * @param e event
- */
- private void onKeyDown(Event e)
- {
- if (focusColumn == null || focusColumn.isDisposed())
- {
- if (columns.size() == 0)
- return;
-
- focusColumn = getColumn(0);
- intendedFocusColumn = focusColumn;
- }
-
- if (e.character == '\r' && focusItem != null)
- {
- Event newEvent = new Event();
- newEvent.item = focusItem;
-
- notifyListeners(SWT.DefaultSelection, newEvent);
- return;
- }
-
- int attemptExpandCollapse = 0;
- if ((e.character == '-' || (!cellSelectionEnabled && e.keyCode == SWT.ARROW_LEFT)) && focusItem != null && focusItem.isExpanded())
- {
- attemptExpandCollapse = SWT.Collapse;
- }
- else if ((e.character == '+' || (!cellSelectionEnabled && e.keyCode == SWT.ARROW_RIGHT)) && focusItem != null && !focusItem.isExpanded())
- {
- attemptExpandCollapse = SWT.Expand;
- }
-
- if (attemptExpandCollapse != 0 && focusItem != null && focusItem.hasChildren())
- {
- int performExpandCollapse = 0;
-
- if (cellSelectionEnabled && focusColumn != null && focusColumn.isTree())
- {
- performExpandCollapse = attemptExpandCollapse;
- }
- else if (!cellSelectionEnabled)
- {
- performExpandCollapse = attemptExpandCollapse;
- }
-
- if (performExpandCollapse == SWT.Expand)
- {
- focusItem.setExpanded(true);
- focusItem.fireEvent(SWT.Expand);
- return;
- }
- if (performExpandCollapse == SWT.Collapse)
- {
- focusItem.setExpanded(false);
- focusItem.fireEvent(SWT.Collapse);
- return;
- }
- }
-
- if (e.character == ' ')
- {
- handleSpaceBarDown(e);
- }
-
-
- GridItem newSelection = null;
- GridColumn newColumnFocus = null;
-
- //These two variables are used because the key navigation when the shift key is down is
- //based, not off the focus item/column, but rather off the implied focus (i.e. where the
- //keyboard has extended focus to).
- GridItem impliedFocusItem = focusItem;
- GridColumn impliedFocusColumn = focusColumn;
-
- if (cellSelectionEnabled && e.stateMask == SWT.MOD2)
- {
- if (shiftSelectionAnchorColumn != null)
- {
- impliedFocusItem = shiftSelectionAnchorItem;
- impliedFocusColumn = shiftSelectionAnchorColumn;
- }
- }
-
- switch (e.keyCode)
- {
- case SWT.ARROW_RIGHT :
- if (cellSelectionEnabled)
- {
- if (impliedFocusItem != null && impliedFocusColumn != null)
- {
- newSelection = impliedFocusItem;
-
- int index = displayOrderedColumns.indexOf(impliedFocusColumn);
-
- int jumpAhead = impliedFocusItem.getColumnSpan(indexOf(impliedFocusColumn));
-
- jumpAhead ++;
-
- while (jumpAhead > 0)
- {
- index ++;
- if (index < displayOrderedColumns.size())
- {
- if (((GridColumn)displayOrderedColumns.get(index)).isVisible())
- jumpAhead --;
- }
- else
- {
- break;
- }
- }
-
- if (index < displayOrderedColumns.size())
- {
- newColumnFocus = (GridColumn)displayOrderedColumns.get(index);
- }
- else
- {
- newColumnFocus = impliedFocusColumn;
- }
- }
- intendedFocusColumn = newColumnFocus;
- }
- else
- {
- if (impliedFocusItem != null && impliedFocusItem.hasChildren())
- {
- newSelection = impliedFocusItem.getItem(0);
- }
- }
- break;
- case SWT.ARROW_LEFT :
- if (cellSelectionEnabled)
- {
- if (impliedFocusItem != null && impliedFocusColumn != null)
- {
- newSelection = impliedFocusItem;
-
- int index = displayOrderedColumns.indexOf(impliedFocusColumn);
-
- if (index != 0)
- {
- newColumnFocus = (GridColumn)displayOrderedColumns.get(index -1);
-
- newColumnFocus = getVisibleColumn_DegradeLeft(impliedFocusItem, newColumnFocus);
- }
- else
- {
- newColumnFocus = impliedFocusColumn;
- }
- }
- intendedFocusColumn = newColumnFocus;
- }
- else
- {
- if (impliedFocusItem != null && impliedFocusItem.getParentItem() != null)
- {
- newSelection = impliedFocusItem.getParentItem();
- }
- }
- break;
- case SWT.ARROW_UP :
- if (impliedFocusItem != null)
- {
- newSelection = getPreviousVisibleItem(impliedFocusItem);
- }
-
- if (impliedFocusColumn != null)
- {
- if (newSelection != null)
- {
- newColumnFocus = getVisibleColumn_DegradeLeft(newSelection, intendedFocusColumn);
- }
- else
- {
- newColumnFocus = impliedFocusColumn;
- }
- }
-
- break;
- case SWT.ARROW_DOWN :
- if (impliedFocusItem != null)
- {
- newSelection = getNextVisibleItem(impliedFocusItem);
- }
- else
- {
- if (items.size() > 0)
- {
- newSelection = (GridItem)items.get(0);
- }
- }
-
- if (impliedFocusColumn != null)
- {
- if (newSelection != null)
- {
- newColumnFocus = getVisibleColumn_DegradeLeft(newSelection, intendedFocusColumn);
- }
- else
- {
- newColumnFocus = impliedFocusColumn;
- }
- }
- break;
- case SWT.HOME :
-
- if (!cellSelectionEnabled)
- {
- if (items.size() > 0)
- {
- newSelection = (GridItem)items.get(0);
- }
- }
- else
- {
- newSelection = impliedFocusItem;
- newColumnFocus = getVisibleColumn_DegradeRight(newSelection,(GridColumn)displayOrderedColumns.get(0));
- }
-
- break;
- case SWT.END :
- if (!cellSelectionEnabled)
- {
- if (items.size() > 0)
- {
- newSelection = getPreviousVisibleItem(null);
- }
- }
- else
- {
- newSelection = impliedFocusItem;
- newColumnFocus = getVisibleColumn_DegradeLeft(newSelection,(GridColumn)displayOrderedColumns.get(displayOrderedColumns.size() - 1));
- }
-
- break;
- case SWT.PAGE_UP :
- int topIndex = getTopIndex();
-
- newSelection = (GridItem)items.get(topIndex);
-
- if (focusItem == newSelection)
- {
- RowRange range = getRowRange(getTopIndex(),getVisibleGridHeight(),false,true);
- newSelection = (GridItem)items.get(range.startIndex);
- }
-
- newColumnFocus = focusColumn;
- break;
- case SWT.PAGE_DOWN :
- int bottomIndex = getBottomIndex();
-
- newSelection = (GridItem)items.get(bottomIndex);
-
- if(!isShown(newSelection))
- {
- // the item at bottom index is not shown completely
- GridItem tmpItem = getPreviousVisibleItem(newSelection);
- if(tmpItem!=null)
- newSelection = tmpItem;
- }
-
- if (focusItem == newSelection)
- {
- RowRange range = getRowRange(getBottomIndex(),getVisibleGridHeight(),true,false);
- newSelection = (GridItem)items.get(range.endIndex);
- }
-
- newColumnFocus = focusColumn;
- break;
- default :
- break;
- }
-
- if (newSelection == null)
- {
- return;
- }
-
- if (cellSelectionEnabled)
- {
- if (e.stateMask != SWT.MOD2)
- focusColumn = newColumnFocus;
- showColumn(newColumnFocus);
-
- if (e.stateMask != SWT.MOD2)
- focusItem = newSelection;
- showItem(newSelection);
-
- if (e.stateMask != SWT.MOD1)
- {
- Event selEvent = updateCellSelection(new Point(indexOf(newColumnFocus),indexOf(newSelection)),e.stateMask, false, false);
- if (selEvent != null)
- {
- selEvent.stateMask = e.stateMask;
- selEvent.character = e.character;
- selEvent.keyCode = e.keyCode;
- notifyListeners(SWT.Selection, selEvent);
- }
- }
-
- redraw();
- }
- else
- {
- Event selectionEvent = null;
- if (selectionType == SWT.SINGLE || e.stateMask != SWT.MOD1)
- {
- selectionEvent = updateSelection(newSelection, e.stateMask);
- if (selectionEvent != null)
- {
- selectionEvent.stateMask = e.stateMask;
- selectionEvent.character = e.character;
- selectionEvent.keyCode = e.keyCode;
- }
- }
-
- focusItem = newSelection;
- showItem(newSelection);
- redraw();
-
- if (selectionEvent != null)
- notifyListeners(SWT.Selection, selectionEvent);
- }
- }
-
- private void handleSpaceBarDown(Event event)
- {
- if (focusItem == null)
- return;
-
- if (selectionEnabled && !cellSelectionEnabled && !selectedItems.contains(focusItem))
- {
- selectedItems.add(focusItem);
- redraw();
- Event e = new Event();
- e.item = focusItem;
- e.stateMask = event.stateMask;
- e.character = event.character;
- e.keyCode = event.keyCode;
- notifyListeners(SWT.Selection, e);
- }
-
- if (!cellSelectionEnabled)
- {
- boolean checkFirstCol = false;
- boolean first = true;
-
- for (Iterator iter = columns.iterator(); iter.hasNext();)
- {
- GridColumn col = (GridColumn)iter.next();
-
- if (first)
- {
- if (!col.isCheck()) break;
-
- first = false;
- checkFirstCol = true;
- }
- else
- {
- if (col.isCheck())
- {
- checkFirstCol = false;
- break;
- }
- }
- }
-
- if (checkFirstCol)
- {
- focusItem.setChecked(!focusItem.getChecked());
- redraw();
- focusItem.fireCheckEvent(0);
- }
- }
- }
-
- /**
- * Resize event handler.
- */
- private void onResize()
- {
-
- //CGross 1/2/08 - I don't really want to be doing this....
- //I shouldn't be changing something you user configured...
- //leaving out for now
-// if (columnScrolling)
-// {
-// int maxWidth = getClientArea().width;
-// if (rowHeaderVisible)
-// maxWidth -= rowHeaderWidth;
-//
-// for (Iterator cols = columns.iterator(); cols.hasNext();) {
-// GridColumn col = (GridColumn) cols.next();
-// if (col.getWidth() > maxWidth)
-// col.setWidth(maxWidth);
-// }
-// }
-
- scrollValuesObsolete = true;
- topIndex = -1;
- bottomIndex = -1;
- }
-
- /**
- * Scrollbar selection event handler.
- */
- private void onScrollSelection()
- {
- topIndex = -1;
- bottomIndex = -1;
- refreshHoverState();
- redraw(getClientArea().x, getClientArea().y, getClientArea().width, getClientArea().height,
- false);
- }
-
- /**
- * Returns the intersection of the given column and given item.
- *
- * @param column column
- * @param item item
- * @return x,y of top left corner of the cell
- */
- Point getOrigin(GridColumn column, GridItem item)
- {
- int x = 0;
-
- if (rowHeaderVisible)
- {
- x += rowHeaderWidth;
- }
-
- x -= getHScrollSelectionInPixels();
-
- for (Iterator colIterIterator = displayOrderedColumns.iterator(); colIterIterator.hasNext(); )
- {
- GridColumn colIter = (GridColumn) colIterIterator.next();
-
- if (colIter == column)
- {
- break;
- }
-
- if (colIter.isVisible())
- {
- x += colIter.getWidth();
- }
- }
-
- int y = 0;
- if (item != null)
- {
- if (columnHeadersVisible)
- {
- y += headerHeight;
- }
-
- int currIndex=getTopIndex();
- int itemIndex=items.indexOf(item);
-
- if (itemIndex == -1)
- {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
-
- while(currIndex!=itemIndex)
- {
- if(currIndex<itemIndex)
- {
- GridItem currItem = (GridItem)items.get(currIndex);
- if(currItem.isVisible())
- {
- y += currItem.getHeight() + 1;
- }
- currIndex++;
- }
- else if(currIndex>itemIndex)
- {
- currIndex--;
- GridItem currItem = (GridItem)items.get(currIndex);
- if(currItem.isVisible())
- {
- y -= currItem.getHeight() + 1;
- }
- }
- }
- }
- else
- {
- if (column.getColumnGroup() != null)
- {
- y += groupHeaderHeight;
- }
- }
-
- return new Point(x, y);
- }
-
- /**
- * Determines (which cell/if a cell) has been clicked (mouse down really)
- * and notifies the appropriate renderer. Returns true when a cell has
- * responded to this event in some way and prevents the event from
- * triggering an action further down the chain (like a selection).
- *
- * @param item item clicked
- * @param x mouse x
- * @param y mouse y
- * @return true if this event has been consumed.
- */
- private boolean handleCellClick(GridItem item, int x, int y)
- {
-
- // if(!isTree)
- // return false;
-
- GridColumn col = getColumn(new Point(x, y));
- if (col == null)
- {
- return false;
- }
-
- col.getCellRenderer().setBounds(item.getBounds(indexOf(col)));
- return col.getCellRenderer().notify(IInternalWidget.LeftMouseButtonDown, new Point(x, y), item);
-
- }
-
- /**
- * Sets the hovering variables (hoverItem,hoveringColumn) as well as
- * hoverDetail by talking to the cell renderers. Triggers a redraw if
- * necessary.
- *
- * @param x mouse x
- * @param y mouse y
- * @return true if a new section of the table is now being hovered
- */
- private boolean handleCellHover(int x, int y)
- {
-
- String detail = "";
-
- boolean overText = false;
-
- final GridColumn col = getColumn(new Point(x, y));
- final GridItem item = getItem(new Point(x, y));
-
- GridColumnGroup hoverColGroup = null;
- GridColumn hoverColHeader = null;
-
- if (col != null)
- {
- if (item != null)
- {
- if( y < getClientArea().height - footerHeight ) {
- col.getCellRenderer().setBounds(item.getBounds(columns.indexOf(col)));
-
- if (col.getCellRenderer().notify(IInternalWidget.MouseMove, new Point(x, y), item))
- {
- detail = col.getCellRenderer().getHoverDetail();
- }
-
- Rectangle textBounds = col.getCellRenderer().getTextBounds(item,false);
-
- if (textBounds != null)
- {
- Point p = new Point(x - col.getCellRenderer().getBounds().x, y - col.getCellRenderer().getBounds().y);
- overText = textBounds.contains(p);
- }
- }
- }
- else
- {
- if (y < headerHeight)
- {
- if (columnGroups.length != 0 && y < groupHeaderHeight
- && col.getColumnGroup() != null)
- {
- hoverColGroup = col.getColumnGroup();
- hoverColGroup.getHeaderRenderer().setBounds(hoverColGroup.getBounds());
- if (hoverColGroup.getHeaderRenderer()
- .notify(IInternalWidget.MouseMove, new Point(x, y), hoverColGroup))
- {
- detail = hoverColGroup.getHeaderRenderer().getHoverDetail();
- }
-
- Rectangle textBounds = hoverColGroup.getHeaderRenderer().getTextBounds(hoverColGroup,false);
-
- if (textBounds != null)
- {
- Point p = new Point(x - hoverColGroup.getHeaderRenderer().getBounds().x, y - hoverColGroup.getHeaderRenderer().getBounds().y);
- overText = textBounds.contains(p);
- }
- }
- else
- {
- // on col header
- hoverColHeader = col;
-
- col.getHeaderRenderer().setBounds(col.getBounds());
- if (col.getHeaderRenderer().notify(IInternalWidget.MouseMove, new Point(x, y),
- col))
- {
- detail = col.getHeaderRenderer().getHoverDetail();
- }
-
- Rectangle textBounds = col.getHeaderRenderer().getTextBounds(col,false);
-
- if (textBounds != null)
- {
- Point p = new Point(x - col.getHeaderRenderer().getBounds().x, y - col.getHeaderRenderer().getBounds().y);
- overText = textBounds.contains(p);
- }
- }
- }
- }
- }
-
- boolean hoverChange = false;
-
- if (hoveringItem != item || !hoveringDetail.equals(detail) || hoveringColumn != col
- || hoverColGroup != hoverColumnGroupHeader || hoverColHeader != hoveringColumnHeader)
- {
- hoveringItem = item;
- hoveringDetail = detail;
- hoveringColumn = col;
- hoveringColumnHeader = hoverColHeader;
- hoverColumnGroupHeader = hoverColGroup;
-
- Rectangle clientArea = getClientArea();
- redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
-
- hoverChange = true;
- }
-
- //do inplace toolTip stuff
- if (hoverChange || hoveringOverText != overText)
- {
- hoveringOverText = overText;
-
- if (overText){
-
- Rectangle cellBounds = null;
- Rectangle textBounds = null;
- Rectangle preferredTextBounds = null;
-
- if (hoveringItem != null && hoveringItem.getToolTipText(indexOf(col)) == null && //no inplace tooltips when regular tooltip
- !col.getWordWrap()) //dont show inplace tooltips for cells with wordwrap
- {
- cellBounds = col.getCellRenderer().getBounds();
- if (cellBounds.x + cellBounds.width > getSize().x)
- {
- cellBounds.width = getSize().x - cellBounds.x;
- }
- textBounds = col.getCellRenderer().getTextBounds(item,false);
- preferredTextBounds = col.getCellRenderer().getTextBounds(item,true);
- }
- else if (hoveringColumnHeader != null && hoveringColumnHeader.getHeaderTooltip() == null) //no inplace tooltips when regular tooltip
- {
- cellBounds = hoveringColumnHeader.getHeaderRenderer().getBounds();
- if (cellBounds.x + cellBounds.width > getSize().x)
- {
- cellBounds.width = getSize().x - cellBounds.x;
- }
- textBounds = hoveringColumnHeader.getHeaderRenderer().getTextBounds(col,false);
- preferredTextBounds = hoveringColumnHeader.getHeaderRenderer().getTextBounds(col,true);
- }
- else if (hoverColumnGroupHeader != null)
- {
- cellBounds = hoverColumnGroupHeader.getHeaderRenderer().getBounds();
- if (cellBounds.x + cellBounds.width > getSize().x)
- {
- cellBounds.width = getSize().x - cellBounds.x;
- }
- textBounds = hoverColumnGroupHeader.getHeaderRenderer().getTextBounds(hoverColumnGroupHeader,false);
- preferredTextBounds = hoverColumnGroupHeader.getHeaderRenderer().getTextBounds(hoverColumnGroupHeader,true);
- }
-
- //if we are truncated
- if (textBounds != null && textBounds.width < preferredTextBounds.width)
- {
- showToolTip(item,col, hoverColumnGroupHeader, new Point(cellBounds.x + textBounds.x,cellBounds.y +
- textBounds.y));
- //the following 2 lines are done here rather than in showToolTip to allow
- //that method to be overridden yet still capture the mouse.
- setCapture(true);
- inplaceTooltipCapture = true;
- }
- }
- else
- {
- hideToolTip();
- }
- }
-
- //do normal cell specific tooltip stuff
- if (hoverChange)
- {
- String newTip = null;
+ if (!column.isVisible()) {
+ colIndex++;
+ if (skipCell) {
+ cellSpanManager.consumeCell(colIndex, row);
+ }
+ continue;
+ }
+
+ int width = item.getCellSize(indexOfColumn).x;
+
+ if (skipCell == false) {
+
+ int nrRowsToSpan = item.getRowSpan(indexOfColumn);
+ int nrColumnsToSpan = item.getColumnSpan(indexOfColumn);
+
+ if (nrRowsToSpan > 0 || nrColumnsToSpan > 0) {
+ cellSpanManager.addCellSpanInfo(colIndex, row, nrColumnsToSpan, nrRowsToSpan);
+ }
+
+ if (x + width >= 0 && x < getClientArea().width) {
+ Point sizeOfColumn = item.getCellSize(indexOfColumn);
+
+ column.getCellRenderer().setBounds(x, y, width, sizeOfColumn.y);
+ int cellInHeaderDelta = columnHeadersVisible ? headerHeight - y : 0;
+ if (cellInHeaderDelta > 0) {
+ e.gc.setClipping(new Rectangle(x - 1, y + cellInHeaderDelta, width + 1, sizeOfColumn.y
+ + 2 - cellInHeaderDelta));
+ }
+ else {
+ e.gc.setClipping(new Rectangle(x - 1, y - 1, width + 1, sizeOfColumn.y + 2));
+ }
+
+ column.getCellRenderer().setRow(i + 1);
+
+ column.getCellRenderer().setSelected(selectedItems.contains(item));
+ column.getCellRenderer().setFocus(this.isFocusControl());
+ column.getCellRenderer().setRowFocus(focusItem == item);
+ column.getCellRenderer().setCellFocus(
+ cellSelectionEnabled && focusItem == item && focusColumn == column);
+
+ column.getCellRenderer().setRowHover(hoveringItem == item);
+ column.getCellRenderer().setColumnHover(hoveringColumn == column);
+
+ column.getCellRenderer().setColumn(indexOfColumn);
+
+ if (selectedCells.contains(new Point(indexOfColumn, row))) {
+ column.getCellRenderer().setCellSelected(true);
+ cellInRowSelected = true;
+ }
+ else {
+ column.getCellRenderer().setCellSelected(false);
+ }
+
+ if (hoveringItem == item && hoveringColumn == column) {
+ column.getCellRenderer().setHoverDetail(hoveringDetail);
+ }
+ else {
+ column.getCellRenderer().setHoverDetail("");
+ }
+
+ column.getCellRenderer().paint(e.gc, item);
+
+ e.gc.setClipping((Rectangle) null);
+
+ // collect the insertMark position
+ if (!insertMarkPosFound && insertMarkItem == item
+ && (insertMarkColumn == null || insertMarkColumn == column)) {
+ // y-pos
+ insertMarkPosY = y - 1;
+ if (!insertMarkBefore)
+ insertMarkPosY += item.getHeight() + 1;
+ // x1-pos
+ insertMarkPosX1 = x;
+ if (column.isTree()) {
+ insertMarkPosX1 += Math.min(width,
+ column.getCellRenderer().getTextBounds(item, false).x);
+ }
+
+ // x2-pos
+ if (insertMarkColumn == null) {
+ insertMarkPosX2 = getClientArea().x + getClientArea().width;
+ }
+ else {
+ insertMarkPosX2 = x + width;
+ }
+
+ insertMarkPosFound = true;
+ }
+ }
+ }
+ else {
+ cellSpanManager.consumeCell(colIndex, row);
+ }
+
+ x += column.getWidth();
+ colIndex++;
+
+ }
+
+ if (x < getClientArea().width) {
+ // insertMarkPos needs correction
+ if (insertMarkPosFound && insertMarkColumn == null)
+ insertMarkPosX2 = x;
+
+ emptyCellRenderer.setSelected(selectedItems.contains(item));
+ emptyCellRenderer.setFocus(this.isFocusControl());
+ emptyCellRenderer.setRow(i + 1);
+ emptyCellRenderer.setBounds(x, y, getClientArea().width - x + 1, item.getHeight());
+ emptyCellRenderer.setColumn(getColumnCount());
+ emptyCellRenderer.paint(e.gc, item);
+ }
+
+ x = 0;
+
+ if (rowHeaderVisible) {
+
+ if (!cellSelectionEnabled) {
+ rowHeaderRenderer.setSelected(selectedItems.contains(item));
+ }
+ else {
+ rowHeaderRenderer.setSelected(cellInRowSelected);
+ }
+ if (y >= headerHeight) {
+ rowHeaderRenderer.setBounds(0, y, rowHeaderWidth, item.getHeight() + 1);
+ rowHeaderRenderer.paint(e.gc, item);
+ }
+ x += rowHeaderWidth;
+ }
+
+ // focus
+ if (isFocusControl() && !cellSelectionEnabled) {
+ if (item == focusItem) {
+ if (focusRenderer != null) {
+ int focusX = 0;
+ if (rowHeaderVisible) {
+ focusX = rowHeaderWidth;
+ }
+ focusRenderer.setBounds(focusX, focusY - 1, getClientArea().width - focusX - 1,
+ item.getHeight() + 1);
+ focusRenderer.paint(e.gc, item);
+ }
+ }
+ }
+
+ y += item.getHeight() + 1;
+ }
+ else {
+
+ if (rowHeaderVisible) {
+ //row header is actually painted later
+ x += rowHeaderWidth;
+ }
+
+ emptyCellRenderer.setBounds(x, y, getClientArea().width - x, getItemHeight());
+ emptyCellRenderer.setFocus(false);
+ emptyCellRenderer.setSelected(false);
+ emptyCellRenderer.setRow(i + 1);
+
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+ GridColumn column = (GridColumn) columnIterator.next();
+
+ if (column.isVisible()) {
+ emptyCellRenderer.setBounds(x, y, column.getWidth(), getItemHeight());
+ emptyCellRenderer.setColumn(indexOf(column));
+ emptyCellRenderer.paint(e.gc, this);
+
+ x += column.getWidth();
+ }
+ }
+
+ if (x < getClientArea().width) {
+ emptyCellRenderer.setBounds(x, y, getClientArea().width - x + 1, getItemHeight());
+ emptyCellRenderer.setColumn(getColumnCount());
+ emptyCellRenderer.paint(e.gc, this);
+ }
+
+ x = 0;
+
+ if (rowHeaderVisible) {
+ emptyRowHeaderRenderer.setBounds(x, y, rowHeaderWidth, getItemHeight() + 1);
+ emptyRowHeaderRenderer.paint(e.gc, this);
+
+ x += rowHeaderWidth;
+ }
+
+ y += getItemHeight() + 1;
+ }
+
+ row++;
+ }
+
+ // draw drop point
+ if (draggingColumn) {
+ if ((dragDropAfterColumn != null || dragDropBeforeColumn != null)
+ && (dragDropAfterColumn != columnBeingPushed && dragDropBeforeColumn != columnBeingPushed)
+ && dragDropPointValid) {
+ if (dragDropBeforeColumn != null) {
+ x = getColumnHeaderXPosition(dragDropBeforeColumn);
+ }
+ else {
+ x = getColumnHeaderXPosition(dragDropAfterColumn) + dragDropAfterColumn.getWidth();
+ }
+
+ Point size = dropPointRenderer.computeSize(e.gc, SWT.DEFAULT, SWT.DEFAULT, null);
+ x -= size.x / 2;
+ if (x < 0) {
+ x = 0;
+ }
+ dropPointRenderer.setBounds(x - 1, headerHeight + DROP_POINT_LOWER_OFFSET, size.x, size.y);
+ dropPointRenderer.paint(e.gc, null);
+ }
+ }
+
+ // draw insertion mark
+ if (insertMarkPosFound) {
+ e.gc.setClipping(rowHeaderVisible ? rowHeaderWidth : 0, columnHeadersVisible ? headerHeight : 0,
+ getClientArea().width, getClientArea().height);
+ insertMarkRenderer.paint(e.gc, new Rectangle(insertMarkPosX1, insertMarkPosY, insertMarkPosX2
+ - insertMarkPosX1, 0));
+ }
+
+ if (columnFootersVisible) {
+ paintFooter(e.gc);
+ }
+ }
+
+ /**
+ * Returns a column reference if the x,y coordinates are over a column
+ * header (header only).
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return column reference which mouse is over, or null.
+ */
+ private GridColumn overColumnHeader(int x, int y) {
+ GridColumn col = null;
+
+ if (y <= headerHeight && y > 0) {
+ col = getColumn(new Point(x, y));
+ if (col != null && col.getColumnGroup() != null) {
+ if (y <= groupHeaderHeight) {
+ return null;
+ }
+ }
+ }
+
+ return col;
+ }
+
+ /**
+ * Returns a column reference if the x,y coordinates are over a column
+ * header (header only).
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return column reference which mouse is over, or null.
+ */
+ private GridColumn overColumnFooter(int x, int y) {
+ GridColumn col = null;
+
+ if (y >= getClientArea().height - footerHeight) {
+ col = getColumn(new Point(x, y));
+ }
+
+ return col;
+ }
+
+ /**
+ * Returns a column group reference if the x,y coordinates are over a column
+ * group header (header only).
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return column group reference which mouse is over, or null.
+ */
+ private GridColumnGroup overColumnGroupHeader(int x, int y) {
+ GridColumnGroup group = null;
+
+ if (y <= groupHeaderHeight && y > 0) {
+ GridColumn col = getColumn(new Point(x, y));
+ if (col != null) {
+ group = col.getColumnGroup();
+ }
+ }
+
+ return group;
+ }
+
+ /**
+ * Paints the header.
+ *
+ * @param gc gc from paint event
+ */
+ private void paintHeader(GC gc) {
+ int x = 0;
+ int y = 0;
+
+ x -= getHScrollSelectionInPixels();
+
+ if (rowHeaderVisible) {
+ // paint left corner
+ // topLeftRenderer.setBounds(0, y, rowHeaderWidth, headerHeight);
+ // topLeftRenderer.paint(gc, null);
+ x += rowHeaderWidth;
+ }
+
+ GridColumnGroup previousPaintedGroup = null;
+
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+ if (x > getClientArea().width)
+ break;
+
+ GridColumn column = (GridColumn) columnIterator.next();
+ int height = 0;
+
+ if (!column.isVisible()) {
+ continue;
+ }
+
+ if (column.getColumnGroup() != null) {
+
+ if (column.getColumnGroup() != previousPaintedGroup) {
+ int width = column.getWidth();
+
+ GridColumn nextCol = null;
+ if (displayOrderedColumns.indexOf(column) + 1 < displayOrderedColumns.size()) {
+ nextCol = (GridColumn) displayOrderedColumns.get(displayOrderedColumns.indexOf(column) + 1);
+ }
+
+ while (nextCol != null && nextCol.getColumnGroup() == column.getColumnGroup()) {
+
+ if ((nextCol.getColumnGroup().getExpanded() && !nextCol.isDetail())
+ || (!nextCol.getColumnGroup().getExpanded() && !nextCol.isSummary())) {
+ }
+ else if (nextCol.isVisible()) {
+ width += nextCol.getWidth();
+ }
+
+ if (displayOrderedColumns.indexOf(nextCol) + 1 < displayOrderedColumns.size()) {
+ nextCol = (GridColumn) displayOrderedColumns
+ .get(displayOrderedColumns.indexOf(nextCol) + 1);
+ }
+ else {
+ nextCol = null;
+ }
+ }
+
+ boolean selected = true;
+
+ for (int i = 0; i < column.getColumnGroup().getColumns().length; i++) {
+ GridColumn col = column.getColumnGroup().getColumns()[i];
+ if (col.isVisible() && (column.getMoveable() || !selectedColumns.contains(col))) {
+ selected = false;
+ break;
+ }
+ }
+
+ column.getColumnGroup().getHeaderRenderer().setSelected(selected);
+ column.getColumnGroup().getHeaderRenderer()
+ .setHover(hoverColumnGroupHeader == column.getColumnGroup());
+ column.getColumnGroup().getHeaderRenderer().setHoverDetail(hoveringDetail);
+
+ column.getColumnGroup().getHeaderRenderer().setBounds(x, 0, width, groupHeaderHeight);
+
+ column.getColumnGroup().getHeaderRenderer().paint(gc, column.getColumnGroup());
+
+ previousPaintedGroup = column.getColumnGroup();
+ }
+
+ height = headerHeight - groupHeaderHeight;
+ y = groupHeaderHeight;
+ }
+ else {
+ height = headerHeight;
+ y = 0;
+ }
+
+ if (pushingColumn) {
+ column.getHeaderRenderer().setHover(columnBeingPushed == column && pushingAndHovering);
+ }
+ else {
+ column.getHeaderRenderer().setHover(hoveringColumnHeader == column);
+ }
+
+ column.getHeaderRenderer().setHoverDetail(hoveringDetail);
+
+ column.getHeaderRenderer().setBounds(x, y, column.getWidth(), height);
+
+ if (cellSelectionEnabled)
+ column.getHeaderRenderer().setSelected(selectedColumns.contains(column));
+
+ if (x + column.getWidth() >= 0) {
+ column.getHeaderRenderer().paint(gc, column);
+ }
+
+ x += column.getWidth();
+ }
+
+ if (x < getClientArea().width) {
+ emptyColumnHeaderRenderer.setBounds(x, 0, getClientArea().width - x, headerHeight);
+ emptyColumnHeaderRenderer.paint(gc, null);
+ }
+
+ x = 0;
+
+ if (rowHeaderVisible) {
+ // paint left corner
+ topLeftRenderer.setBounds(0, 0, rowHeaderWidth, headerHeight);
+ topLeftRenderer.paint(gc, this);
+ x += rowHeaderWidth;
+ }
+
+ if (draggingColumn) {
+
+ gc.setAlpha(COLUMN_DRAG_ALPHA);
+
+ columnBeingPushed.getHeaderRenderer().setSelected(false);
+
+ int height = 0;
+
+ if (columnBeingPushed.getColumnGroup() != null) {
+ height = headerHeight - groupHeaderHeight;
+ y = groupHeaderHeight;
+ }
+ else {
+ height = headerHeight;
+ y = 0;
+ }
+
+ columnBeingPushed.getHeaderRenderer().setBounds(
+ getColumnHeaderXPosition(columnBeingPushed) + (currentHeaderDragX - startHeaderDragX), y,
+ columnBeingPushed.getWidth(), height);
+ columnBeingPushed.getHeaderRenderer().paint(gc, columnBeingPushed);
+ columnBeingPushed.getHeaderRenderer().setSelected(false);
+
+ gc.setAlpha(-1);
+ gc.setAdvanced(false);
+ }
+
+ }
+
+ private void paintFooter(GC gc) {
+ int x = 0;
+ int y = 0;
+
+ x -= getHScrollSelectionInPixels();
+
+ if (rowHeaderVisible) {
+ // paint left corner
+ // topLeftRenderer.setBounds(0, y, rowHeaderWidth, headerHeight);
+ // topLeftRenderer.paint(gc, null);
+ x += rowHeaderWidth;
+ }
+
+ for (Iterator columnIterator = displayOrderedColumns.iterator(); columnIterator.hasNext();) {
+ if (x > getClientArea().width)
+ break;
+
+ GridColumn column = (GridColumn) columnIterator.next();
+ int height = 0;
+
+ if (!column.isVisible()) {
+ continue;
+ }
+
+ height = footerHeight;
+ y = getClientArea().height - height;
+
+ column.getFooterRenderer().setBounds(x, y, column.getWidth(), height);
+ if (x + column.getWidth() >= 0) {
+ column.getFooterRenderer().paint(gc, column);
+ }
+
+ x += column.getWidth();
+ }
+
+ if (x < getClientArea().width) {
+ emptyColumnFooterRenderer.setBounds(x, getClientArea().height - footerHeight, getClientArea().width - x,
+ footerHeight);
+ emptyColumnFooterRenderer.paint(gc, null);
+ }
+
+ if (rowHeaderVisible) {
+ // paint left corner
+ bottomLeftRenderer.setBounds(0, getClientArea().height - footerHeight, rowHeaderWidth, footerHeight);
+ bottomLeftRenderer.paint(gc, this);
+ x += rowHeaderWidth;
+ }
+ }
+
+ /**
+ * Manages the state of the scrollbars when new items are added or the
+ * bounds are changed.
+ */
+ private void updateScrollbars() {
+ Point preferredSize = getTableSize();
+
+ Rectangle clientArea = getClientArea();
+
+ // First, figure out if the scrollbars should be visible and turn them
+ // on right away
+ // this will allow the computations further down to accommodate the
+ // correct client
+ // area
+
+ // Turn the scrollbars on if necessary and do it all over again if
+ // necessary. This ensures
+ // that if a scrollbar is turned on/off, the other scrollbar's
+ // visibility may be affected (more
+ // area may have been added/removed.
+ for (int doublePass = 1; doublePass <= 2; doublePass++) {
+
+ if (preferredSize.y > clientArea.height) {
+ vScroll.setVisible(true);
+ }
+ else {
+ vScroll.setVisible(false);
+ vScroll.setValues(0, 0, 1, 1, 1, 1);
+ }
+ if (preferredSize.x > clientArea.width) {
+ hScroll.setVisible(true);
+ }
+ else {
+ hScroll.setVisible(false);
+ hScroll.setValues(0, 0, 1, 1, 1, 1);
+ }
+
+ // get the clientArea again with the now visible/invisible
+ // scrollbars
+ clientArea = getClientArea();
+ }
+
+ // if the scrollbar is visible set its values
+ if (vScroll.getVisible()) {
+ int max = currentVisibleItems;
+ int thumb = 1;
+
+ if (!hasDifferingHeights) {
+ // in this case, the number of visible rows on screen is constant,
+ // so use this as thumb
+ thumb = (getVisibleGridHeight() + 1) / (getItemHeight() + 1);
+ }
+ else {
+ // in this case, the number of visible rows on screen is variable,
+ // so we have to use 1 as thumb and decrease max by the number of
+ // rows on the last page
+ if (getVisibleGridHeight() >= 1) {
+ RowRange range = getRowRange(-1, getVisibleGridHeight(), true, true);
+ max -= range.rows - 1;
+ }
+ }
+
+ // if possible, remember selection, if selection is too large, just
+ // make it the max you can
+ int selection = Math.min(vScroll.getSelection(), max);
+
+ vScroll.setValues(selection, 0, max, thumb, 1, thumb);
+ }
+
+ // if the scrollbar is visible set its values
+ if (hScroll.getVisible()) {
+
+ if (!columnScrolling) {
+ // horizontal scrolling works pixel by pixel
+
+ int hiddenArea = preferredSize.x - clientArea.width + 1;
+
+ // if possible, remember selection, if selection is too large,
+ // just
+ // make it the max you can
+ int selection = Math.min(hScroll.getSelection(), hiddenArea - 1);
+
+ hScroll.setValues(selection, 0, hiddenArea + clientArea.width - 1, clientArea.width,
+ HORZ_SCROLL_INCREMENT, clientArea.width);
+ }
+ else {
+ // horizontal scrolling is column by column
+
+ int hiddenArea = preferredSize.x - clientArea.width + 1;
+
+ int max = 0;
+ int i = 0;
+
+ while (hiddenArea > 0 && i < getColumnCount()) {
+ GridColumn col = (GridColumn) displayOrderedColumns.get(i);
+
+ i++;
+
+ if (col.isVisible()) {
+ hiddenArea -= col.getWidth();
+ max++;
+ }
+ }
+
+ max++;
+
+ // max should never be greater than the number of visible cols
+ int visCols = 0;
+ for (Iterator iter = columns.iterator(); iter.hasNext();) {
+ GridColumn element = (GridColumn) iter.next();
+ if (element.isVisible()) {
+ visCols++;
+ }
+ }
+ max = Math.min(visCols, max);
+
+ // if possible, remember selection, if selection is too large,
+ // just
+ // make it the max you can
+ int selection = Math.min(hScroll.getSelection(), max);
+
+ hScroll.setValues(selection, 0, max, 1, 1, 1);
+ }
+ }
+
+ }
+
+ /**
+ * Adds/removes items from the selected items list based on the
+ * selection/deselection of the given item.
+ *
+ * @param item item being selected/unselected
+ * @param stateMask key state during selection
+ *
+ * @return selection event that needs to be fired or null
+ */
+ private Event updateSelection(GridItem item, int stateMask) {
+ if (!selectionEnabled) {
+ return null;
+ }
+
+ Event selectionEvent = null;
+
+ if (selectionType == SWT.SINGLE) {
+ if (selectedItems.contains(item)) {
+ // Deselect when pressing CTRL
+ if ((stateMask & SWT.MOD1) == SWT.MOD1) {
+ selectedItems.clear();
+ }
+ }
+ else {
+ selectedItems.clear();
+ selectedItems.add(item);
+ }
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ selectionEvent = new Event();
+ selectionEvent.item = item;
+ }
+ else if (selectionType == SWT.MULTI) {
+ boolean shift = false;
+ boolean ctrl = false;
+
+ if ((stateMask & SWT.MOD2) == SWT.MOD2) {
+ shift = true;
+ }
+
+ if ((stateMask & SWT.MOD1) == SWT.MOD1) {
+ ctrl = true;
+ }
+
+ if (!shift && !ctrl) {
+ if (selectedItems.size() == 1 && selectedItems.contains(item))
+ return null;
+
+ selectedItems.clear();
+
+ selectedItems.add(item);
+
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ shiftSelectionAnchorItem = null;
+
+ selectionEvent = new Event();
+ selectionEvent.item = item;
+ }
+ else if (shift) {
+
+ if (shiftSelectionAnchorItem == null) {
+ shiftSelectionAnchorItem = focusItem;
+ }
+
+ // if (shiftSelectionAnchorItem == item)
+ // {
+ // return;
+ // }
+
+ boolean maintainAnchorSelection = false;
+
+ if (!ctrl) {
+ if (selectedItems.contains(shiftSelectionAnchorItem)) {
+ maintainAnchorSelection = true;
+ }
+ selectedItems.clear();
+ }
+
+ int anchorIndex = items.indexOf(shiftSelectionAnchorItem);
+ int itemIndex = items.indexOf(item);
+
+ int min = 0;
+ int max = 0;
+
+ if (anchorIndex < itemIndex) {
+ if (maintainAnchorSelection) {
+ min = anchorIndex;
+ }
+ else {
+ min = anchorIndex + 1;
+ }
+ max = itemIndex;
+ }
+ else {
+ if (maintainAnchorSelection) {
+ max = anchorIndex;
+ }
+ else {
+ max = anchorIndex - 1;
+ }
+ min = itemIndex;
+ }
+
+ for (int i = min; i <= max; i++) {
+ if (!selectedItems.contains(items.get(i)) && ((GridItem) items.get(i)).isVisible()) {
+ selectedItems.add(items.get(i));
+ }
+ }
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ selectionEvent = new Event();
+ }
+ else if (ctrl) {
+ if (selectedItems.contains(item)) {
+ selectedItems.remove(item);
+ }
+ else {
+ selectedItems.add(item);
+ }
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ shiftSelectionAnchorItem = null;
+
+ selectionEvent = new Event();
+ selectionEvent.item = item;
+ }
+ }
+
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ return selectionEvent;
+ }
+
+ /**
+ * Updates cell selection.
+ *
+ * @param newCell newly clicked, navigated to cell.
+ * @param stateMask statemask during preceeding mouse or key event.
+ * @param dragging true if the user is dragging.
+ * @param reverseDuplicateSelections true if the user is reversing selection rather than adding to.
+ *
+ * @return selection event that will need to be fired or null.
+ */
+ private Event updateCellSelection(Point newCell, int stateMask, boolean dragging, boolean reverseDuplicateSelections) {
+ Vector v = new Vector();
+ v.add(newCell);
+ return updateCellSelection(v, stateMask, dragging, reverseDuplicateSelections);
+ }
+
+ /**
+ * Updates cell selection.
+ *
+ * @param newCell newly clicked, navigated to cells.
+ * @param stateMask statemask during preceeding mouse or key event.
+ * @param dragging true if the user is dragging.
+ * @param reverseDuplicateSelections true if the user is reversing selection rather than adding to.
+ *
+ * @return selection event that will need to be fired or null.
+ */
+ private Event updateCellSelection(Vector newCells, int stateMask, boolean dragging,
+ boolean reverseDuplicateSelections) {
+ boolean shift = false;
+ boolean ctrl = false;
+
+ if ((stateMask & SWT.MOD2) == SWT.MOD2) {
+ shift = true;
+ }
+ else {
+ shiftSelectionAnchorColumn = null;
+ shiftSelectionAnchorItem = null;
+ }
+
+ if ((stateMask & SWT.MOD1) == SWT.MOD1) {
+ ctrl = true;
+ }
+
+ if (!shift && !ctrl) {
+ if (newCells.equals(selectedCells))
+ return null;
+
+ selectedCells.clear();
+ for (int i = 0; i < newCells.size(); i++) {
+ addToCellSelection((Point) newCells.get(i));
+ }
+
+ }
+ else if (shift) {
+
+ Point newCell = (Point) newCells.get(0); //shift selection should only occur with one
+ //cell, ignoring others
+
+ if ((focusColumn == null) || (focusItem == null)) {
+ return null;
+ }
+
+ shiftSelectionAnchorColumn = getColumn(newCell.x);
+ shiftSelectionAnchorItem = getItem(newCell.y);
+
+ if (ctrl) {
+ selectedCells.clear();
+ selectedCells.addAll(selectedCellsBeforeRangeSelect);
+ }
+ else {
+ selectedCells.clear();
+ }
+
+ GridColumn currentColumn = focusColumn;
+ GridItem currentItem = focusItem;
+
+ GridColumn endColumn = getColumn(newCell.x);
+ GridItem endItem = getItem(newCell.y);
+
+ Point newRange = getSelectionRange(currentItem, currentColumn, endItem, endColumn);
+
+ currentColumn = getColumn(newRange.x);
+ endColumn = getColumn(newRange.y);
+
+ GridColumn startCol = currentColumn;
+
+ if (indexOf(currentItem) > indexOf(endItem)) {
+ GridItem temp = currentItem;
+ currentItem = endItem;
+ endItem = temp;
+ }
+
+ boolean firstLoop = true;
+
+ do {
+ if (!firstLoop) {
+ currentItem = getNextVisibleItem(currentItem);
+ }
+
+ firstLoop = false;
+
+ boolean firstLoop2 = true;
+
+ currentColumn = startCol;
+
+ do {
+ if (!firstLoop2) {
+ int index = displayOrderedColumns.indexOf(currentColumn) + 1;
+
+ if (index < displayOrderedColumns.size()) {
+ currentColumn = getVisibleColumn_DegradeRight(currentItem,
+ (GridColumn) displayOrderedColumns.get(index));
+ }
+ else {
+ currentColumn = null;
+ }
+
+ if (currentColumn != null)
+ if (displayOrderedColumns.indexOf(currentColumn) > displayOrderedColumns.indexOf(endColumn))
+ currentColumn = null;
+ }
+
+ firstLoop2 = false;
+
+ if (currentColumn != null) {
+ Point cell = new Point(indexOf(currentColumn), indexOf(currentItem));
+ addToCellSelection(cell);
+ }
+ }
+ while (currentColumn != endColumn && currentColumn != null);
+ }
+ while (currentItem != endItem);
+ }
+ else if (ctrl) {
+ boolean reverse = reverseDuplicateSelections;
+ if (!selectedCells.containsAll(newCells))
+ reverse = false;
+
+ if (dragging) {
+ selectedCells.clear();
+ selectedCells.addAll(selectedCellsBeforeRangeSelect);
+ }
+
+ if (reverse) {
+ selectedCells.removeAll(newCells);
+ }
+ else {
+ for (int i = 0; i < newCells.size(); i++) {
+ addToCellSelection((Point) newCells.get(i));
+ }
+ }
+ }
+
+ updateColumnSelection();
+
+ Event e = new Event();
+ if (dragging) {
+ e.detail = SWT.DRAG;
+ followupCellSelectionEventOwed = true;
+ }
+
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ return e;
+ }
+
+ private void addToCellSelection(Point newCell) {
+ if (newCell.x < 0 || newCell.x >= columns.size())
+ return;
+
+ if (newCell.y < 0 || newCell.y >= items.size())
+ return;
+
+ if (getColumn(newCell.x).getCellSelectionEnabled()) {
+ Iterator it = selectedCells.iterator();
+ boolean found = false;
+ while (it.hasNext()) {
+ Point p = (Point) it.next();
+ if (newCell.equals(p)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ selectedCells.add(newCell);
+ }
+ }
+ }
+
+ void updateColumnSelection() {
+ //Update the list of which columns have all their cells selected
+ selectedColumns.clear();
+
+ for (Iterator iter = selectedCells.iterator(); iter.hasNext();) {
+ Point cell = (Point) iter.next();
+
+ GridColumn col = getColumn(cell.x);
+
+ selectedColumns.add(col);
+ }
+ }
+
+ /**
+ * Initialize all listeners.
+ */
+ private void initListeners() {
+ disposeListener = new Listener() {
+ @Override
+ public void handleEvent(Event e) {
+ onDispose(e);
+ }
+ };
+ addListener(SWT.Dispose, disposeListener);
+
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(PaintEvent e) {
+ onPaint(e);
+ }
+ });
+
+ addListener(SWT.Resize, new Listener() {
+ @Override
+ public void handleEvent(Event e) {
+ onResize();
+ }
+ });
+
+ if (getVerticalBar() != null) {
+ getVerticalBar().addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event e) {
+ onScrollSelection();
+ }
+ });
+ }
+
+ if (getHorizontalBar() != null) {
+ getHorizontalBar().addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event e) {
+ onScrollSelection();
+ }
+ });
+ }
+
+ addListener(SWT.KeyDown, new Listener() {
+ @Override
+ public void handleEvent(Event e) {
+ onKeyDown(e);
+ }
+ });
+
+ addTraverseListener(new TraverseListener() {
+ @Override
+ public void keyTraversed(TraverseEvent e) {
+ e.doit = true;
+ }
+ });
+
+ addMouseListener(new MouseListener() {
+ @Override
+ public void mouseDoubleClick(MouseEvent e) {
+ onMouseDoubleClick(e);
+ }
+
+ @Override
+ public void mouseDown(MouseEvent e) {
+ onMouseDown(e);
+ }
+
+ @Override
+ public void mouseUp(MouseEvent e) {
+ onMouseUp(e);
+ }
+ });
+
+ addMouseMoveListener(new MouseMoveListener() {
+ @Override
+ public void mouseMove(MouseEvent e) {
+ onMouseMove(e);
+ }
+ });
+
+ addMouseTrackListener(new MouseTrackListener() {
+ @Override
+ public void mouseEnter(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExit(MouseEvent e) {
+ onMouseExit(e);
+ }
+
+ @Override
+ public void mouseHover(MouseEvent e) {
+ }
+ });
+
+ addFocusListener(new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ onFocusIn();
+ redraw();
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ redraw();
+ }
+ });
+
+ // Special code to reflect mouse wheel events if using an external
+ // scroller
+ addListener(SWT.MouseWheel, new Listener() {
+ @Override
+ public void handleEvent(Event e) {
+ onMouseWheel(e);
+ }
+ });
+ }
+
+ private void onFocusIn() {
+ if (!items.isEmpty() && focusItem == null) {
+ focusItem = (GridItem) items.get(0);
+ }
+ }
+
+ private void onDispose(Event event) {
+ //We only want to dispose of our items and such *after* anybody else who may have been
+ //listening to the dispose has had a chance to do whatever.
+ removeListener(SWT.Dispose, disposeListener);
+ notifyListeners(SWT.Dispose, event);
+ event.type = SWT.None;
+
+ disposing = true;
+
+ cellHeaderSelectionBackground.dispose();
+
+ for (Iterator iterator = items.iterator(); iterator.hasNext();) {
+ GridItem item = (GridItem) iterator.next();
+ item.dispose();
+ }
+
+ for (int i = 0; i < columnGroups.length; i++) {
+ columnGroups[i].dispose();
+ }
+
+ for (Iterator iterator = columns.iterator(); iterator.hasNext();) {
+ GridColumn col = (GridColumn) iterator.next();
+ col.dispose();
+ }
+
+ sizingGC.dispose();
+ }
+
+ /**
+ * Mouse wheel event handler.
+ *
+ * @param e event
+ */
+ private void onMouseWheel(Event e) {
+ if (vScroll.getVisible()) {
+ vScroll.handleMouseWheel(e);
+ if (getVerticalBar() == null)
+ e.doit = false;
+ }
+ else if (hScroll.getVisible()) {
+ hScroll.handleMouseWheel(e);
+ if (getHorizontalBar() == null)
+ e.doit = false;
+ }
+ }
+
+ /**
+ * Mouse down event handler.
+ *
+ * @param e event
+ */
+ private void onMouseDown(MouseEvent e) {
+ // for some reason, SWT prefers the children to get focus if
+ // there are any children
+ // the setFocus method on Composite will not set focus to the
+ // Composite if one of its
+ // children can get focus instead. This only affects the table
+ // when an editor is open
+ // and therefore the table has a child. The solution is to
+ // forceFocus()
+ if ((getStyle() & SWT.NO_FOCUS) != SWT.NO_FOCUS) {
+ forceFocus();
+ }
+
+ hideToolTip();
+
+ //if populated will be fired at end of method.
+ Event selectionEvent = null;
+
+ cellSelectedOnLastMouseDown = false;
+ cellRowSelectedOnLastMouseDown = false;
+ cellColumnSelectedOnLastMouseDown = false;
+
+ if (hoveringOnColumnResizer) {
+ if (e.button == 1) {
+ resizingColumn = true;
+ resizingStartX = e.x;
+ resizingColumnStartWidth = columnBeingResized.getWidth();
+ }
+ return;
+ }
+ if (rowsResizeable && hoveringOnRowResizer) {
+ if (e.button == 1) {
+ resizingRow = true;
+ resizingStartY = e.y;
+ resizingRowStartHeight = rowBeingResized.getHeight();
+ }
+ return;
+ }
+
+ if (e.button == 1 && handleColumnHeaderPush(e.x, e.y)) {
+ return;
+ }
+
+ if (e.button == 1 && handleColumnGroupHeaderClick(e.x, e.y)) {
+ return;
+ }
+
+ if (e.button == 1 && handleColumnFooterPush(e.x, e.y)) {
+ return;
+ }
+
+ GridItem item = getItem(new Point(e.x, e.y));
+
+ if (e.button == 1 && item != null && handleCellClick(item, e.x, e.y)) {
+ return;
+ }
+
+ if (isListening(SWT.DragDetect)) {
+ if ((cellSelectionEnabled && hoveringOnSelectionDragArea)
+ || (!cellSelectionEnabled && item != null && selectedItems.contains(item))) {
+ if (dragDetect(e)) {
+ return;
+ }
+ }
+ }
+
+ if (item != null) {
+ if (cellSelectionEnabled) {
+ GridColumn col = getColumn(new Point(e.x, e.y));
+ boolean isSelectedCell = false;
+ if (col != null)
+ isSelectedCell = selectedCells.contains(new Point(indexOf(col), indexOf(item)));
+
+ if (e.button == 1 || (e.button == 3 && col != null && !isSelectedCell)) {
+ if (col != null) {
+ selectionEvent = updateCellSelection(new Point(indexOf(col), indexOf(item)), e.stateMask,
+ false, true);
+ cellSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
+
+ if (e.stateMask != SWT.MOD2) {
+ focusColumn = col;
+ focusItem = item;
+ }
+ //showColumn(col);
+ showItem(item);
+ redraw();
+ }
+ else if (rowHeaderVisible) {
+ if (e.x <= rowHeaderWidth) {
+
+ boolean shift = ((e.stateMask & SWT.MOD2) != 0);
+ boolean ctrl = false;
+ if (!shift) {
+ ctrl = ((e.stateMask & SWT.MOD1) != 0);
+ }
+
+ Vector cells = new Vector();
+
+ if (shift) {
+ getCells(item, focusItem, cells);
+ }
+ else {
+ getCells(item, cells);
+ }
+
+ int newStateMask = SWT.NONE;
+ if (ctrl)
+ newStateMask = SWT.MOD1;
+
+ selectionEvent = updateCellSelection(cells, newStateMask, shift, ctrl);
+ cellRowSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
+
+ if (!shift) {
+ //set focus back to the first visible column
+ focusColumn = getColumn(new Point(rowHeaderWidth + 1, e.y));
+
+ focusItem = item;
+ }
+ showItem(item);
+ redraw();
+ }
+ }
+ intendedFocusColumn = focusColumn;
+ }
+ }
+ else {
+ if (e.button == 2 || e.button > 3) {
+ return;
+ }
+
+ if (e.button == 3 && selectionType == SWT.MULTI) {
+ if ((e.stateMask & SWT.MOD2) == SWT.MOD2) {
+ return;
+ }
+
+ if ((e.stateMask & SWT.MOD1) == SWT.MOD1) {
+ return;
+ }
+
+ if (selectedItems.contains(item)) {
+ return;
+ }
+ }
+ selectionEvent = updateSelection(item, e.stateMask);
+
+ focusItem = item;
+ showItem(item);
+ redraw();
+ }
+ }
+ else if (e.button == 1 && rowHeaderVisible && e.x <= rowHeaderWidth && e.y < headerHeight) {
+ // Nothing to select
+ if (items.size() == 0) {
+ return;
+ }
+ if (cellSelectionEnabled) {
+ //click on the top left corner means select everything
+ selectionEvent = selectAllCellsInternal();
+
+ focusColumn = getColumn(new Point(rowHeaderWidth + 1, 1));
+ }
+ else {
+ //click on the top left corner means select everything
+ selectionEvent = selectAllRowsInternal();
+ }
+ focusItem = getItem(getTopIndex());
+ }
+ else if (cellSelectionEnabled && e.button == 1 && columnHeadersVisible && e.y <= headerHeight) {
+ //column cell selection
+ GridColumn col = getColumn(new Point(e.x, e.y));
+
+ if (col == null)
+ return;
+
+ if (getItemCount() == 0)
+ return;
+
+ Vector cells = new Vector();
+
+ GridColumnGroup group = col.getColumnGroup();
+ if (group != null && e.y < groupHeaderHeight) {
+ getCells(group, cells);
+ }
+ else {
+ getCells(col, cells);
+ }
+
+ selectionEvent = updateCellSelection(cells, e.stateMask, false, true);
+ cellColumnSelectedOnLastMouseDown = (getCellSelectionCount() > 0);
+
+ GridItem newFocusItem = getItem(0);
+
+ while (newFocusItem != null && getSpanningColumn(newFocusItem, col) != null) {
+ newFocusItem = getNextVisibleItem(newFocusItem);
+ }
+
+ if (newFocusItem != null) {
+ focusColumn = col;
+ focusItem = newFocusItem;
+ }
+
+ showColumn(col);
+ redraw();
+ }
+
+ if (selectionEvent != null) {
+ selectionEvent.stateMask = e.stateMask;
+ selectionEvent.button = e.button;
+ selectionEvent.item = item;
+ selectionEvent.x = e.x;
+ selectionEvent.y = e.y;
+ notifyListeners(SWT.Selection, selectionEvent);
+
+ if (!cellSelectionEnabled) {
+ if (isListening(SWT.DragDetect)) {
+ dragDetect(e);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Mouse double click event handler.
+ *
+ * @param e event
+ */
+ private void onMouseDoubleClick(MouseEvent e) {
+ if (e.button == 1) {
+
+ if (hoveringOnColumnResizer) {
+ columnBeingResized.pack();
+ columnBeingResized.fireResized();
+ for (int index = displayOrderedColumns.indexOf(columnBeingResized) + 1; index < displayOrderedColumns
+ .size(); index++) {
+ GridColumn col = (GridColumn) displayOrderedColumns.get(index);
+ if (col.isVisible())
+ col.fireMoved();
+ }
+ resizingColumn = false;
+ handleHoverOnColumnResizer(e.x, e.y);
+ return;
+ }
+ else if (rowsResizeable && hoveringOnRowResizer) {
+ List sel = Arrays.asList(getSelection());
+ if (sel.contains(rowBeingResized)) {
+ // the user double-clicked a row resizer of a selected row
+ // so update all selected rows
+ for (int cnt = 0; cnt < sel.size(); cnt++)
+ ((GridItem) sel.get(cnt)).pack();
+ redraw();
+ }
+ else {
+ // otherwise only update the row the user double-clicked
+ rowBeingResized.pack();
+ }
+
+ resizingRow = false;
+ handleHoverOnRowResizer(e.x, e.y);
+ return;
+ }
+
+ GridItem item = getItem(new Point(e.x, e.y));
+ if (item != null) {
+ if (isListening(SWT.DefaultSelection)) {
+ Event newEvent = new Event();
+ newEvent.item = item;
+
+ notifyListeners(SWT.DefaultSelection, newEvent);
+ }
+ else if (item.getItemCount() > 0) {
+ item.setExpanded(!item.isExpanded());
+
+ if (item.isExpanded()) {
+ item.fireEvent(SWT.Expand);
+ }
+ else {
+ item.fireEvent(SWT.Collapse);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Mouse up handler.
+ *
+ * @param e event
+ */
+ private void onMouseUp(MouseEvent e) {
+ cellSelectedOnLastMouseDown = false;
+
+ if (resizingColumn) {
+ resizingColumn = false;
+ handleHoverOnColumnResizer(e.x, e.y); // resets cursor if
+ // necessary
+ return;
+ }
+ if (resizingRow) {
+ resizingRow = false;
+ handleHoverOnRowResizer(e.x, e.y); // resets cursor if
+ // necessary
+ return;
+ }
+
+ if (pushingColumn) {
+ pushingColumn = false;
+ columnBeingPushed.getHeaderRenderer().setMouseDown(false);
+ columnBeingPushed.getHeaderRenderer().setHover(false);
+ redraw();
+ if (pushingAndHovering) {
+ columnBeingPushed.fireListeners();
+ }
+ setCapture(false);
+ return;
+ }
+
+ if (draggingColumn) {
+ handleColumnDrop();
+ return;
+ }
+
+ if (cellDragSelectionOccuring || cellRowDragSelectionOccuring || cellColumnDragSelectionOccuring) {
+ cellDragSelectionOccuring = false;
+ cellRowDragSelectionOccuring = false;
+ cellColumnDragSelectionOccuring = false;
+ setCursor(null);
+
+ if (followupCellSelectionEventOwed) {
+ Event se = new Event();
+ se.button = e.button;
+ se.item = getItem(new Point(e.x, e.y));
+ se.stateMask = e.stateMask;
+ se.x = e.x;
+ se.y = e.y;
+
+ notifyListeners(SWT.Selection, se);
+ followupCellSelectionEventOwed = false;
+ }
+ }
+ }
+
+ /**
+ * Mouse move event handler.
+ *
+ * @param e event
+ */
+ private void onMouseMove(MouseEvent e) {
+ //check to see if the mouse is outside the grid
+ //this should only happen when the mouse is captured for inplace
+ //tooltips - see bug 203364
+ if (inplaceTooltipCapture && (e.x < 0 || e.y < 0 || e.x >= getBounds().width || e.y >= getBounds().height)) {
+ setCapture(false);
+ inplaceTooltipCapture = false;
+ return; //a mouseexit event should occur immediately
+ }
+
+ //if populated will be fired at end of method.
+ Event selectionEvent = null;
+
+ if ((e.stateMask & SWT.BUTTON1) == 0) {
+ handleHovering(e.x, e.y);
+ }
+ else {
+ if (draggingColumn) {
+ handleColumnDragging(e.x);
+ return;
+ }
+
+ if (resizingColumn) {
+ handleColumnResizerDragging(e.x);
+ return;
+ }
+ if (resizingRow) {
+ handleRowResizerDragging(e.y);
+ return;
+ }
+ if (pushingColumn) {
+ handleColumnHeaderHoverWhilePushing(e.x, e.y);
+ return;
+ }
+ if (cellSelectionEnabled) {
+ if (!cellDragSelectionOccuring && cellSelectedOnLastMouseDown) {
+ cellDragSelectionOccuring = true;
+ //XXX: make this user definable
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
+ cellDragCTRL = ((e.stateMask & SWT.MOD1) != 0);
+ if (cellDragCTRL) {
+ selectedCellsBeforeRangeSelect.clear();
+ selectedCellsBeforeRangeSelect.addAll(selectedCells);
+ }
+ }
+ if (!cellRowDragSelectionOccuring && cellRowSelectedOnLastMouseDown) {
+ cellRowDragSelectionOccuring = true;
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
+ cellDragCTRL = ((e.stateMask & SWT.MOD1) != 0);
+ if (cellDragCTRL) {
+ selectedCellsBeforeRangeSelect.clear();
+ selectedCellsBeforeRangeSelect.addAll(selectedCells);
+ }
+ }
+
+ if (!cellColumnDragSelectionOccuring && cellColumnSelectedOnLastMouseDown) {
+ cellColumnDragSelectionOccuring = true;
+ setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
+ cellDragCTRL = ((e.stateMask & SWT.MOD1) != 0);
+ if (cellDragCTRL) {
+ selectedCellsBeforeRangeSelect.clear();
+ selectedCellsBeforeRangeSelect.addAll(selectedCells);
+ }
+ }
+
+ int ctrlFlag = (cellDragCTRL ? SWT.MOD1 : SWT.NONE);
+
+ if (cellDragSelectionOccuring && handleCellHover(e.x, e.y)) {
+ GridColumn intentColumn = hoveringColumn;
+ GridItem intentItem = hoveringItem;
+
+ if (hoveringItem == null) {
+ if (e.y > headerHeight) {
+ //then we must be hovering way to the bottom
+ intentItem = getPreviousVisibleItem(null);
+ }
+ else {
+ intentItem = (GridItem) items.get(0);
+ }
+ }
+
+ if (hoveringColumn == null) {
+ if (e.x > rowHeaderWidth) {
+ //then we must be hovering way to the right
+ intentColumn = getVisibleColumn_DegradeLeft(intentItem,
+ (GridColumn) displayOrderedColumns.get(displayOrderedColumns.size() - 1));
+ }
+ else {
+ GridColumn firstCol = (GridColumn) displayOrderedColumns.get(0);
+ if (!firstCol.isVisible()) {
+ firstCol = getNextVisibleColumn(firstCol);
+ }
+ intentColumn = firstCol;
+ }
+ }
+
+ showColumn(intentColumn);
+ showItem(intentItem);
+ selectionEvent = updateCellSelection(new Point(indexOf(intentColumn), indexOf(intentItem)),
+ ctrlFlag | SWT.MOD2, true, false);
+ }
+ if (cellRowDragSelectionOccuring && handleCellHover(e.x, e.y)) {
+ GridItem intentItem = hoveringItem;
+
+ if (hoveringItem == null) {
+ if (e.y > headerHeight) {
+ //then we must be hovering way to the bottom
+ intentItem = getPreviousVisibleItem(null);
+ }
+ else {
+ if (getTopIndex() > 0) {
+ intentItem = getPreviousVisibleItem((GridItem) items.get(getTopIndex()));
+ }
+ else {
+ intentItem = (GridItem) items.get(0);
+ }
+ }
+ }
+
+ Vector cells = new Vector();
+
+ getCells(intentItem, focusItem, cells);
+
+ showItem(intentItem);
+ selectionEvent = updateCellSelection(cells, ctrlFlag, true, false);
+ }
+ if (cellColumnDragSelectionOccuring && handleCellHover(e.x, e.y)) {
+ GridColumn intentCol = hoveringColumn;
+
+ if (intentCol == null) {
+ if (e.y < rowHeaderWidth) {
+ //TODO: get the first col to the left
+ }
+ else {
+ //TODO: get the first col to the right
+ }
+ }
+
+ if (intentCol == null)
+ return; //temporary
+
+ GridColumn iterCol = intentCol;
+
+ Vector newSelected = new Vector();
+
+ boolean decreasing = (displayOrderedColumns.indexOf(iterCol) > displayOrderedColumns
+ .indexOf(focusColumn));
+
+ do {
+ getCells(iterCol, newSelected);
+
+ if (iterCol == focusColumn) {
+ break;
+ }
+
+ if (decreasing) {
+ iterCol = getPreviousVisibleColumn(iterCol);
+ }
+ else {
+ iterCol = getNextVisibleColumn(iterCol);
+ }
+
+ }
+ while (true);
+
+ selectionEvent = updateCellSelection(newSelected, ctrlFlag, true, false);
+ }
+
+ }
+ }
+
+ if (selectionEvent != null) {
+ selectionEvent.stateMask = e.stateMask;
+ selectionEvent.button = e.button;
+ selectionEvent.item = getItem(new Point(e.x, e.y));
+ selectionEvent.x = e.x;
+ selectionEvent.y = e.y;
+ notifyListeners(SWT.Selection, selectionEvent);
+ }
+ }
+
+ /**
+ * Handles the assignment of the correct values to the hover* field
+ * variables that let the painting code now what to paint as hovered.
+ *
+ * @param x mouse x coordinate
+ * @param y mouse y coordinate
+ */
+ private void handleHovering(int x, int y) {
+ // TODO: need to clean up and refactor hover code
+ handleCellHover(x, y);
+
+ // Is this Grid a DragSource ??
+ if (cellSelectionEnabled && getData("DragSource") != null) {
+ if (handleHoverOnSelectionDragArea(x, y)) {
+ return;
+ }
+ }
+
+ if (columnHeadersVisible) {
+ if (handleHoverOnColumnResizer(x, y)) {
+ // if (hoveringItem != null || !hoveringDetail.equals("") || hoveringColumn != null
+ // || hoveringColumnHeader != null || hoverColumnGroupHeader != null)
+ // {
+ // hoveringItem = null;
+ // hoveringDetail = "";
+ // hoveringColumn = null;
+ // hoveringColumnHeader = null;
+ // hoverColumnGroupHeader = null;
+ //
+ // Rectangle clientArea = getClientArea();
+ // redraw(clientArea.x,clientArea.y,clientArea.width,clientArea.height,false);
+ // }
+ return;
+ }
+ }
+ if (rowsResizeable && rowHeaderVisible) {
+ if (handleHoverOnRowResizer(x, y)) {
+ return;
+ }
+ }
+
+ // handleCellHover(x, y);
+ }
+
+ /**
+ * Refreshes the hover* variables according to the mouse location and
+ * current state of the table. This is useful is some method call, caused
+ * the state of the table to change and therefore the hover effects may have
+ * become out of date.
+ */
+ protected void refreshHoverState() {
+ Point p = getDisplay().map(null, this, getDisplay().getCursorLocation());
+ handleHovering(p.x, p.y);
+ }
+
+ /**
+ * Mouse exit event handler.
+ *
+ * @param e event
+ */
+ private void onMouseExit(MouseEvent e) {
+ hoveringItem = null;
+ hoveringDetail = "";
+ hoveringColumn = null;
+ hoveringOverText = false;
+ hideToolTip();
+ redraw();
+ }
+
+ /**
+ * Key down event handler.
+ *
+ * @param e event
+ */
+ private void onKeyDown(Event e) {
+ if (focusColumn == null || focusColumn.isDisposed()) {
+ if (columns.size() == 0)
+ return;
+
+ focusColumn = getColumn(0);
+ intendedFocusColumn = focusColumn;
+ }
+
+ if (e.character == '\r' && focusItem != null) {
+ Event newEvent = new Event();
+ newEvent.item = focusItem;
+
+ notifyListeners(SWT.DefaultSelection, newEvent);
+ return;
+ }
+
+ int attemptExpandCollapse = 0;
+ if ((e.character == '-' || (!cellSelectionEnabled && e.keyCode == SWT.ARROW_LEFT)) && focusItem != null
+ && focusItem.isExpanded()) {
+ attemptExpandCollapse = SWT.Collapse;
+ }
+ else if ((e.character == '+' || (!cellSelectionEnabled && e.keyCode == SWT.ARROW_RIGHT)) && focusItem != null
+ && !focusItem.isExpanded()) {
+ attemptExpandCollapse = SWT.Expand;
+ }
+
+ if (attemptExpandCollapse != 0 && focusItem != null && focusItem.hasChildren()) {
+ int performExpandCollapse = 0;
+
+ if (cellSelectionEnabled && focusColumn != null && focusColumn.isTree()) {
+ performExpandCollapse = attemptExpandCollapse;
+ }
+ else if (!cellSelectionEnabled) {
+ performExpandCollapse = attemptExpandCollapse;
+ }
+
+ if (performExpandCollapse == SWT.Expand) {
+ focusItem.setExpanded(true);
+ focusItem.fireEvent(SWT.Expand);
+ return;
+ }
+ if (performExpandCollapse == SWT.Collapse) {
+ focusItem.setExpanded(false);
+ focusItem.fireEvent(SWT.Collapse);
+ return;
+ }
+ }
+
+ if (e.character == ' ') {
+ handleSpaceBarDown(e);
+ }
+
+ GridItem newSelection = null;
+ GridColumn newColumnFocus = null;
+
+ //These two variables are used because the key navigation when the shift key is down is
+ //based, not off the focus item/column, but rather off the implied focus (i.e. where the
+ //keyboard has extended focus to).
+ GridItem impliedFocusItem = focusItem;
+ GridColumn impliedFocusColumn = focusColumn;
+
+ if (cellSelectionEnabled && e.stateMask == SWT.MOD2) {
+ if (shiftSelectionAnchorColumn != null) {
+ impliedFocusItem = shiftSelectionAnchorItem;
+ impliedFocusColumn = shiftSelectionAnchorColumn;
+ }
+ }
+
+ switch (e.keyCode) {
+ case SWT.ARROW_RIGHT:
+ if (cellSelectionEnabled) {
+ if (impliedFocusItem != null && impliedFocusColumn != null) {
+ newSelection = impliedFocusItem;
+
+ int index = displayOrderedColumns.indexOf(impliedFocusColumn);
+
+ int jumpAhead = impliedFocusItem.getColumnSpan(indexOf(impliedFocusColumn));
+
+ jumpAhead++;
+
+ while (jumpAhead > 0) {
+ index++;
+ if (index < displayOrderedColumns.size()) {
+ if (((GridColumn) displayOrderedColumns.get(index)).isVisible())
+ jumpAhead--;
+ }
+ else {
+ break;
+ }
+ }
+
+ if (index < displayOrderedColumns.size()) {
+ newColumnFocus = (GridColumn) displayOrderedColumns.get(index);
+ }
+ else {
+ newColumnFocus = impliedFocusColumn;
+ }
+ }
+ intendedFocusColumn = newColumnFocus;
+ }
+ else {
+ if (impliedFocusItem != null && impliedFocusItem.hasChildren()) {
+ newSelection = impliedFocusItem.getItem(0);
+ }
+ }
+ break;
+ case SWT.ARROW_LEFT:
+ if (cellSelectionEnabled) {
+ if (impliedFocusItem != null && impliedFocusColumn != null) {
+ newSelection = impliedFocusItem;
+
+ int index = displayOrderedColumns.indexOf(impliedFocusColumn);
+
+ if (index != 0) {
+ newColumnFocus = (GridColumn) displayOrderedColumns.get(index - 1);
+
+ newColumnFocus = getVisibleColumn_DegradeLeft(impliedFocusItem, newColumnFocus);
+ }
+ else {
+ newColumnFocus = impliedFocusColumn;
+ }
+ }
+ intendedFocusColumn = newColumnFocus;
+ }
+ else {
+ if (impliedFocusItem != null && impliedFocusItem.getParentItem() != null) {
+ newSelection = impliedFocusItem.getParentItem();
+ }
+ }
+ break;
+ case SWT.ARROW_UP:
+ if (impliedFocusItem != null) {
+ newSelection = getPreviousVisibleItem(impliedFocusItem);
+ }
+
+ if (impliedFocusColumn != null) {
+ if (newSelection != null) {
+ newColumnFocus = getVisibleColumn_DegradeLeft(newSelection, intendedFocusColumn);
+ }
+ else {
+ newColumnFocus = impliedFocusColumn;
+ }
+ }
+
+ break;
+ case SWT.ARROW_DOWN:
+ if (impliedFocusItem != null) {
+ newSelection = getNextVisibleItem(impliedFocusItem);
+ }
+ else {
+ if (items.size() > 0) {
+ newSelection = (GridItem) items.get(0);
+ }
+ }
+
+ if (impliedFocusColumn != null) {
+ if (newSelection != null) {
+ newColumnFocus = getVisibleColumn_DegradeLeft(newSelection, intendedFocusColumn);
+ }
+ else {
+ newColumnFocus = impliedFocusColumn;
+ }
+ }
+ break;
+ case SWT.HOME:
+
+ if (!cellSelectionEnabled) {
+ if (items.size() > 0) {
+ newSelection = (GridItem) items.get(0);
+ }
+ }
+ else {
+ newSelection = impliedFocusItem;
+ newColumnFocus = getVisibleColumn_DegradeRight(newSelection, (GridColumn) displayOrderedColumns.get(0));
+ }
+
+ break;
+ case SWT.END:
+ if (!cellSelectionEnabled) {
+ if (items.size() > 0) {
+ newSelection = getPreviousVisibleItem(null);
+ }
+ }
+ else {
+ newSelection = impliedFocusItem;
+ newColumnFocus = getVisibleColumn_DegradeLeft(newSelection,
+ (GridColumn) displayOrderedColumns.get(displayOrderedColumns.size() - 1));
+ }
+
+ break;
+ case SWT.PAGE_UP:
+ int topIndex = getTopIndex();
+
+ newSelection = (GridItem) items.get(topIndex);
+
+ if (focusItem == newSelection) {
+ RowRange range = getRowRange(getTopIndex(), getVisibleGridHeight(), false, true);
+ newSelection = (GridItem) items.get(range.startIndex);
+ }
+
+ newColumnFocus = focusColumn;
+ break;
+ case SWT.PAGE_DOWN:
+ int bottomIndex = getBottomIndex();
+
+ newSelection = (GridItem) items.get(bottomIndex);
+
+ if (!isShown(newSelection)) {
+ // the item at bottom index is not shown completely
+ GridItem tmpItem = getPreviousVisibleItem(newSelection);
+ if (tmpItem != null)
+ newSelection = tmpItem;
+ }
+
+ if (focusItem == newSelection) {
+ RowRange range = getRowRange(getBottomIndex(), getVisibleGridHeight(), true, false);
+ newSelection = (GridItem) items.get(range.endIndex);
+ }
+
+ newColumnFocus = focusColumn;
+ break;
+ default:
+ break;
+ }
+
+ if (newSelection == null) {
+ return;
+ }
+
+ if (cellSelectionEnabled) {
+ if (e.stateMask != SWT.MOD2)
+ focusColumn = newColumnFocus;
+ showColumn(newColumnFocus);
+
+ if (e.stateMask != SWT.MOD2)
+ focusItem = newSelection;
+ showItem(newSelection);
+
+ if (e.stateMask != SWT.MOD1) {
+ Event selEvent = updateCellSelection(new Point(indexOf(newColumnFocus), indexOf(newSelection)),
+ e.stateMask, false, false);
+ if (selEvent != null) {
+ selEvent.stateMask = e.stateMask;
+ selEvent.character = e.character;
+ selEvent.keyCode = e.keyCode;
+ notifyListeners(SWT.Selection, selEvent);
+ }
+ }
+
+ redraw();
+ }
+ else {
+ Event selectionEvent = null;
+ if (selectionType == SWT.SINGLE || e.stateMask != SWT.MOD1) {
+ selectionEvent = updateSelection(newSelection, e.stateMask);
+ if (selectionEvent != null) {
+ selectionEvent.stateMask = e.stateMask;
+ selectionEvent.character = e.character;
+ selectionEvent.keyCode = e.keyCode;
+ }
+ }
+
+ focusItem = newSelection;
+ showItem(newSelection);
+ redraw();
+
+ if (selectionEvent != null)
+ notifyListeners(SWT.Selection, selectionEvent);
+ }
+ }
+
+ private void handleSpaceBarDown(Event event) {
+ if (focusItem == null)
+ return;
+
+ if (selectionEnabled && !cellSelectionEnabled && !selectedItems.contains(focusItem)) {
+ selectedItems.add(focusItem);
+ redraw();
+ Event e = new Event();
+ e.item = focusItem;
+ e.stateMask = event.stateMask;
+ e.character = event.character;
+ e.keyCode = event.keyCode;
+ notifyListeners(SWT.Selection, e);
+ }
+
+ if (!cellSelectionEnabled) {
+ boolean checkFirstCol = false;
+ boolean first = true;
+
+ for (Iterator iter = columns.iterator(); iter.hasNext();) {
+ GridColumn col = (GridColumn) iter.next();
+
+ if (first) {
+ if (!col.isCheck())
+ break;
+
+ first = false;
+ checkFirstCol = true;
+ }
+ else {
+ if (col.isCheck()) {
+ checkFirstCol = false;
+ break;
+ }
+ }
+ }
+
+ if (checkFirstCol) {
+ focusItem.setChecked(!focusItem.getChecked());
+ redraw();
+ focusItem.fireCheckEvent(0);
+ }
+ }
+ }
+
+ /**
+ * Resize event handler.
+ */
+ private void onResize() {
+
+ //CGross 1/2/08 - I don't really want to be doing this....
+ //I shouldn't be changing something you user configured...
+ //leaving out for now
+ // if (columnScrolling)
+ // {
+ // int maxWidth = getClientArea().width;
+ // if (rowHeaderVisible)
+ // maxWidth -= rowHeaderWidth;
+ //
+ // for (Iterator cols = columns.iterator(); cols.hasNext();) {
+ // GridColumn col = (GridColumn) cols.next();
+ // if (col.getWidth() > maxWidth)
+ // col.setWidth(maxWidth);
+ // }
+ // }
+
+ scrollValuesObsolete = true;
+ topIndex = -1;
+ bottomIndex = -1;
+ }
+
+ /**
+ * Scrollbar selection event handler.
+ */
+ private void onScrollSelection() {
+ topIndex = -1;
+ bottomIndex = -1;
+ refreshHoverState();
+ redraw(getClientArea().x, getClientArea().y, getClientArea().width, getClientArea().height, false);
+ }
+
+ /**
+ * Returns the intersection of the given column and given item.
+ *
+ * @param column column
+ * @param item item
+ * @return x,y of top left corner of the cell
+ */
+ Point getOrigin(GridColumn column, GridItem item) {
+ int x = 0;
+
+ if (rowHeaderVisible) {
+ x += rowHeaderWidth;
+ }
+
+ x -= getHScrollSelectionInPixels();
+
+ for (Iterator colIterIterator = displayOrderedColumns.iterator(); colIterIterator.hasNext();) {
+ GridColumn colIter = (GridColumn) colIterIterator.next();
+
+ if (colIter == column) {
+ break;
+ }
+
+ if (colIter.isVisible()) {
+ x += colIter.getWidth();
+ }
+ }
+
+ int y = 0;
+ if (item != null) {
+ if (columnHeadersVisible) {
+ y += headerHeight;
+ }
+
+ int currIndex = getTopIndex();
+ int itemIndex = items.indexOf(item);
+
+ if (itemIndex == -1) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ while (currIndex != itemIndex) {
+ if (currIndex < itemIndex) {
+ GridItem currItem = (GridItem) items.get(currIndex);
+ if (currItem.isVisible()) {
+ y += currItem.getHeight() + 1;
+ }
+ currIndex++;
+ }
+ else if (currIndex > itemIndex) {
+ currIndex--;
+ GridItem currItem = (GridItem) items.get(currIndex);
+ if (currItem.isVisible()) {
+ y -= currItem.getHeight() + 1;
+ }
+ }
+ }
+ }
+ else {
+ if (column.getColumnGroup() != null) {
+ y += groupHeaderHeight;
+ }
+ }
+
+ return new Point(x, y);
+ }
+
+ /**
+ * Determines (which cell/if a cell) has been clicked (mouse down really)
+ * and notifies the appropriate renderer. Returns true when a cell has
+ * responded to this event in some way and prevents the event from
+ * triggering an action further down the chain (like a selection).
+ *
+ * @param item item clicked
+ * @param x mouse x
+ * @param y mouse y
+ * @return true if this event has been consumed.
+ */
+ private boolean handleCellClick(GridItem item, int x, int y) {
+
+ // if(!isTree)
+ // return false;
+
+ GridColumn col = getColumn(new Point(x, y));
+ if (col == null) {
+ return false;
+ }
+
+ col.getCellRenderer().setBounds(item.getBounds(indexOf(col)));
+ return col.getCellRenderer().notify(IInternalWidget.LeftMouseButtonDown, new Point(x, y), item);
+
+ }
+
+ /**
+ * Sets the hovering variables (hoverItem,hoveringColumn) as well as
+ * hoverDetail by talking to the cell renderers. Triggers a redraw if
+ * necessary.
+ *
+ * @param x mouse x
+ * @param y mouse y
+ * @return true if a new section of the table is now being hovered
+ */
+ private boolean handleCellHover(int x, int y) {
+
+ String detail = "";
+
+ boolean overText = false;
+
+ final GridColumn col = getColumn(new Point(x, y));
+ final GridItem item = getItem(new Point(x, y));
+
+ GridColumnGroup hoverColGroup = null;
+ GridColumn hoverColHeader = null;
+
+ if (col != null) {
+ if (item != null) {
+ if (y < getClientArea().height - footerHeight) {
+ col.getCellRenderer().setBounds(item.getBounds(columns.indexOf(col)));
+
+ if (col.getCellRenderer().notify(IInternalWidget.MouseMove, new Point(x, y), item)) {
+ detail = col.getCellRenderer().getHoverDetail();
+ }
+
+ Rectangle textBounds = col.getCellRenderer().getTextBounds(item, false);
+
+ if (textBounds != null) {
+ Point p = new Point(x - col.getCellRenderer().getBounds().x, y
+ - col.getCellRenderer().getBounds().y);
+ overText = textBounds.contains(p);
+ }
+ }
+ }
+ else {
+ if (y < headerHeight) {
+ if (columnGroups.length != 0 && y < groupHeaderHeight && col.getColumnGroup() != null) {
+ hoverColGroup = col.getColumnGroup();
+ hoverColGroup.getHeaderRenderer().setBounds(hoverColGroup.getBounds());
+ if (hoverColGroup.getHeaderRenderer().notify(IInternalWidget.MouseMove, new Point(x, y),
+ hoverColGroup)) {
+ detail = hoverColGroup.getHeaderRenderer().getHoverDetail();
+ }
+
+ Rectangle textBounds = hoverColGroup.getHeaderRenderer().getTextBounds(hoverColGroup, false);
+
+ if (textBounds != null) {
+ Point p = new Point(x - hoverColGroup.getHeaderRenderer().getBounds().x, y
+ - hoverColGroup.getHeaderRenderer().getBounds().y);
+ overText = textBounds.contains(p);
+ }
+ }
+ else {
+ // on col header
+ hoverColHeader = col;
+
+ col.getHeaderRenderer().setBounds(col.getBounds());
+ if (col.getHeaderRenderer().notify(IInternalWidget.MouseMove, new Point(x, y), col)) {
+ detail = col.getHeaderRenderer().getHoverDetail();
+ }
+
+ Rectangle textBounds = col.getHeaderRenderer().getTextBounds(col, false);
+
+ if (textBounds != null) {
+ Point p = new Point(x - col.getHeaderRenderer().getBounds().x, y
+ - col.getHeaderRenderer().getBounds().y);
+ overText = textBounds.contains(p);
+ }
+ }
+ }
+ }
+ }
+
+ boolean hoverChange = false;
+
+ if (hoveringItem != item || !hoveringDetail.equals(detail) || hoveringColumn != col
+ || hoverColGroup != hoverColumnGroupHeader || hoverColHeader != hoveringColumnHeader) {
+ hoveringItem = item;
+ hoveringDetail = detail;
+ hoveringColumn = col;
+ hoveringColumnHeader = hoverColHeader;
+ hoverColumnGroupHeader = hoverColGroup;
+
+ Rectangle clientArea = getClientArea();
+ redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false);
+
+ hoverChange = true;
+ }
+
+ //do inplace toolTip stuff
+ if (hoverChange || hoveringOverText != overText) {
+ hoveringOverText = overText;
+
+ if (overText) {
+
+ Rectangle cellBounds = null;
+ Rectangle textBounds = null;
+ Rectangle preferredTextBounds = null;
+
+ if (hoveringItem != null && hoveringItem.getToolTipText(indexOf(col)) == null && //no inplace tooltips when regular tooltip
+ !col.getWordWrap()) //dont show inplace tooltips for cells with wordwrap
+ {
+ cellBounds = col.getCellRenderer().getBounds();
+ if (cellBounds.x + cellBounds.width > getSize().x) {
+ cellBounds.width = getSize().x - cellBounds.x;
+ }
+ textBounds = col.getCellRenderer().getTextBounds(item, false);
+ preferredTextBounds = col.getCellRenderer().getTextBounds(item, true);
+ }
+ else if (hoveringColumnHeader != null && hoveringColumnHeader.getHeaderTooltip() == null) //no inplace tooltips when regular tooltip
+ {
+ cellBounds = hoveringColumnHeader.getHeaderRenderer().getBounds();
+ if (cellBounds.x + cellBounds.width > getSize().x) {
+ cellBounds.width = getSize().x - cellBounds.x;
+ }
+ textBounds = hoveringColumnHeader.getHeaderRenderer().getTextBounds(col, false);
+ preferredTextBounds = hoveringColumnHeader.getHeaderRenderer().getTextBounds(col, true);
+ }
+ else if (hoverColumnGroupHeader != null) {
+ cellBounds = hoverColumnGroupHeader.getHeaderRenderer().getBounds();
+ if (cellBounds.x + cellBounds.width > getSize().x) {
+ cellBounds.width = getSize().x - cellBounds.x;
+ }
+ textBounds = hoverColumnGroupHeader.getHeaderRenderer()
+ .getTextBounds(hoverColumnGroupHeader, false);
+ preferredTextBounds = hoverColumnGroupHeader.getHeaderRenderer().getTextBounds(
+ hoverColumnGroupHeader, true);
+ }
+
+ //if we are truncated
+ if (textBounds != null && textBounds.width < preferredTextBounds.width) {
+ showToolTip(item, col, hoverColumnGroupHeader, new Point(cellBounds.x + textBounds.x, cellBounds.y
+ + textBounds.y));
+ //the following 2 lines are done here rather than in showToolTip to allow
+ //that method to be overridden yet still capture the mouse.
+ setCapture(true);
+ inplaceTooltipCapture = true;
+ }
+ }
+ else {
+ hideToolTip();
+ }
+ }
+
+ //do normal cell specific tooltip stuff
+ if (hoverChange) {
+ String newTip = null;
if ((hoveringItem != null) && (hoveringColumn != null)) {
// get cell specific tooltip
newTip = hoveringItem.getToolTipText(indexOf(hoveringColumn));
- } else if ((hoveringColumn != null) && (hoveringColumnHeader != null)) {
+ }
+ else if ((hoveringColumn != null) && (hoveringColumnHeader != null)) {
// get column header specific tooltip
newTip = hoveringColumn.getHeaderTooltip();
}
@@ -8124,2190 +7334,1926 @@ public class Grid extends Canvas
newTip = getToolTipText();
}
- //Avoid unnecessarily resetting tooltip - this will cause the tooltip to jump around
- if (newTip != null && !newTip.equals(displayedToolTipText))
- {
- updateToolTipText(newTip);
- }
- else if(newTip == null && displayedToolTipText != null)
- {
- updateToolTipText(null);
- }
- displayedToolTipText = newTip;
- }
-
- return hoverChange;
- }
-
- /**
- * Sets the tooltip for the whole Grid to the given text. This method is made available
- * for subclasses to override, when a subclass wants to display a different than the standard
- * SWT/OS tooltip. Generally, those subclasses would override this event and use this tooltip
- * text in their own tooltip or just override this method to prevent the SWT/OS tooltip from
- * displaying.
- *
- * @param text
- */
- protected void updateToolTipText(String text)
- {
- super.setToolTipText(text);
- }
-
- /**
- * Marks the scroll values obsolete so they will be recalculated.
- */
- protected void setScrollValuesObsolete()
- {
- this.scrollValuesObsolete = true;
- redraw();
- }
-
- /**
- * Inserts a new column into the table.
- *
- * @param column new column
- * @param index index to insert new column
- * @return current number of columns
- */
- int newColumn(GridColumn column, int index)
- {
-
- if (index == -1)
- {
- columns.add(column);
- displayOrderedColumns.add(column);
- }
- else
- {
- columns.add(index, column);
- displayOrderedColumns.add(index, column);
-
- for (int i = 0; i < columns.size(); i++) {
+ //Avoid unnecessarily resetting tooltip - this will cause the tooltip to jump around
+ if (newTip != null && !newTip.equals(displayedToolTipText)) {
+ updateToolTipText(newTip);
+ }
+ else if (newTip == null && displayedToolTipText != null) {
+ updateToolTipText(null);
+ }
+ displayedToolTipText = newTip;
+ }
+
+ return hoverChange;
+ }
+
+ /**
+ * Sets the tooltip for the whole Grid to the given text. This method is made available
+ * for subclasses to override, when a subclass wants to display a different than the standard
+ * SWT/OS tooltip. Generally, those subclasses would override this event and use this tooltip
+ * text in their own tooltip or just override this method to prevent the SWT/OS tooltip from
+ * displaying.
+ *
+ * @param text
+ */
+ protected void updateToolTipText(String text) {
+ super.setToolTipText(text);
+ }
+
+ /**
+ * Marks the scroll values obsolete so they will be recalculated.
+ */
+ protected void setScrollValuesObsolete() {
+ this.scrollValuesObsolete = true;
+ redraw();
+ }
+
+ /**
+ * Inserts a new column into the table.
+ *
+ * @param column new column
+ * @param index index to insert new column
+ * @return current number of columns
+ */
+ int newColumn(GridColumn column, int index) {
+
+ if (index == -1) {
+ columns.add(column);
+ displayOrderedColumns.add(column);
+ }
+ else {
+ columns.add(index, column);
+ displayOrderedColumns.add(index, column);
+
+ dataVisualizer.addColumn(index);
+ for (int i = 0; i < columns.size(); i++) {
((GridColumn) columns.get(i)).setColumnIndex(i);
}
- }
-
- computeHeaderHeight(sizingGC);
- computeFooterHeight(sizingGC);
-
- updatePrimaryCheckColumn();
-
- for (Iterator iterator = items.iterator(); iterator.hasNext();)
- {
- GridItem item = (GridItem)iterator.next();
- item.columnAdded(index);
- }
-
- scrollValuesObsolete = true;
- redraw();
-
- return columns.size() - 1;
- }
-
- /**
- * Removes the given column from the table.
- *
- * @param column column to remove
- */
- void removeColumn(GridColumn column)
- {
- boolean selectionModified = false;
-
- int index = indexOf(column);
-
- if (cellSelectionEnabled)
- {
- Vector removeSelectedCells = new Vector();
-
- for (Iterator iterator = selectedCells.iterator(); iterator.hasNext();)
- {
- Point cell = (Point)iterator.next();
- if (cell.x == index)
- {
- removeSelectedCells.add(cell);
- }
- }
-
- if (removeSelectedCells.size() > 0)
- {
- selectedCells.removeAll(removeSelectedCells);
- selectionModified = true;
- }
-
- for (Iterator iterator = selectedCells.iterator(); iterator.hasNext();)
- {
- Point cell = (Point)iterator.next();
- if (cell.x >= index)
- {
- cell.x--;
- selectionModified = true;
- }
- }
- }
-
- columns.remove(column);
- displayOrderedColumns.remove(column);
-
- updatePrimaryCheckColumn();
-
- scrollValuesObsolete = true;
- redraw();
-
- for (Iterator iterator = items.iterator(); iterator.hasNext();)
- {
- GridItem item = (GridItem)iterator.next();
- item.columnRemoved(index);
- }
-
- int i = 0;
- for (Iterator iterator = columns.iterator(); iterator.hasNext();)
- {
- GridColumn col = (GridColumn)iterator.next();
- col.setColumnIndex(i);
- i++;
- }
-
- if (selectionModified && !disposing)
- {
- updateColumnSelection();
- }
- }
-
- /**
- * Manages the setting of the checkbox column when the SWT.CHECK style was given to the
- * table. This method will ensure that the first column of the table always has a checkbox
- * when SWT.CHECK is given to the table.
- */
- private void updatePrimaryCheckColumn()
- {
- if ((getStyle() & SWT.CHECK) == SWT.CHECK)
- {
- boolean firstCol = true;
-
- for (Iterator iter = columns.iterator(); iter.hasNext();)
- {
- GridColumn col = (GridColumn)iter.next();
- col.setTableCheck(firstCol);
- firstCol = false;
- }
- }
- }
-
- void newRootItem(GridItem item, int index)
- {
- if (index == -1 || index >= rootItems.size())
- {
- rootItems.add(item);
- }
- else
- {
- rootItems.add(index,item);
- }
- }
-
- void removeRootItem(GridItem item)
- {
- rootItems.remove(item);
- }
-
- /**
- * Creates the new item at the given index. Only called from GridItem
- * constructor.
- *
- * @param item new item
- * @param index index to insert the item at
- * @return the index where the item was insert
- */
- int newItem(GridItem item, int index, boolean root)
- {
- int row = 0;
-
- if (!isTree)
- {
- if (item.getParentItem() != null)
- {
- isTree = true;
- }
- }
-
- //Have to convert indexes, this method needs a flat index, the method is called with indexes
- //that are relative to the level
- if (root && index != -1)
- {
- if (index >= rootItems.size())
- {
- index = -1;
- }
- else
- {
- index = items.indexOf(rootItems.get(index));
- }
- }
- else if (!root)
- {
- if (index >= item.getParentItem().getItems().length || index == -1)
- {
- GridItem rightMostDescendent = item.getParentItem();
-
- while (rightMostDescendent.getItems().length > 0)
- {
- rightMostDescendent = rightMostDescendent.getItems()[rightMostDescendent
- .getItems().length - 1];
- }
-
- index = indexOf(rightMostDescendent) + 1;
- }
- else
- {
- index = indexOf(item.getParentItem().getItems()[index]);
- }
- }
-
- if (index == -1)
- {
- items.add(item);
- row = items.size() - 1;
- }
- else
- {
- items.add(index, item);
- row = index;
- }
-
- if (items.size() == 1 && !userModifiedItemHeight)
- itemHeight = computeItemHeight(item,sizingGC);
-
- item.initializeHeight(itemHeight);
-
- if (isRowHeaderVisible() && isAutoWidth())
- {
- rowHeaderWidth = Math.max(rowHeaderWidth,rowHeaderRenderer
- .computeSize(sizingGC, SWT.DEFAULT, SWT.DEFAULT, item).x);
- }
-
- scrollValuesObsolete = true;
- topIndex = -1;
- bottomIndex = -1;
-
- currentVisibleItems++;
-
- redraw();
-
- return row;
- }
-
- /**
- * Removes the given item from the table. This method is only called from
- * the item's dispose method.
- *
- * @param item item to remove
- */
- void removeItem(GridItem item)
- {
- Point[] cells = getCells(item);
- boolean selectionModified = false;
-
- items.remove(item);
-
- if (disposing)
- return;
-
- if (selectedItems.remove(item))
- selectionModified = true;
-
- for (int i = 0; i < cells.length; i++)
- {
- if (selectedCells.remove(cells[i]))
- selectionModified = true;
- }
-
- if (focusItem == item)
- {
- focusItem = null;
- }
-
- scrollValuesObsolete = true;
- topIndex = -1;
- bottomIndex = -1;
- if (item.isVisible())
- {
- currentVisibleItems--;
- }
-
- if (selectionModified && !disposing)
- {
- updateColumnSelection();
- }
-
- redraw();
- // Need to update the scrollbars see see 375327
- updateScrollbars();
- }
-
- /**
- * Creates the given column group at the given index. This method is only
- * called from the {@code GridColumnGroup}'s constructor.
- *
- * @param group group to add.
- */
- void newColumnGroup(GridColumnGroup group)
- {
- GridColumnGroup[] newColumnGroups = new GridColumnGroup[columnGroups.length + 1];
- System.arraycopy(columnGroups, 0, newColumnGroups, 0, columnGroups.length);
- newColumnGroups[newColumnGroups.length - 1] = group;
- columnGroups = newColumnGroups;
-
- // if we just added the first col group, then we need to up the row
- // height
- if (columnGroups.length == 1)
- {
- computeHeaderHeight(sizingGC);
- }
-
- scrollValuesObsolete = true;
- redraw();
- }
-
- /**
- * Removes the given column group from the table. This method is only called
- * from the {@code GridColumnGroup}'s dispose method.
- *
- * @param group group to remove.
- */
- void removeColumnGroup(GridColumnGroup group)
- {
- GridColumnGroup[] newColumnGroups = new GridColumnGroup[columnGroups.length - 1];
- int newIndex = 0;
- for (int i = 0; i < columnGroups.length; i++)
- {
- if (columnGroups[i] != group)
- {
- newColumnGroups[newIndex] = columnGroups[i];
- newIndex++;
- }
- }
- columnGroups = newColumnGroups;
-
- if (columnGroups.length == 0)
- {
- computeHeaderHeight(sizingGC);
- }
-
- scrollValuesObsolete = true;
- redraw();
- }
-
- /**
- * Updates the cached number of visible items by the given amount.
- *
- * @param amount amount to update cached total
- */
- void updateVisibleItems(int amount)
- {
- currentVisibleItems += amount;
- }
-
- /**
- * Returns the current item in focus.
- *
- * @return item in focus or {@code null}.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public GridItem getFocusItem()
- {
- checkWidget();
- return focusItem;
- }
-
- /**
- * Returns the current cell in focus. If cell selection is disabled, this method returns null.
- *
- * @return cell in focus or {@code null}. x represents the column and y the row the cell is in
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public Point getFocusCell()
- {
- checkWidget();
- if (!cellSelectionEnabled) return null;
-
- int x = -1;
- int y = -1;
-
- if (focusColumn != null)
- x = indexOf(focusColumn);
-
- if (focusItem != null)
- y = indexOf(focusItem);
-
- return new Point(x,y);
- }
-
- /**
- * Sets the focused item to the given item.
- *
- * @param item item to focus.
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_ARGUMENT - if item is disposed</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setFocusItem(GridItem item)
- {
- checkWidget();
- //TODO: check and make sure this item is valid for focus
- if (item == null || item.isDisposed() || item.getParent() != this)
- {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- focusItem = item;
- }
-
- /**
- * Sets the focused item to the given column. Column focus is only applicable when cell
- * selection is enabled.
- *
- * @param column column to focus.
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_INVALID_ARGUMENT - if item is disposed</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setFocusColumn(GridColumn column)
- {
- checkWidget();
- //TODO: check and make sure this item is valid for focus
- if (column == null || column.isDisposed() || column.getParent() != this || !column.isVisible())
- {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
-
- focusColumn = column;
- intendedFocusColumn = column;
- }
-
-
- /**
- * Returns an array of the columns in their display order.
- *
- * @return columns in display order
- */
- GridColumn[] getColumnsInOrder()
- {
- checkWidget();
- return (GridColumn[])displayOrderedColumns.toArray(new GridColumn[columns.size()]);
- }
-
- /**
- * Returns true if the table is set to horizontally scroll column-by-column
- * rather than pixel-by-pixel.
- *
- * @return true if the table is scrolled horizontally by column
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean getColumnScrolling()
- {
- checkWidget();
- return columnScrolling;
- }
-
- /**
- * Sets the table scrolling method to either scroll column-by-column (true)
- * or pixel-by-pixel (false).
- *
- * @param columnScrolling true to horizontally scroll by column, false to
- * scroll by pixel
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setColumnScrolling(boolean columnScrolling)
- {
- checkWidget();
- if (rowHeaderVisible && !columnScrolling)
- {
- return;
- }
-
- this.columnScrolling = columnScrolling;
- scrollValuesObsolete = true;
- redraw();
- }
-
- /**
- * Returns the first visible column that is not spanned by any other column that is either the
- * given column or any of the columns displaying to the left of the given column. If the
- * given column and subsequent columns to the right are either not visible or spanned, this
- * method will return null.
- *
- * @param item
- * @param col
- * @return
- */
- private GridColumn getVisibleColumn_DegradeLeft(GridItem item, GridColumn col)
- {
- int index = displayOrderedColumns.indexOf(col);
-
- GridColumn prevCol = col;
-
- int i = 0;
- while (!prevCol.isVisible())
- {
- i ++;
- if (index - i < 0)
- return null;
-
- prevCol = (GridColumn)displayOrderedColumns.get(index - i);
- }
-
- index = displayOrderedColumns.indexOf(prevCol);
-
- for (int j = 0; j < index; j++)
- {
- GridColumn tempCol = (GridColumn)displayOrderedColumns.get(j);
-
- if (!tempCol.isVisible())
- {
- continue;
- }
-
- if (item.getColumnSpan(indexOf(tempCol)) >= index - j)
- {
- prevCol = tempCol;
- break;
- }
- }
-
- return prevCol;
- }
-
- /**
- * Returns the first visible column that is not spanned by any other column that is either the
- * given column or any of the columns displaying to the right of the given column. If the
- * given column and subsequent columns to the right are either not visible or spanned, this
- * method will return null.
- *
- * @param item
- * @param col
- * @return
- */
- private GridColumn getVisibleColumn_DegradeRight(GridItem item, GridColumn col)
- {
- int index = displayOrderedColumns.indexOf(col);
-
- int i = 0;
- GridColumn nextCol = col;
- while (!nextCol.isVisible())
- {
- i ++;
- if (index + i == displayOrderedColumns.size())
- return null;
-
- nextCol = (GridColumn)displayOrderedColumns.get(index + i);
- }
-
-
- index = displayOrderedColumns.indexOf(nextCol);
- int startIndex = index;
-
- while (index > 0)
- {
-
- index --;
- GridColumn prevCol = (GridColumn)displayOrderedColumns.get(index);
-
- if (item.getColumnSpan(indexOf(prevCol)) >= startIndex - index)
- {
- if (startIndex == displayOrderedColumns.size() - 1)
- {
- return null;
- }
- else
- {
- return getVisibleColumn_DegradeRight(item, (GridColumn)displayOrderedColumns.get(startIndex + 1));
- }
- }
-
- }
-
- return nextCol;
- }
-
- /**
- * Returns true if the cells are selectable in the reciever.
- *
- * @return cell selection enablement status.
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public boolean getCellSelectionEnabled()
- {
- checkWidget();
- return cellSelectionEnabled;
- }
-
- /**
- * Sets whether cells are selectable in the receiver.
- *
- * @param cellSelection the cellSelection to set
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setCellSelectionEnabled(boolean cellSelection)
- {
- checkWidget();
- if (!cellSelection)
- {
- selectedCells.clear();
- redraw();
- }
- else
- {
- selectedItems.clear();
- redraw();
- }
-
- this.cellSelectionEnabled = cellSelection;
- }
-
- /**
- * @return <code>true</code> if cell selection is enabled
- */
- public boolean isCellSelectionEnabled() {
- return cellSelectionEnabled;
- }
-
- /**
- * Deselects the given cell in the receiver. If the given cell is already
- * deselected it remains deselected. Invalid cells are ignored.
- *
- * @param cell cell to deselect.
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the cell is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void deselectCell(Point cell)
- {
- checkWidget();
-
- if (cell == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- selectedCells.remove(cell);
- updateColumnSelection();
- redraw();
- }
-
- /**
- * Deselects the given cells. Invalid cells are ignored.
- *
- * @param cells the cells to deselect.
- *
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the set of cells or any cell is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void deselectCells(Point[] cells)
- {
- checkWidget();
-
- if (cells == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- for (int i = 0; i < cells.length; i++)
- {
- if (cells[i] == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
-
- for (int i = 0; i < cells.length; i++)
- {
- selectedCells.remove(cells[i]);
- }
-
- updateColumnSelection();
-
- redraw();
- }
-
- /**
- * Deselects all selected cells in the receiver.
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void deselectAllCells()
- {
- checkWidget();
- selectedCells.clear();
- updateColumnSelection();
- redraw();
- }
-
- /**
- * Selects the given cell. Invalid cells are ignored.
- *
- * @param cell point whose x values is a column index and y value is an item index
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void selectCell(Point cell)
- {
- checkWidget();
-
- if (!cellSelectionEnabled) return;
-
- if (cell == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- addToCellSelection(cell);
- updateColumnSelection();
- redraw();
- }
-
- /**
- * Selects the given cells. Invalid cells are ignored.
- *
- * @param cells an arry of points whose x value is a column index and y value is an item index
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the set of cells or an individual cell is null</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void selectCells(Point[] cells)
- {
- checkWidget();
-
- if (!cellSelectionEnabled) return;
-
- if (cells == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- for (int i = 0; i < cells.length; i++)
- {
- if (cells[i] == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
-
- for (int i = 0; i < cells.length; i++)
- {
- addToCellSelection(cells[i]);
- }
-
- updateColumnSelection();
- redraw();
- }
-
- /**
- * Selects all cells in the receiver.
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void selectAllCells()
- {
- checkWidget();
- selectAllCellsInternal();
- }
-
- /**
- * Selects all cells in the receiver.
- *
- * @return An Event object
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- private Event selectAllCellsInternal()
- {
- if (!cellSelectionEnabled)
- return selectAllRowsInternal();
-
- if (columns.size() == 0)
- return null;
-
- if(items.size() == 0)
- return null;
-
- int index = 0;
- GridColumn column = (GridColumn)displayOrderedColumns.get(index);
-
- while (!column.isVisible())
- {
- index ++;
-
- if (index >= columns.size())
- return null;
-
- column = (GridColumn)displayOrderedColumns.get(index);
- }
-
- GridColumn oldFocusColumn = focusColumn;
- GridItem oldFocusItem = focusItem;
-
- focusColumn = column;
- focusItem = (GridItem)items.get(0);
-
- GridItem lastItem = getPreviousVisibleItem(null);
- GridColumn lastCol = getVisibleColumn_DegradeLeft(lastItem,(GridColumn)displayOrderedColumns.get(displayOrderedColumns.size() -1));
-
- Event event = updateCellSelection(new Point(indexOf(lastCol),indexOf(lastItem)),SWT.MOD2, true, false);
-
- focusColumn = oldFocusColumn;
- focusItem = oldFocusItem;
-
- updateColumnSelection();
-
- redraw();
- return event;
- }
-
- /**
- * Selects rows in the receiver.
- *
- * @return An Event object
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- private Event selectAllRowsInternal()
- {
- if (cellSelectionEnabled)
- return selectAllCellsInternal();
-
- if (SWT.MULTI != selectionType)
- return null;
-
- if(items.size() == 0)
- return null;
-
- deselectAll();
-
- GridItem oldFocusItem = focusItem;
-
- GridItem firstItem = getItem(getTopIndex());
- GridItem lastItem = getPreviousVisibleItem(null);
-
- setFocusItem(firstItem);
- updateSelection(firstItem, SWT.NONE);
-
- Event event = updateSelection(lastItem, SWT.MOD2);
-
- setFocusItem(oldFocusItem);
-
- redraw();
- return event;
- }
-
- /**
- * Selects all cells in the given column in the receiver.
- *
- * @param col
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void selectColumn(int col) {
- checkWidget();
- Vector cells = new Vector();
+ }
+
+ computeHeaderHeight(sizingGC);
+ computeFooterHeight(sizingGC);
+
+ updatePrimaryCheckColumn();
+
+ for (Iterator iterator = items.iterator(); iterator.hasNext();) {
+ GridItem item = (GridItem) iterator.next();
+ item.columnAdded(index);
+ }
+
+ scrollValuesObsolete = true;
+ redraw();
+
+ return columns.size() - 1;
+ }
+
+ /**
+ * Removes the given column from the table.
+ *
+ * @param column column to remove
+ */
+ void removeColumn(GridColumn column) {
+ boolean selectionModified = false;
+
+ int index = indexOf(column);
+
+ if (cellSelectionEnabled) {
+ Vector removeSelectedCells = new Vector();
+
+ for (Iterator iterator = selectedCells.iterator(); iterator.hasNext();) {
+ Point cell = (Point) iterator.next();
+ if (cell.x == index) {
+ removeSelectedCells.add(cell);
+ }
+ }
+
+ if (removeSelectedCells.size() > 0) {
+ selectedCells.removeAll(removeSelectedCells);
+ selectionModified = true;
+ }
+
+ for (Iterator iterator = selectedCells.iterator(); iterator.hasNext();) {
+ Point cell = (Point) iterator.next();
+ if (cell.x >= index) {
+ cell.x--;
+ selectionModified = true;
+ }
+ }
+ }
+
+ columns.remove(column);
+ displayOrderedColumns.remove(column);
+ dataVisualizer.clearColumn(index);
+
+ updatePrimaryCheckColumn();
+
+ scrollValuesObsolete = true;
+ redraw();
+
+ int i = 0;
+ for (Iterator iterator = columns.iterator(); iterator.hasNext();) {
+ GridColumn col = (GridColumn) iterator.next();
+ col.setColumnIndex(i);
+ i++;
+ }
+
+ if (selectionModified && !disposing) {
+ updateColumnSelection();
+ }
+ }
+
+ /**
+ * Manages the setting of the checkbox column when the SWT.CHECK style was given to the
+ * table. This method will ensure that the first column of the table always has a checkbox
+ * when SWT.CHECK is given to the table.
+ */
+ private void updatePrimaryCheckColumn() {
+ if ((getStyle() & SWT.CHECK) == SWT.CHECK) {
+ boolean firstCol = true;
+
+ for (Iterator iter = columns.iterator(); iter.hasNext();) {
+ GridColumn col = (GridColumn) iter.next();
+ col.setTableCheck(firstCol);
+ firstCol = false;
+ }
+ }
+ }
+
+ void newRootItem(GridItem item, int index) {
+ if (index == -1 || index >= rootItems.size()) {
+ rootItems.add(item);
+ }
+ else {
+ rootItems.add(index, item);
+ }
+ }
+
+ void removeRootItem(GridItem item) {
+ rootItems.remove(item);
+ }
+
+ /**
+ * Creates the new item at the given index. Only called from GridItem
+ * constructor.
+ *
+ * @param item new item
+ * @param index index to insert the item at
+ * @return the index where the item was insert
+ */
+ int newItem(GridItem item, int index, boolean root) {
+ int row = 0;
+
+ if (!isTree) {
+ if (item.getParentItem() != null) {
+ isTree = true;
+ }
+ }
+
+ //Have to convert indexes, this method needs a flat index, the method is called with indexes
+ //that are relative to the level
+ if (root && index != -1) {
+ if (index >= rootItems.size()) {
+ index = -1;
+ }
+ else {
+ index = items.indexOf(rootItems.get(index));
+ }
+ }
+ else if (!root) {
+ if (index >= item.getParentItem().getItems().length || index == -1) {
+ GridItem rightMostDescendent = item.getParentItem();
+
+ while (rightMostDescendent.getItems().length > 0) {
+ rightMostDescendent = rightMostDescendent.getItems()[rightMostDescendent.getItems().length - 1];
+ }
+
+ index = indexOf(rightMostDescendent) + 1;
+ }
+ else {
+ index = indexOf(item.getParentItem().getItems()[index]);
+ }
+ }
+
+ if (index == -1) {
+ items.add(item);
+ row = items.size() - 1;
+ }
+ else {
+ items.add(index, item);
+ row = index;
+ }
+
+ if (items.size() == 1 && !userModifiedItemHeight)
+ itemHeight = computeItemHeight(item, sizingGC);
+
+ item.initializeHeight(itemHeight);
+
+ if (isRowHeaderVisible() && isAutoWidth()) {
+ rowHeaderWidth = Math.max(rowHeaderWidth,
+ rowHeaderRenderer.computeSize(sizingGC, SWT.DEFAULT, SWT.DEFAULT, item).x);
+ }
+
+ scrollValuesObsolete = true;
+ topIndex = -1;
+ bottomIndex = -1;
+
+ currentVisibleItems++;
+
+ redraw();
+
+ return row;
+ }
+
+ /**
+ * Removes the given item from the table. This method is only called from
+ * the item's dispose method.
+ *
+ * @param item item to remove
+ */
+ void removeItem(GridItem item) {
+ Point[] cells = getCells(item);
+ boolean selectionModified = false;
+
+ items.remove(item);
+
+ dataVisualizer.clearRow(item);
+
+ if (disposing)
+ return;
+
+ if (selectedItems.remove(item))
+ selectionModified = true;
+
+ for (int i = 0; i < cells.length; i++) {
+ if (selectedCells.remove(cells[i]))
+ selectionModified = true;
+ }
+
+ if (focusItem == item) {
+ focusItem = null;
+ }
+
+ scrollValuesObsolete = true;
+ topIndex = -1;
+ bottomIndex = -1;
+ if (item.isVisible()) {
+ currentVisibleItems--;
+ }
+
+ if (selectionModified && !disposing) {
+ updateColumnSelection();
+ }
+
+ redraw();
+ // Need to update the scrollbars see see 375327
+ updateScrollbars();
+ }
+
+ /**
+ * Creates the given column group at the given index. This method is only
+ * called from the {@code GridColumnGroup}'s constructor.
+ *
+ * @param group group to add.
+ */
+ void newColumnGroup(GridColumnGroup group) {
+ GridColumnGroup[] newColumnGroups = new GridColumnGroup[columnGroups.length + 1];
+ System.arraycopy(columnGroups, 0, newColumnGroups, 0, columnGroups.length);
+ newColumnGroups[newColumnGroups.length - 1] = group;
+ columnGroups = newColumnGroups;
+
+ // if we just added the first col group, then we need to up the row
+ // height
+ if (columnGroups.length == 1) {
+ computeHeaderHeight(sizingGC);
+ }
+
+ scrollValuesObsolete = true;
+ redraw();
+ }
+
+ /**
+ * Removes the given column group from the table. This method is only called
+ * from the {@code GridColumnGroup}'s dispose method.
+ *
+ * @param group group to remove.
+ */
+ void removeColumnGroup(GridColumnGroup group) {
+ GridColumnGroup[] newColumnGroups = new GridColumnGroup[columnGroups.length - 1];
+ int newIndex = 0;
+ for (int i = 0; i < columnGroups.length; i++) {
+ if (columnGroups[i] != group) {
+ newColumnGroups[newIndex] = columnGroups[i];
+ newIndex++;
+ }
+ }
+ columnGroups = newColumnGroups;
+
+ if (columnGroups.length == 0) {
+ computeHeaderHeight(sizingGC);
+ }
+
+ scrollValuesObsolete = true;
+ redraw();
+ }
+
+ /**
+ * Updates the cached number of visible items by the given amount.
+ *
+ * @param amount amount to update cached total
+ */
+ void updateVisibleItems(int amount) {
+ currentVisibleItems += amount;
+ }
+
+ /**
+ * Returns the current item in focus.
+ *
+ * @return item in focus or {@code null}.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public GridItem getFocusItem() {
+ checkWidget();
+ return focusItem;
+ }
+
+ /**
+ * Returns the current cell in focus. If cell selection is disabled, this method returns null.
+ *
+ * @return cell in focus or {@code null}. x represents the column and y the row the cell is in
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public Point getFocusCell() {
+ checkWidget();
+ if (!cellSelectionEnabled)
+ return null;
+
+ int x = -1;
+ int y = -1;
+
+ if (focusColumn != null)
+ x = indexOf(focusColumn);
+
+ if (focusItem != null)
+ y = indexOf(focusItem);
+
+ return new Point(x, y);
+ }
+
+ /**
+ * Sets the focused item to the given item.
+ *
+ * @param item item to focus.
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if item is disposed</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setFocusItem(GridItem item) {
+ checkWidget();
+ //TODO: check and make sure this item is valid for focus
+ if (item == null || item.isDisposed() || item.getParent() != this) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ focusItem = item;
+ }
+
+ /**
+ * Sets the focused item to the given column. Column focus is only applicable when cell
+ * selection is enabled.
+ *
+ * @param column column to focus.
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if item is disposed</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setFocusColumn(GridColumn column) {
+ checkWidget();
+ //TODO: check and make sure this item is valid for focus
+ if (column == null || column.isDisposed() || column.getParent() != this || !column.isVisible()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ focusColumn = column;
+ intendedFocusColumn = column;
+ }
+
+ /**
+ * Returns an array of the columns in their display order.
+ *
+ * @return columns in display order
+ */
+ GridColumn[] getColumnsInOrder() {
+ checkWidget();
+ return (GridColumn[]) displayOrderedColumns.toArray(new GridColumn[columns.size()]);
+ }
+
+ /**
+ * Returns true if the table is set to horizontally scroll column-by-column
+ * rather than pixel-by-pixel.
+ *
+ * @return true if the table is scrolled horizontally by column
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean getColumnScrolling() {
+ checkWidget();
+ return columnScrolling;
+ }
+
+ /**
+ * Sets the table scrolling method to either scroll column-by-column (true)
+ * or pixel-by-pixel (false).
+ *
+ * @param columnScrolling true to horizontally scroll by column, false to
+ * scroll by pixel
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setColumnScrolling(boolean columnScrolling) {
+ checkWidget();
+ if (rowHeaderVisible && !columnScrolling) {
+ return;
+ }
+
+ this.columnScrolling = columnScrolling;
+ scrollValuesObsolete = true;
+ redraw();
+ }
+
+ /**
+ * Returns the first visible column that is not spanned by any other column that is either the
+ * given column or any of the columns displaying to the left of the given column. If the
+ * given column and subsequent columns to the right are either not visible or spanned, this
+ * method will return null.
+ *
+ * @param item
+ * @param col
+ * @return
+ */
+ private GridColumn getVisibleColumn_DegradeLeft(GridItem item, GridColumn col) {
+ int index = displayOrderedColumns.indexOf(col);
+
+ GridColumn prevCol = col;
+
+ int i = 0;
+ while (!prevCol.isVisible()) {
+ i++;
+ if (index - i < 0)
+ return null;
+
+ prevCol = (GridColumn) displayOrderedColumns.get(index - i);
+ }
+
+ index = displayOrderedColumns.indexOf(prevCol);
+
+ for (int j = 0; j < index; j++) {
+ GridColumn tempCol = (GridColumn) displayOrderedColumns.get(j);
+
+ if (!tempCol.isVisible()) {
+ continue;
+ }
+
+ if (item.getColumnSpan(indexOf(tempCol)) >= index - j) {
+ prevCol = tempCol;
+ break;
+ }
+ }
+
+ return prevCol;
+ }
+
+ /**
+ * Returns the first visible column that is not spanned by any other column that is either the
+ * given column or any of the columns displaying to the right of the given column. If the
+ * given column and subsequent columns to the right are either not visible or spanned, this
+ * method will return null.
+ *
+ * @param item
+ * @param col
+ * @return
+ */
+ private GridColumn getVisibleColumn_DegradeRight(GridItem item, GridColumn col) {
+ int index = displayOrderedColumns.indexOf(col);
+
+ int i = 0;
+ GridColumn nextCol = col;
+ while (!nextCol.isVisible()) {
+ i++;
+ if (index + i == displayOrderedColumns.size())
+ return null;
+
+ nextCol = (GridColumn) displayOrderedColumns.get(index + i);
+ }
+
+ index = displayOrderedColumns.indexOf(nextCol);
+ int startIndex = index;
+
+ while (index > 0) {
+
+ index--;
+ GridColumn prevCol = (GridColumn) displayOrderedColumns.get(index);
+
+ if (item.getColumnSpan(indexOf(prevCol)) >= startIndex - index) {
+ if (startIndex == displayOrderedColumns.size() - 1) {
+ return null;
+ }
+ else {
+ return getVisibleColumn_DegradeRight(item, (GridColumn) displayOrderedColumns.get(startIndex + 1));
+ }
+ }
+
+ }
+
+ return nextCol;
+ }
+
+ /**
+ * Returns true if the cells are selectable in the reciever.
+ *
+ * @return cell selection enablement status.
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public boolean getCellSelectionEnabled() {
+ checkWidget();
+ return cellSelectionEnabled;
+ }
+
+ /**
+ * Sets whether cells are selectable in the receiver.
+ *
+ * @param cellSelection the cellSelection to set
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void setCellSelectionEnabled(boolean cellSelection) {
+ checkWidget();
+ if (!cellSelection) {
+ selectedCells.clear();
+ redraw();
+ }
+ else {
+ selectedItems.clear();
+ redraw();
+ }
+
+ this.cellSelectionEnabled = cellSelection;
+ }
+
+ /**
+ * @return <code>true</code> if cell selection is enabled
+ */
+ public boolean isCellSelectionEnabled() {
+ return cellSelectionEnabled;
+ }
+
+ /**
+ * Deselects the given cell in the receiver. If the given cell is already
+ * deselected it remains deselected. Invalid cells are ignored.
+ *
+ * @param cell cell to deselect.
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the cell is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void deselectCell(Point cell) {
+ checkWidget();
+
+ if (cell == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ selectedCells.remove(cell);
+ updateColumnSelection();
+ redraw();
+ }
+
+ /**
+ * Deselects the given cells. Invalid cells are ignored.
+ *
+ * @param cells the cells to deselect.
+ *
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the set of cells or any cell is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void deselectCells(Point[] cells) {
+ checkWidget();
+
+ if (cells == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ for (int i = 0; i < cells.length; i++) {
+ if (cells[i] == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ for (int i = 0; i < cells.length; i++) {
+ selectedCells.remove(cells[i]);
+ }
+
+ updateColumnSelection();
+
+ redraw();
+ }
+
+ /**
+ * Deselects all selected cells in the receiver.
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void deselectAllCells() {
+ checkWidget();
+ selectedCells.clear();
+ updateColumnSelection();
+ redraw();
+ }
+
+ /**
+ * Selects the given cell. Invalid cells are ignored.
+ *
+ * @param cell point whose x values is a column index and y value is an item index
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void selectCell(Point cell) {
+ checkWidget();
+
+ if (!cellSelectionEnabled)
+ return;
+
+ if (cell == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ addToCellSelection(cell);
+ updateColumnSelection();
+ redraw();
+ }
+
+ /**
+ * Selects the given cells. Invalid cells are ignored.
+ *
+ * @param cells an arry of points whose x value is a column index and y value is an item index
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the set of cells or an individual cell is null</li>
+ * </ul>
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void selectCells(Point[] cells) {
+ checkWidget();
+
+ if (!cellSelectionEnabled)
+ return;
+
+ if (cells == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+ for (int i = 0; i < cells.length; i++) {
+ if (cells[i] == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
+ for (int i = 0; i < cells.length; i++) {
+ addToCellSelection(cells[i]);
+ }
+
+ updateColumnSelection();
+ redraw();
+ }
+
+ /**
+ * Selects all cells in the receiver.
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void selectAllCells() {
+ checkWidget();
+ selectAllCellsInternal();
+ }
+
+ /**
+ * Selects all cells in the receiver.
+ *
+ * @return An Event object
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ private Event selectAllCellsInternal() {
+ if (!cellSelectionEnabled)
+ return selectAllRowsInternal();
+
+ if (columns.size() == 0)
+ return null;
+
+ if (items.size() == 0)
+ return null;
+
+ int index = 0;
+ GridColumn column = (GridColumn) displayOrderedColumns.get(index);
+
+ while (!column.isVisible()) {
+ index++;
+
+ if (index >= columns.size())
+ return null;
+
+ column = (GridColumn) displayOrderedColumns.get(index);
+ }
+
+ GridColumn oldFocusColumn = focusColumn;
+ GridItem oldFocusItem = focusItem;
+
+ focusColumn = column;
+ focusItem = (GridItem) items.get(0);
+
+ GridItem lastItem = getPreviousVisibleItem(null);
+ GridColumn lastCol = getVisibleColumn_DegradeLeft(lastItem,
+ (GridColumn) displayOrderedColumns.get(displayOrderedColumns.size() - 1));
+
+ Event event = updateCellSelection(new Point(indexOf(lastCol), indexOf(lastItem)), SWT.MOD2, true, false);
+
+ focusColumn = oldFocusColumn;
+ focusItem = oldFocusItem;
+
+ updateColumnSelection();
+
+ redraw();
+ return event;
+ }
+
+ /**
+ * Selects rows in the receiver.
+ *
+ * @return An Event object
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ private Event selectAllRowsInternal() {
+ if (cellSelectionEnabled)
+ return selectAllCellsInternal();
+
+ if (SWT.MULTI != selectionType)
+ return null;
+
+ if (items.size() == 0)
+ return null;
+
+ deselectAll();
+
+ GridItem oldFocusItem = focusItem;
+
+ GridItem firstItem = getItem(getTopIndex());
+ GridItem lastItem = getPreviousVisibleItem(null);
+
+ setFocusItem(firstItem);
+ updateSelection(firstItem, SWT.NONE);
+
+ Event event = updateSelection(lastItem, SWT.MOD2);
+
+ setFocusItem(oldFocusItem);
+
+ redraw();
+ return event;
+ }
+
+ /**
+ * Selects all cells in the given column in the receiver.
+ *
+ * @param col
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void selectColumn(int col) {
+ checkWidget();
+ Vector cells = new Vector();
getCells(getColumn(col), cells);
- selectCells((Point[])cells.toArray(new Point[0]));
- }
-
- /**
- * Selects all cells in the given column group in the receiver.
- *
- * @param colGroup the column group
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void selectColumnGroup(int colGroup) {
- selectColumnGroup(getColumnGroup(colGroup));
- }
-
- /**
- * Selects all cells in the given column group in the receiver.
- *
- * @param colGroup the column group
- *
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void selectColumnGroup(GridColumnGroup colGroup) {
- checkWidget();
- Vector cells = new Vector();
+ selectCells((Point[]) cells.toArray(new Point[0]));
+ }
+
+ /**
+ * Selects all cells in the given column group in the receiver.
+ *
+ * @param colGroup the column group
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void selectColumnGroup(int colGroup) {
+ selectColumnGroup(getColumnGroup(colGroup));
+ }
+
+ /**
+ * Selects all cells in the given column group in the receiver.
+ *
+ * @param colGroup the column group
+ *
+ * @throws org.eclipse.swt.SWTException
+ * <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
+ * created the receiver</li>
+ * </ul>
+ */
+ public void selectColumnGroup(GridColumnGroup colGroup) {
+ checkWidget();
+ Vector cells = new Vector();
getCells(colGroup, cells);
- selectCells((Point[])cells.toArray(new Point[0]));
- }
-
- /**
- * Selects the selection to the given cell. The existing selection is cleared before
- * selecting the given cell.
- *
- * @param cell point whose x values is a column index and y value is an item index
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
- * <li>ERROR_INVALID_ARGUMENT - if the cell is invalid</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setCellSelection(Point cell)
- {
- checkWidget();
-
- if (!cellSelectionEnabled) return;
-
- if (cell == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- if (!isValidCell(cell))
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
-
- selectedCells.clear();
- addToCellSelection(cell);
- updateColumnSelection();
- redraw();
- }
-
- /**
- * Selects the selection to the given set of cell. The existing selection is cleared before
- * selecting the given cells.
- *
- * @param cells point array whose x values is a column index and y value is an item index
- * @throws IllegalArgumentException
- * <ul>
- * <li>ERROR_NULL_ARGUMENT - if the cell array or an individual cell is null</li>
- * <li>ERROR_INVALID_ARGUMENT - if the a cell is invalid</li>
- * </ul>
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public void setCellSelection(Point[] cells)
- {
- checkWidget();
-
- if (!cellSelectionEnabled) return;
-
- if (cells == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- for (int i = 0; i < cells.length; i++)
- {
- if (cells[i] == null)
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
-
- if (!isValidCell(cells[i]))
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
-
- selectedCells.clear();
- for (int i = 0; i < cells.length; i++)
- {
- addToCellSelection(cells[i]);
- }
-
- updateColumnSelection();
- redraw();
- }
-
- /**
- * Returns an array of cells that are currently selected in the
- * receiver. The order of the items is unspecified. An empty array indicates
- * that no items are selected.
- * <p>
- * Note: This is not the actual structure used by the receiver to maintain
- * its selection, so modifying the array will not affect the receiver.
- * </p>
- *
- * @return an array representing the cell selection
- * @throws org.eclipse.swt.SWTException
- * <ul>
- * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
- * created the receiver</li>
- * </ul>
- */
- public Point[] getCellSelection()
- {
- checkWidget();
- return (Point[])selectedCells.toArray(new Point[selectedCells.size()]);
- }
-
-
-
-
- GridColumn getFocusColumn()
- {
- return focusColumn;
- }
-
- void updateColumnFocus()
- {
- if (!focusColumn.isVisible())
- {
- int index = displayOrderedColumns.indexOf(focusColumn);
- if (index > 0)
- {
- GridColumn prev = (GridColumn)displayOrderedColumns.get(index - 1);
- prev = getVisibleColumn_DegradeLeft(focusItem,prev);
- if (prev == null)
- {
- prev = getVisibleColumn_DegradeRight(focusItem,focusColumn);
- }
- focusColumn = prev;
- }<