From dcbc37ff99a3205a0a4a87c09e35edbc25ba4359 Mon Sep 17 00:00:00 2001 From: Dirk Fauth Date: Tue, 15 Apr 2025 16:12:25 +0200 Subject: [PATCH] Modifications to support NatTable in RAP --- .mvn/extensions.xml | 2 +- .../META-INF/MANIFEST.MF | 6 +- .../nebula/widgets/nattable/Activator.java | 44 +++++ .../nebula/widgets/nattable/NatTable.java | 11 +- .../edit/editor/AbstractCellEditor.java | 21 ++- .../editor/ControlDecorationProvider.java | 52 ++---- .../nattable/edit/editor/TableCellEditor.java | 9 +- .../nattable/edit/editor/TextCellEditor.java | 10 +- .../edit/gui/FileDialogCellEditor.java | 55 +----- .../export/FileOutputStreamProvider.java | 86 +++++---- .../widgets/nattable/export/NatExporter.java | 17 +- .../nattable/export/image/ImageExporter.java | 7 +- .../filterrow/FilterRowTextCellEditor.java | 7 +- .../combobox/FilterRowComboBoxCellEditor.java | 4 +- .../painter/cell/AbstractTextPainter.java | 19 +- .../nattable/painter/cell/GraphicsUtils.java | 35 ++-- .../painter/cell/VerticalTextPainter.java | 13 +- .../persistence/gui/PersistenceDialog.java | 143 ++++++++------- .../print/command/PrintCommandHandler.java | 7 +- .../nattable/style/editor/ColorPicker.java | 34 +--- .../nattable/style/editor/SeparatorPanel.java | 6 +- .../widgets/nattable/ui/ExceptionDialog.java | 11 +- .../widgets/nattable/ui/mode/ModeSupport.java | 16 +- .../ScalingUiBindingConfiguration.java | 8 +- .../widgets/nattable/util/PlatformHelper.java | 173 ++++++++++++++++++ .../nattable/viewport/ScrollBarScroller.java | 19 +- .../widgets/nattable/widget/NatCombo.java | 21 ++- pom.xml | 2 +- target-platform/target-platform.target | 3 +- 29 files changed, 547 insertions(+), 294 deletions(-) create mode 100644 org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/Activator.java create mode 100644 org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/util/PlatformHelper.java diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index da955453f..a16b019d7 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -3,6 +3,6 @@ org.eclipse.tycho tycho-build - 4.0.10 + 4.0.12 \ No newline at end of file diff --git a/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF b/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF index ffc0546c5..be4d417d5 100644 --- a/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF +++ b/org.eclipse.nebula.widgets.nattable.core/META-INF/MANIFEST.MF @@ -222,10 +222,12 @@ Import-Package: org.eclipse.collections.api;version="10.1.0", org.eclipse.swt.events, org.eclipse.swt.graphics, org.eclipse.swt.layout, - org.eclipse.swt.printing, - org.eclipse.swt.program, + org.eclipse.swt.printing;resolution:=optional, + org.eclipse.swt.program;resolution:=optional, org.eclipse.swt.widgets, + org.osgi.framework;version="[1.10.0,2.0.0)", org.slf4j;version="1.7.2" Bundle-Vendor: Eclipse Nebula NatTable Require-Bundle: org.eclipse.equinox.common Automatic-Module-Name: org.eclipse.nebula.widgets.nattable.core +Bundle-Activator: org.eclipse.nebula.widgets.nattable.Activator diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/Activator.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/Activator.java new file mode 100644 index 000000000..5a28b9854 --- /dev/null +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/Activator.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2025 Dirk Fauth and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dirk Fauth - initial API and implementation + ******************************************************************************/ +package org.eclipse.nebula.widgets.nattable; + +import java.lang.reflect.InvocationTargetException; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * Activator that will call the RAPInitializer if available. Needed in an + * activator to ensure that the RAPInitializer is called before any NatTable + * class is loaded. + * + * @since 2.6 + */ +public class Activator implements BundleActivator { + + @Override + public void start(BundleContext context) { + try { + Class forName = getClass().getClassLoader().loadClass("org.eclipse.nebula.widgets.nattable.RAPInitializer"); //$NON-NLS-1$ + if (forName != null) { + forName.getMethod("initialize").invoke(null); //$NON-NLS-1$ + } + } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { + // do nothing, if not running in RAP there is no initializer + } + } + + @Override + public void stop(BundleContext context) throws Exception { + } +} diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java index d5c82fa51..122241d71 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/NatTable.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2023 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -72,6 +72,7 @@ import org.eclipse.nebula.widgets.nattable.ui.mode.ModeSupport; import org.eclipse.nebula.widgets.nattable.util.GUIHelper; import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.nebula.widgets.nattable.viewport.command.RecalculateScrollBarsCommand; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; @@ -281,14 +282,18 @@ public NatTable( this.conflaterChain.add(getVisualChangeEventConflater()); this.conflaterChain.start(); - parent.addListener(SWT.Resize, this.closeEditorOnParentResize); + if (!PlatformHelper.isRAP()) { + parent.addListener(SWT.Resize, this.closeEditorOnParentResize); + } addDisposeListener(e -> { doCommand(new DisposeResourcesCommand()); NatTable.this.conflaterChain.stop(); layer.dispose(); - parent.removeListener(SWT.Resize, NatTable.this.closeEditorOnParentResize); + if (!PlatformHelper.isRAP()) { + parent.removeListener(SWT.Resize, NatTable.this.closeEditorOnParentResize); + } }); } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/AbstractCellEditor.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/AbstractCellEditor.java index a9fa8ba0a..c15faa141 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/AbstractCellEditor.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/AbstractCellEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -393,16 +393,19 @@ public boolean commit(MoveDirectionEnum direction, boolean closeAfterCommit, boo @Override public void close() { - this.closed = true; - if (this.parent != null && !this.parent.isDisposed()) { - this.parent.forceFocus(); - } + if (!this.closed) { + this.closed = true; - removeEditorControlListeners(); + removeEditorControlListeners(); - Control editorControl = getEditorControl(); - if (editorControl != null && !editorControl.isDisposed()) { - editorControl.dispose(); + if (this.parent != null && !this.parent.isDisposed()) { + this.parent.forceFocus(); + } + + Control editorControl = getEditorControl(); + if (editorControl != null && !editorControl.isDisposed()) { + editorControl.dispose(); + } } } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/ControlDecorationProvider.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/ControlDecorationProvider.java index 7445b4db3..130aa20a0 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/ControlDecorationProvider.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/ControlDecorationProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -15,6 +15,7 @@ import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; @@ -116,7 +117,7 @@ public void setErrorDecorationText(String errorText) { public void showErrorDecorationHover(String errorText) { if (this.errorDecoration != null) { this.errorDecoration.show(); - this.errorDecoration.showHoverText(errorText); + PlatformHelper.callSetter(this.errorDecoration, "showHoverText", String.class, errorText); //$NON-NLS-1$ } } @@ -175,8 +176,10 @@ public void hideDecoration() { */ public void dispose() { if (this.errorDecoration != null) { - this.errorDecoration.hide(); - this.errorDecoration.dispose(); + if (this.errorDecoration.getControl() != null && !this.errorDecoration.getControl().isDisposed()) { + this.errorDecoration.hide(); + this.errorDecoration.dispose(); + } this.errorDecoration = null; } } @@ -193,43 +196,28 @@ public void createErrorDecorationIfRequired(final Control controlToDecorate) { if (this.errorDecorationEnabled) { - final Image errorImage = FieldDecorationRegistry.getDefault() - .getFieldDecoration(this.fieldDecorationId).getImage(); + final Image errorImage = FieldDecorationRegistry.getDefault().getFieldDecoration(this.fieldDecorationId).getImage(); if (this.decorationPositionOverride == SWT.DEFAULT) { - controlToDecorate.addPaintListener(new PaintListener() { // Using - // a - // PaintListener - // as - // bounds - // are - // only - // set - // AFTER - // activateCell() + // Using a PaintListener as bounds are only set AFTER + // activateCell() + PlatformHelper.callSetter(controlToDecorate, "addPaintListener", PaintListener.class, new PaintListener() { //$NON-NLS-1$ @Override public void paintControl(PaintEvent e) { - - controlToDecorate.removePaintListener(this); + PlatformHelper.callSetter(controlToDecorate, "removePaintListener", PaintListener.class, this); //$NON-NLS-1$ int position = SWT.TOP; - final Rectangle textBounds = controlToDecorate - .getBounds(); - final Rectangle parentClientArea = controlToDecorate - .getParent().getClientArea(); - if ((parentClientArea.x + parentClientArea.width) > (textBounds.x - + textBounds.width + errorImage - .getBounds().width)) { + final Rectangle textBounds = controlToDecorate.getBounds(); + final Rectangle parentClientArea = controlToDecorate.getParent().getClientArea(); + if ((parentClientArea.x + parentClientArea.width) > (textBounds.x + textBounds.width + errorImage.getBounds().width)) { position |= SWT.RIGHT; } else { position |= SWT.LEFT; } - ControlDecorationProvider.this.errorDecoration = newControlDecoration( - controlToDecorate, errorImage, position); + ControlDecorationProvider.this.errorDecoration = newControlDecoration(controlToDecorate, errorImage, position); } }); } else { - this.errorDecoration = newControlDecoration(controlToDecorate, - errorImage, this.decorationPositionOverride); + this.errorDecoration = newControlDecoration(controlToDecorate, errorImage, this.decorationPositionOverride); } } } @@ -250,10 +238,8 @@ public void paintControl(PaintEvent e) { * SWT.RIGHT, and SWT.CENTER). * @return The created {@link ControlDecoration} */ - private ControlDecoration newControlDecoration(Control controlToDecorate, - Image errorImage, int position) { - final ControlDecoration errorDecoration = new ControlDecoration( - controlToDecorate, position); + private ControlDecoration newControlDecoration(Control controlToDecorate, Image errorImage, int position) { + final ControlDecoration errorDecoration = new ControlDecoration(controlToDecorate, position); errorDecoration.setImage(errorImage); errorDecoration.setDescriptionText(this.errorDecorationText); errorDecoration.hide(); diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/TableCellEditor.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/TableCellEditor.java index 8ba5d6eb2..c0755dda8 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/TableCellEditor.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/TableCellEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2024 Dirk Fauth and others. + * Copyright (c) 2013, 2025 Dirk Fauth and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -41,6 +41,7 @@ import org.eclipse.nebula.widgets.nattable.style.IStyle; import org.eclipse.nebula.widgets.nattable.style.Style; import org.eclipse.nebula.widgets.nattable.util.GUIHelper; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.nebula.widgets.nattable.widget.EditModeEnum; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; @@ -434,6 +435,12 @@ protected Object[] getDataAsArray(Object cellData) { * results in using the OS default height based on the font. */ public int getFixedSubCellHeight() { + if (PlatformHelper.isRAP()) { + // RAP does not know the SWT.MeasureItem event + // it is therefore only possible to use the the default height based + // on the font + return -1; + } return this.fixedSubCellHeight; } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/TextCellEditor.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/TextCellEditor.java index 2c82e0ec3..7df4ba20c 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/TextCellEditor.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/editor/TextCellEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2024 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -28,6 +28,7 @@ import org.eclipse.nebula.widgets.nattable.style.DisplayMode; import org.eclipse.nebula.widgets.nattable.style.HorizontalAlignmentEnum; import org.eclipse.nebula.widgets.nattable.style.IStyle; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.nebula.widgets.nattable.widget.EditModeEnum; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; @@ -384,6 +385,13 @@ public void keyPressed(KeyEvent event) { if (isCommitWithCtrlKey()) { commit = (event.stateMask == SWT.MOD1) ? true : false; } + + // in case of RAP we need to avoid the commit in an edit + // dialog, as the commit from the dialog otherwise fails + if (PlatformHelper.isRAP() && TextCellEditor.this.editMode == EditModeEnum.DIALOG) { + commit = false; + } + MoveDirectionEnum move = MoveDirectionEnum.NONE; if (TextCellEditor.this.moveSelectionOnEnter && TextCellEditor.this.editMode == EditModeEnum.INLINE) { diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/gui/FileDialogCellEditor.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/gui/FileDialogCellEditor.java index fe42b90d7..2e8a2088f 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/gui/FileDialogCellEditor.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/edit/gui/FileDialogCellEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2020 Dirk Fauth and others. + * Copyright (c) 2013, 2025 Dirk Fauth and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -14,6 +14,7 @@ import org.eclipse.jface.window.Window; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.FileDialog; @@ -34,13 +35,6 @@ public class FileDialogCellEditor extends AbstractDialogCellEditor { */ private boolean closed = false; - /* - * (non-Javadoc) - * - * @see - * org.eclipse.nebula.widgets.nattable.edit.editor.AbstractDialogCellEditor - * #open() - */ @Override public int open() { this.selectedFile = getDialogInstance().open(); @@ -54,76 +48,33 @@ public int open() { } } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.nebula.widgets.nattable.edit.editor.AbstractDialogCellEditor - * #createDialogInstance() - */ @Override public FileDialog createDialogInstance() { this.closed = false; return new FileDialog(this.parent.getShell(), SWT.OPEN); } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.nebula.widgets.nattable.edit.editor.AbstractDialogCellEditor - * #getDialogInstance() - */ @Override public FileDialog getDialogInstance() { return (FileDialog) this.dialog; } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.nebula.widgets.nattable.edit.editor.AbstractDialogCellEditor - * #getEditorValue() - */ @Override public Object getEditorValue() { return this.selectedFile; } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.nebula.widgets.nattable.edit.editor.AbstractDialogCellEditor - * #setEditorValue(java.lang.Object) - */ @Override public void setEditorValue(Object value) { - getDialogInstance() - .setFileName(value != null ? value.toString() : null); + PlatformHelper.callSetter(getDialogInstance(), "setFileName", String.class, value != null ? value.toString() : null); //$NON-NLS-1$ } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.nebula.widgets.nattable.edit.editor.AbstractDialogCellEditor - * #close() - */ @Override public void close() { // as the FileDialog does not support a programmatically way of closing, // this method is forced to do nothing } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.nebula.widgets.nattable.edit.editor.AbstractDialogCellEditor - * #isClosed() - */ @Override public boolean isClosed() { return this.closed; diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/FileOutputStreamProvider.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/FileOutputStreamProvider.java index 7ae285e66..4e05f40bc 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/FileOutputStreamProvider.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/FileOutputStreamProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2023 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -14,10 +14,14 @@ package org.eclipse.nebula.widgets.nattable.export; import java.io.File; +import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; import org.eclipse.nebula.widgets.nattable.Messages; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; @@ -56,39 +60,55 @@ public OutputStream getOutputStream(Shell shell) { throw new IllegalArgumentException("Shell can not be null"); //$NON-NLS-1$ } - // ensure the FileDialog is opened in the UI thread - shell.getDisplay().syncExec(() -> { - - FileDialog dialog = new FileDialog(shell, SWT.SAVE); - - String filterPath; - String relativeFileName; - - int lastIndexOfFileSeparator = this.defaultFileName.lastIndexOf(File.separator); - if (lastIndexOfFileSeparator >= 0) { - filterPath = this.defaultFileName.substring(0, lastIndexOfFileSeparator); - relativeFileName = this.defaultFileName.substring(lastIndexOfFileSeparator + 1); - } else { - filterPath = "/"; //$NON-NLS-1$ - relativeFileName = this.defaultFileName; + if (!PlatformHelper.isRAP()) { + // ensure the FileDialog is opened in the UI thread + shell.getDisplay().syncExec(() -> { + + FileDialog dialog = new FileDialog(shell, SWT.SAVE); + + String filterPath; + String relativeFileName; + + int lastIndexOfFileSeparator = this.defaultFileName.lastIndexOf(File.separator); + if (lastIndexOfFileSeparator >= 0) { + filterPath = this.defaultFileName.substring(0, lastIndexOfFileSeparator); + relativeFileName = this.defaultFileName.substring(lastIndexOfFileSeparator + 1); + } else { + filterPath = "/"; //$NON-NLS-1$ + relativeFileName = this.defaultFileName; + } + + PlatformHelper.callSetter(dialog, "setFilterPath", String.class, filterPath); //$NON-NLS-1$ + PlatformHelper.callSetter(dialog, "setOverwrite", boolean.class, true); //$NON-NLS-1$ + + PlatformHelper.callSetter(dialog, "setFileName", String.class, relativeFileName); //$NON-NLS-1$ + PlatformHelper.callSetter(dialog, "setFilterNames", String[].class, this.defaultFilterNames); //$NON-NLS-1$ + dialog.setFilterExtensions(this.defaultFilterExtensions); + this.currentFileName = dialog.open(); + + // reset the extension filter index each time the FileDialog is + // opened + // to avoid the case that if the dialog is cancelled, the old + // value + // index could be accidentally reused + this.extFilterIndex = -1; + + Object filterIndex = PlatformHelper.callGetter(dialog, "getFilterIndex"); //$NON-NLS-1$ + if (filterIndex != null) { + this.extFilterIndex = (int) filterIndex; + } + }); + } else { + // in RAP we simply generate the file in a temporary directory with + // the default file name + try { + Path tempDirectory = Files.createTempDirectory("nattable_export_"); //$NON-NLS-1$ + Path exportFile = tempDirectory.resolve(this.defaultFileName); + this.currentFileName = exportFile.toString(); + } catch (IOException e) { + throw new IllegalStateException("Failed to write the export to a temporary directory", e); //$NON-NLS-1$ } - - dialog.setFilterPath(filterPath); - dialog.setOverwrite(true); - - dialog.setFileName(relativeFileName); - dialog.setFilterNames(this.defaultFilterNames); - dialog.setFilterExtensions(this.defaultFilterExtensions); - this.currentFileName = dialog.open(); - - // reset the extension filter index each time the FileDialog is - // opened - // to avoid the case that if the dialog is cancelled, the old value - // index could be accidentally reused - this.extFilterIndex = -1; - - this.extFilterIndex = dialog.getFilterIndex(); - }); + } if (this.currentFileName == null) { return null; diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/NatExporter.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/NatExporter.java index ebb08c931..7d2df152d 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/NatExporter.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/NatExporter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2023 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -16,6 +16,8 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; @@ -35,9 +37,9 @@ import org.eclipse.nebula.widgets.nattable.summaryrow.command.CalculateSummaryRowValuesCommand; import org.eclipse.nebula.widgets.nattable.ui.ExceptionDialog; import org.eclipse.nebula.widgets.nattable.util.IClientAreaProvider; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; import org.slf4j.Logger; @@ -854,7 +856,7 @@ protected void exportLayer( */ protected void prepareExportProcess(ILayer layer, IConfigRegistry configRegistry) { - if (this.preRender) { + if (this.preRender && !PlatformHelper.isRAP()) { AutoResizeHelper.autoResize(layer, configRegistry); } @@ -948,7 +950,14 @@ protected void openExport(IExporter exporter) { && this.openResult && exporter.getResult() != null && exporter.getResult() instanceof File) { - Program.launch(((File) exporter.getResult()).getAbsolutePath()); + + try { + Class program = Class.forName("org.eclipse.swt.program.Program"); //$NON-NLS-1$ + Method launch = program.getMethod("launch", String.class); //$NON-NLS-1$ + launch.invoke(null, ((File) exporter.getResult()).getAbsolutePath()); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + LOG.info("Could not open the export because org.eclipse.swt.program.Program, you are probably running a RAP application."); //$NON-NLS-1$ + } } } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/image/ImageExporter.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/image/ImageExporter.java index 05368539c..078ea4874 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/image/ImageExporter.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/image/ImageExporter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2024 Original authors and others. + * Copyright (c) 2017, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -20,6 +20,7 @@ import org.eclipse.nebula.widgets.nattable.export.IOutputStreamProvider; import org.eclipse.nebula.widgets.nattable.export.ITableExporter; import org.eclipse.nebula.widgets.nattable.layer.ILayer; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.GC; @@ -122,6 +123,10 @@ public void exportTable(Shell shell, throw new IllegalArgumentException("Shell, layer or configure registry must not be null"); //$NON-NLS-1$ } + if (PlatformHelper.isRAP()) { + throw new IllegalStateException("An export to image is not supported with RAP"); //$NON-NLS-1$ + } + int width = layer.getWidth(); int height = layer.getHeight(); diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowTextCellEditor.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowTextCellEditor.java index 0cdf85a5e..cfc3faf2b 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowTextCellEditor.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/FilterRowTextCellEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2023 Dirk Fauth and others. + * Copyright (c) 2014, 2025 Dirk Fauth and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -20,6 +20,7 @@ import org.eclipse.nebula.widgets.nattable.edit.editor.TextCellEditor; import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.PaintEvent; @@ -84,11 +85,11 @@ public void paintControl(PaintEvent e) { } }; - parent.addPaintListener(paintListener); + PlatformHelper.callSetter(parent, "addPaintListener", PaintListener.class, paintListener); //$NON-NLS-1$ text.addDisposeListener(e -> { service.shutdownNow(); - parent.removePaintListener(paintListener); + PlatformHelper.callSetter(parent, "removePaintListener", PaintListener.class, paintListener); //$NON-NLS-1$ }); return text; diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/combobox/FilterRowComboBoxCellEditor.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/combobox/FilterRowComboBoxCellEditor.java index 85ca94e06..f1f8fdb36 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/combobox/FilterRowComboBoxCellEditor.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/filterrow/combobox/FilterRowComboBoxCellEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2024 Dirk Fauth and others. + * Copyright (c) 2013, 2025 Dirk Fauth and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -233,7 +233,7 @@ public void keyPressed(KeyEvent event) { combo.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent event) { - if (event.keyCode == SWT.SPACE) { + if (event.keyCode == ' ') { commit(MoveDirectionEnum.NONE, (!FilterRowComboBoxCellEditor.this.multiselect && FilterRowComboBoxCellEditor.this.editMode == EditModeEnum.INLINE)); diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/AbstractTextPainter.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/AbstractTextPainter.java index 52fc09d71..a41ad92fb 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/AbstractTextPainter.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/AbstractTextPainter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2024 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -26,9 +26,11 @@ import org.eclipse.nebula.widgets.nattable.style.IStyle; import org.eclipse.nebula.widgets.nattable.style.TextDecorationEnum; import org.eclipse.nebula.widgets.nattable.util.GUIHelper; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; /** @@ -752,18 +754,25 @@ protected void paintDecoration(IStyle cellStyle, GC gc, int x, int y, int length if ((ul || st) && length > 0) { // check and draw underline and strikethrough separately // so it is possible to combine both + FontMetrics metrics = gc.getFontMetrics(); if (ul) { // y = start y of text + font height - half of the font // descent so the underline is between baseline and bottom - int underlineY = y + fontHeight - (gc.getFontMetrics().getDescent() / 2); - gc.drawLine(x, underlineY, x + length, underlineY); + Object descent = PlatformHelper.callGetter(metrics, "getDescent"); //$NON-NLS-1$ + if (descent != null) { + int underlineY = y + fontHeight - (((int) descent) / 2); + gc.drawLine(x, underlineY, x + length, underlineY); + } } if (st) { // y = start y of text + half of font height + ascent // this way lower case characters are also strikethrough - int strikeY = y + (fontHeight / 2) + (gc.getFontMetrics().getLeading() / 2); - gc.drawLine(x, strikeY, x + length, strikeY); + Object leading = PlatformHelper.callGetter(metrics, "getLeading"); //$NON-NLS-1$ + if (leading != null) { + int strikeY = y + (fontHeight / 2) + (((int) leading) / 2); + gc.drawLine(x, strikeY, x + length, strikeY); + } } } } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/GraphicsUtils.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/GraphicsUtils.java index c790c4520..d33bfb9f2 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/GraphicsUtils.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/GraphicsUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2024 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -16,9 +16,11 @@ import org.eclipse.nebula.widgets.nattable.style.BorderStyle; import org.eclipse.nebula.widgets.nattable.style.BorderStyle.BorderModeEnum; import org.eclipse.nebula.widgets.nattable.style.BorderStyle.LineStyleEnum; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; @@ -136,26 +138,27 @@ public static void drawVerticalText(String string, int x, int y, // draw underline and/or strikethrough if (underline || strikethrough) { // check and draw underline and strikethrough separately so it - // is - // possible to combine both + // is possible to combine both + FontMetrics metrics = stringGc.getFontMetrics(); if (underline) { - // y = start y of text + font height - // - half of the font descent so the underline is between - // the - // baseline and the bottom - int underlineY = pt.y - - (stringGc.getFontMetrics().getDescent() / 2); - stringGc.drawLine(0, underlineY, pt.x, underlineY); + // y = start y of text + font height - half of the font + // descent so the underline is between the baseline and the + // bottom + Object descent = PlatformHelper.callGetter(metrics, "getDescent"); //$NON-NLS-1$ + if (descent != null) { + int underlineY = pt.y - (((int) descent) / 2); + stringGc.drawLine(0, underlineY, pt.x, underlineY); + } } if (strikethrough) { // y = start y of text + half of font height + ascent so - // lower - // case characters are - // also strikethrough - int strikeY = (pt.y / 2) - + (stringGc.getFontMetrics().getLeading() / 2); - stringGc.drawLine(0, strikeY, pt.x, strikeY); + // lower case characters are also strikethrough + Object leading = PlatformHelper.callGetter(metrics, "getLeading"); //$NON-NLS-1$ + if (leading != null) { + int strikeY = (pt.y / 2) + (((int) leading) / 2); + stringGc.drawLine(0, strikeY, pt.x, strikeY); + } } } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/VerticalTextPainter.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/VerticalTextPainter.java index 01b36ac3f..b56f6a022 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/VerticalTextPainter.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/painter/cell/VerticalTextPainter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -20,6 +20,7 @@ import org.eclipse.nebula.widgets.nattable.resize.command.RowResizeCommand; import org.eclipse.nebula.widgets.nattable.style.CellStyleUtil; import org.eclipse.nebula.widgets.nattable.style.IStyle; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Rectangle; @@ -231,7 +232,10 @@ public void paintCell(ILayerCell cell, GC gc, Rectangle rectangle, IConfigRegist int horizontalPadding = CellStyleUtil.getHorizontalAlignmentPadding( cellStyle, rectangle, contentHeight); if (horizontalPadding != 0) { - horizontalPadding += gc.getFontMetrics().getLeading(); + Object leading = PlatformHelper.callGetter(gc.getFontMetrics(), "getLeading"); //$NON-NLS-1$ + if (leading != null) { + horizontalPadding += (int) leading; + } } int xOffset = rectangle.y @@ -288,7 +292,10 @@ public void paintCell(ILayerCell cell, GC gc, Rectangle rectangle, IConfigRegist int horizontalPadding = CellStyleUtil.getHorizontalAlignmentPadding(cellStyle, rectangle, contentHeight); if (horizontalPadding != 0) { - horizontalPadding += gc.getFontMetrics().getLeading(); + Object leading = PlatformHelper.callGetter(gc.getFontMetrics(), "getLeading"); //$NON-NLS-1$ + if (leading != null) { + horizontalPadding += (int) leading; + } } int yOffset = -contentHeight - rectangle.y diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/persistence/gui/PersistenceDialog.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/persistence/gui/PersistenceDialog.java index 0a8e36cdf..52399546f 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/persistence/gui/PersistenceDialog.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/persistence/gui/PersistenceDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2022 Dirk Fauth and others. + * Copyright (c) 2012, 2025 Dirk Fauth and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -22,6 +22,7 @@ import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StyledCellLabelProvider; @@ -40,6 +41,7 @@ import org.eclipse.nebula.widgets.nattable.persistence.command.StateChangeEvent; import org.eclipse.nebula.widgets.nattable.persistence.command.StateChangeEvent.StateChangeType; import org.eclipse.nebula.widgets.nattable.util.GUIHelper; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; @@ -157,30 +159,28 @@ public PersistenceDialog(Shell parentShell, NatTable natTable, this.properties = properties; } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets - * .Composite) - */ @Override protected Control createDialogArea(Composite parent) { Composite control = (Composite) super.createDialogArea(parent); Label viewerLabel = new Label(control, SWT.NONE); - viewerLabel - .setText(Messages.getString("PersistenceDialog.viewerLabel")); //$NON-NLS-1$ + viewerLabel.setText(Messages.getString("PersistenceDialog.viewerLabel")); //$NON-NLS-1$ GridDataFactory.fillDefaults().grab(true, false).applyTo(viewerLabel); this.viewer = new TableViewer(control); this.viewer.setContentProvider(new ArrayContentProvider()); - this.viewer.setLabelProvider(new ViewConfigurationNameLabelProvider()); + if (!PlatformHelper.isRAP()) { + this.viewer.setLabelProvider(new ViewConfigurationNameLabelProvider()); + } else { + this.viewer.setLabelProvider(new SimpleViewConfigurationNameLabelProvider()); + } // sort in alphabetical order this.viewer.setComparator(new ViewerComparator()); - GridDataFactory.fillDefaults().grab(true, true) + GridDataFactory + .fillDefaults() + .grab(true, true) .applyTo(this.viewer.getControl()); // layout textbox @@ -192,7 +192,9 @@ protected Control createDialogArea(Composite parent) { Label label = new Label(nameContainer, SWT.NONE); label.setText(Messages.getString("PersistenceDialog.nameLabel")); //$NON-NLS-1$ this.configNameText = new Text(nameContainer, SWT.BORDER); - GridDataFactory.fillDefaults().grab(true, false) + GridDataFactory + .fillDefaults() + .grab(true, false) .applyTo(this.configNameText); this.configNameText.addKeyListener(new KeyAdapter() { @@ -211,60 +213,52 @@ public void keyPressed(KeyEvent event) { } }); - this.configNameDeco = new ControlDecoration(this.configNameText, - SWT.RIGHT); + this.configNameDeco = new ControlDecoration(this.configNameText, SWT.RIGHT); Image image = FieldDecorationRegistry.getDefault() .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR) .getImage(); - this.configNameDeco.setDescriptionText(Messages - .getString("PersistenceDialog.nameErrorText")); //$NON-NLS-1$ + this.configNameDeco.setDescriptionText(Messages.getString("PersistenceDialog.nameErrorText")); //$NON-NLS-1$ this.configNameDeco.setImage(image); this.configNameDeco.hide(); // add click listener on viewer - this.viewer - .addSelectionChangedListener(event -> { - ISelection selection = event.getSelection(); - if (selection instanceof IStructuredSelection && !selection.isEmpty()) { - String configName = ((IStructuredSelection) selection) - .getFirstElement().toString(); - PersistenceDialog.this.configNameText.setText(configName); - } - }); + this.viewer.addSelectionChangedListener(event -> { + ISelection selection = event.getSelection(); + if (selection instanceof IStructuredSelection && !selection.isEmpty()) { + String configName = ((IStructuredSelection) selection) + .getFirstElement().toString(); + PersistenceDialog.this.configNameText.setText(configName); + } + }); // add double click listener this.viewer.addDoubleClickListener(event -> buttonPressed(LOAD_ID)); - this.viewer.add(PersistenceHelper.getAvailableStates(this.properties) - .toArray()); + this.viewer.add(PersistenceHelper.getAvailableStates(this.properties).toArray()); return control; } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse - * .swt.widgets.Composite) - */ @Override protected void createButtonsForButtonBar(Composite parent) { - createButton(parent, DELETE_ID, + createButton( + parent, + DELETE_ID, Messages.getString("PersistenceDialog.buttonDelete"), false); //$NON-NLS-1$ - createButton(parent, SAVE_ID, + createButton( + parent, + SAVE_ID, Messages.getString("PersistenceDialog.buttonSave"), false); //$NON-NLS-1$ - createButton(parent, LOAD_ID, + createButton( + parent, + LOAD_ID, Messages.getString("PersistenceDialog.buttonLoad"), false); //$NON-NLS-1$ - createButton(parent, IDialogConstants.OK_ID, + createButton( + parent, + IDialogConstants.OK_ID, Messages.getString("PersistenceDialog.buttonDone"), false); //$NON-NLS-1$ } - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int) - */ @Override protected void buttonPressed(int buttonId) { if (buttonId == SAVE_ID) { @@ -273,8 +267,7 @@ protected void buttonPressed(int buttonId) { // it is not possible to store an empty configuration with this // dialog // this is because the configuration with an empty name is the - // default - // configuration + // default configuration this.configNameDeco.show(); return; } else { @@ -291,35 +284,30 @@ protected void buttonPressed(int buttonId) { String element = this.viewer.getElementAt(i).toString(); if (configName.equals(element)) { // fire event for a changed view configuration - fireStateChange(new StateChangeEvent(configName, - StateChangeType.CHANGE)); + fireStateChange(new StateChangeEvent(configName, StateChangeType.CHANGE)); return; } } this.viewer.add(configName); // fire event for a newly created view configuration - fireStateChange(new StateChangeEvent(configName, - StateChangeType.CREATE)); + fireStateChange(new StateChangeEvent(configName, StateChangeType.CREATE)); } else if (buttonId == DELETE_ID) { ISelection selection = this.viewer.getSelection(); if (selection instanceof IStructuredSelection && !selection.isEmpty()) { - String configName = ((IStructuredSelection) selection) - .getFirstElement().toString(); + String configName = ((IStructuredSelection) selection).getFirstElement().toString(); PersistenceHelper.deleteState(configName, this.properties); // remove the state name out of the viewer this.viewer.getTable().deselectAll(); this.viewer.remove(configName); this.configNameText.setText(""); //$NON-NLS-1$ // fire event for a deleted view configuration - fireStateChange(new StateChangeEvent(configName, - StateChangeType.DELETE)); + fireStateChange(new StateChangeEvent(configName, StateChangeType.DELETE)); } } else if (buttonId == LOAD_ID) { ISelection selection = this.viewer.getSelection(); if (selection instanceof IStructuredSelection && !selection.isEmpty()) { - String configName = ((IStructuredSelection) selection) - .getFirstElement().toString(); + String configName = ((IStructuredSelection) selection).getFirstElement().toString(); this.natTable.loadState(configName, this.properties); setActiveViewConfigurationName(configName); super.okPressed(); @@ -338,9 +326,12 @@ protected void configureShell(Shell newShell) { @Override protected Point getInitialSize() { - return new Point( - GUIHelper.convertHorizontalPixelToDpi(500, true), - GUIHelper.convertVerticalPixelToDpi(300, true)); + Point size = super.getInitialSize(); + int minHeight = GUIHelper.convertVerticalPixelToDpi(300, true); + if (size.y < minHeight) { + size.y = minHeight; + } + return size; } /** @@ -419,8 +410,7 @@ public void removeStateChangeListener(IStateChangedListener listener) { * @param listeners * The listeners to remove. */ - public void removeAllStateChangeListener( - List listeners) { + public void removeAllStateChangeListener(List listeners) { this.stateChangeListeners.removeAll(listeners); } @@ -466,17 +456,40 @@ public void update(ViewerCell cell) { } Styler styler = null; if (result.length() == 0) { - result = Messages - .getString("PersistenceDialog.defaultStateConfigName"); //$NON-NLS-1$ + result = Messages.getString("PersistenceDialog.defaultStateConfigName"); //$NON-NLS-1$ styler = this.italicStyler; } - StyledString styledString = new StyledString(prefix + result, - styler); + StyledString styledString = new StyledString(prefix + result, styler); cell.setText(styledString.toString()); cell.setStyleRanges(styledString.getStyleRanges()); super.update(cell); } } + + /** + * Simple CellLabelProvider that renders all view configurations the same + * way. Will also add a leading '*' to the current active view + * configuration. + * + * Used in case of RAP where the StyledCellLabelProvider is not known. + */ + class SimpleViewConfigurationNameLabelProvider extends CellLabelProvider { + + @Override + public void update(ViewerCell cell) { + Object element = cell.getElement(); + String result = element == null ? "" : element.toString();//$NON-NLS-1$ + String prefix = ""; //$NON-NLS-1$ + if (result.equals(getActiveViewConfigurationName())) { + prefix = "* "; //$NON-NLS-1$ + } + if (result.length() == 0) { + result = Messages.getString("PersistenceDialog.defaultStateConfigName"); //$NON-NLS-1$ + } + + cell.setText(prefix + result); + } + } } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/command/PrintCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/command/PrintCommandHandler.java index 2ee3aca8e..6128a77cf 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/command/PrintCommandHandler.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/command/PrintCommandHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -16,6 +16,7 @@ import org.eclipse.nebula.widgets.nattable.command.ILayerCommandHandler; import org.eclipse.nebula.widgets.nattable.layer.ILayer; import org.eclipse.nebula.widgets.nattable.print.LayerPrinter; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; /** * {@link ILayerCommandHandler} for handling the {@link PrintCommand}. Simply @@ -39,7 +40,9 @@ public PrintCommandHandler(ILayer layer) { @Override public boolean doCommand(PrintCommand command) { - new LayerPrinter(this.layer, command.getConfigRegistry()).print(command.getShell()); + if (!PlatformHelper.isRAP()) { + new LayerPrinter(this.layer, command.getConfigRegistry()).print(command.getShell()); + } return true; } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/ColorPicker.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/ColorPicker.java index b29dd9d28..9fd3192e4 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/ColorPicker.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/ColorPicker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2024 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -18,10 +18,8 @@ import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.ColorDialog; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; @@ -36,7 +34,6 @@ public class ColorPicker extends CLabel { private Color selectedColor; - private Image image; public ColorPicker(Composite parent, final Color originalColor) { super(parent, SWT.SHADOW_OUT); @@ -44,7 +41,7 @@ public ColorPicker(Composite parent, final Color originalColor) { throw new IllegalArgumentException("null"); //$NON-NLS-1$ } this.selectedColor = originalColor; - setImage(getColorImage(originalColor)); + setBackground(this.selectedColor); addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { @@ -58,22 +55,17 @@ public void mouseDown(MouseEvent e) { }); } - private Image getColorImage(Color color) { - Display display = Display.getCurrent(); - this.image = new Image(display, new Rectangle(10, 10, 70, 20)); - GC gc = new GC(this.image); - try { - gc.setBackground(color); - gc.fillRectangle(this.image.getBounds()); - } finally { - gc.dispose(); - } - return this.image; + @Override + public Point computeSize(int wHint, int hHint, boolean changed) { + // return a fixed size + return new Point( + GUIHelper.convertHorizontalPixelToDpi(70), + GUIHelper.convertVerticalDpiToPixel(20)); } private void update(RGB selected) { this.selectedColor = GUIHelper.getColor(selected); - setImage(getColorImage(this.selectedColor)); + setBackground(this.selectedColor); } /** @@ -98,10 +90,4 @@ public void setSelectedColor(Color backgroundColor) { } update(backgroundColor.getRGB()); } - - @Override - public void dispose() { - super.dispose(); - this.image.dispose(); - } } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/SeparatorPanel.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/SeparatorPanel.java index 7544a552a..46ef01839 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/SeparatorPanel.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/style/editor/SeparatorPanel.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -13,7 +13,6 @@ package org.eclipse.nebula.widgets.nattable.style.editor; import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.GridData; @@ -21,6 +20,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; /** * Adds a separator line and label to the parent panel. @@ -42,7 +42,7 @@ public void initComponents(String label) { setLayoutData(layoutData); // Text label - StyledText gridLinesLabel = new StyledText(this, SWT.NONE); + Text gridLinesLabel = new Text(this, SWT.NONE); gridLinesLabel.setEditable(false); Display display = Display.getDefault(); FontData data = display.getSystemFont().getFontData()[0]; diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/ExceptionDialog.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/ExceptionDialog.java index a69637130..42fc3d41d 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/ExceptionDialog.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/ExceptionDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2020 Dirk Fauth and others. + * Copyright (c) 2016, 2025 Dirk Fauth and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -19,6 +19,7 @@ import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; @@ -101,9 +102,9 @@ protected Control createMessageArea(Composite composite) { @Override protected void createButtonsForButtonBar(Composite parent) { // create OK and Details buttons - createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.OK_ID, PlatformHelper.getIDialogConstantsLabel("OK_LABEL"), true); //$NON-NLS-1$ if (this.exception != null) { - this.detailsButton = createButton(parent, IDialogConstants.DETAILS_ID, IDialogConstants.SHOW_DETAILS_LABEL, false); + this.detailsButton = createButton(parent, IDialogConstants.DETAILS_ID, PlatformHelper.getIDialogConstantsLabel("SHOW_DETAILS_LABEL"), false); //$NON-NLS-1$ } } @@ -123,11 +124,11 @@ private void toggleDetailsArea() { if (this.exceptionAreaCreated) { this.exceptionText.dispose(); this.exceptionAreaCreated = false; - this.detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL); + this.detailsButton.setText(PlatformHelper.getIDialogConstantsLabel("SHOW_DETAILS_LABEL")); //$NON-NLS-1$ opened = false; } else { this.exceptionText = createExceptionText((Composite) getContents()); - this.detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL); + this.detailsButton.setText(PlatformHelper.getIDialogConstantsLabel("HIDE_DETAILS_LABEL")); //$NON-NLS-1$ getContents().getShell().layout(); opened = true; } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/mode/ModeSupport.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/mode/ModeSupport.java index 23713e139..1717bf878 100755 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/mode/ModeSupport.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/mode/ModeSupport.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -16,6 +16,7 @@ import java.util.EnumMap; import org.eclipse.nebula.widgets.nattable.NatTable; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; @@ -34,12 +35,6 @@ */ public class ModeSupport implements KeyListener, MouseListener, MouseMoveListener, MouseTrackListener, FocusListener { - private static final boolean IS_MAC; - - static { - IS_MAC = System.getProperty("os.name").toLowerCase().indexOf("mac") >= 0; //$NON-NLS-1$ //$NON-NLS-2$ - } - private EnumMap modeEventHandlerMap = new EnumMap<>(Mode.class); private IModeEventHandler currentModeEventHandler; @@ -47,9 +42,10 @@ public class ModeSupport implements KeyListener, MouseListener, MouseMoveListene public ModeSupport(NatTable natTable) { natTable.addKeyListener(this); natTable.addMouseListener(this); - natTable.addMouseMoveListener(this); - natTable.addMouseTrackListener(this); natTable.addFocusListener(this); + + PlatformHelper.callSetter(natTable, "addMouseMoveListener", MouseMoveListener.class, this); //$NON-NLS-1$ + PlatformHelper.callSetter(natTable, "addMouseTrackListener", MouseTrackListener.class, this); //$NON-NLS-1$ } /** @@ -157,7 +153,7 @@ public void focusLost(FocusEvent event) { * The {@link MouseEvent} to modify */ private void modifyMouseEventForMac(MouseEvent event) { - if (IS_MAC && event.stateMask == SWT.MOD4 && event.button == 1) { + if (PlatformHelper.isMAC() && event.stateMask == SWT.MOD4 && event.button == 1) { event.stateMask = event.stateMask & ~SWT.MOD4; event.button = 3; } diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/scaling/ScalingUiBindingConfiguration.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/scaling/ScalingUiBindingConfiguration.java index 7c9987362..8afdaeb56 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/scaling/ScalingUiBindingConfiguration.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/ui/scaling/ScalingUiBindingConfiguration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2024 Dirk Fauth and others. + * Copyright (c) 2020, 2025 Dirk Fauth and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -19,7 +19,9 @@ import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry; import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry; import org.eclipse.nebula.widgets.nattable.ui.matcher.KeyEventMatcher; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseWheelListener; /** * Default configuration to add bindings to change the scaling / zoom level of a @@ -101,8 +103,8 @@ public ScalingUiBindingConfiguration(NatTable natTable, boolean percentageScalin * @since 2.6 */ public ScalingUiBindingConfiguration(NatTable natTable, boolean percentageScalingChange, Consumer updater) { - if (natTable != null) { - natTable.addMouseWheelListener(new ScalingMouseWheelListener(percentageScalingChange, updater)); + if (natTable != null && !PlatformHelper.isRAP()) { + PlatformHelper.callSetter(natTable, "addMouseWheelListener", MouseWheelListener.class, new ScalingMouseWheelListener(percentageScalingChange, updater)); //$NON-NLS-1$ } this.percentageScalingChange = percentageScalingChange; this.updater = updater; diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/util/PlatformHelper.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/util/PlatformHelper.java new file mode 100644 index 000000000..2dad83cd3 --- /dev/null +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/util/PlatformHelper.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2025 Dirk Fauth and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Dirk Fauth - initial API and implementation + ******************************************************************************/ +package org.eclipse.nebula.widgets.nattable.util; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Helper class that is used to handle differences in platform implementations + * of SWT. For example to call methods that are available in SWT but not in the + * RAP/RWT implementation. + * + * @since 2.6 + */ +public final class PlatformHelper { + + private static final Logger LOG = LoggerFactory.getLogger(PlatformHelper.class); + + private static final boolean IS_MAC; + + static { + IS_MAC = System.getProperty("os.name").toLowerCase().indexOf("mac") >= 0; //$NON-NLS-1$ //$NON-NLS-2$ + } + + private PlatformHelper() { + // empty private constructor to prevent instantiation + } + + /** + * + * @return true if the SWT platform is rap, + * false if not. + */ + public static boolean isRAP() { + return "rap".equals(SWT.getPlatform()); //$NON-NLS-1$ + } + + /** + * Checks the system property os.name if we are running on a Mac. + * + * @return true if we we are executed on a mac, + * false if not. + */ + public static boolean isMAC() { + return IS_MAC; + } + + private static Map> METHOD_MAPPING = new ConcurrentHashMap<>(); + + /** + * Tries to invoke a getter method on the given object. + * + * @param obj + * The object on which the getter method should be invoked. + * @param methodName + * The name of the getter method to invoke. + * @return The return value of the getter method or null if the + * method does not exist or fails. + */ + public static Object callGetter(Object obj, String methodName) { + String key = obj.getClass().getName() + "#" + methodName; //$NON-NLS-1$ + Optional method = METHOD_MAPPING.computeIfAbsent(key, (k) -> { + try { + Method m = obj.getClass().getMethod(methodName); + return Optional.of(m); + } catch (NoSuchMethodException | IllegalArgumentException e) { + return Optional.empty(); + } + + }); + if (method.isPresent()) { + try { + return method.get().invoke(obj); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + LOG.error("Failed to invoke method \"{}\" on \"{}\"", methodName, obj.getClass().getName(), e); //$NON-NLS-1$ + return null; + } + } + return null; + } + + /** + * Tries to invoke a setter method on the given object. Simply does nothing + * if the setter method does not exist or the invocation fails. + * + * @param obj + * The object on which the setter method should be invoked. + * @param methodName + * The name of the setter method to invoke. + * @param parameterType + * The method parameter. + * @param parameterValue + * The parameter value to set. + */ + public static void callSetter(Object obj, String methodName, Class parameterType, Object parameterValue) { + callSetter(obj, methodName, new Class[] { parameterType }, new Object[] { parameterValue }); + } + + /** + * Tries to invoke a setter method on the given object. Simply does nothing + * if the setter method does not exist or the invocation fails. + * + * @param obj + * The object on which the setter method should be invoked. + * @param methodName + * The name of the setter method to invoke. + * @param parameterTypes + * The list of method parameters. + * @param parameterValues + * The list of parameter values to set. + */ + public static void callSetter(Object obj, String methodName, Class[] parameterTypes, Object[] parameterValues) { + String key = obj.getClass().getName() + "#" + methodName + "#" + Arrays.toString(parameterTypes); //$NON-NLS-1$ //$NON-NLS-2$ + Optional method = METHOD_MAPPING.computeIfAbsent(key, (k) -> { + try { + Method m = obj.getClass().getMethod(methodName, parameterTypes); + return Optional.of(m); + } catch (NoSuchMethodException | IllegalArgumentException e) { + return Optional.empty(); + } + + }); + if (method.isPresent()) { + try { + method.get().invoke(obj, parameterValues); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + LOG.error("Failed to invoke method \"{}\" on \"{}\"", methodName, obj.getClass().getName(), e); //$NON-NLS-1$ + } + } + // else simply do nothing, method does not exist + } + + /** + * Get a label from {@link IDialogConstants}. Needed because in SWT you can + * access the constants directly, while in RWT you need to get an instance + * from which to access the constant. + * + * @param label + * The name of the constant for which the label is requested. + * @return The label for the given label key. + */ + public static String getIDialogConstantsLabel(String label) { + try { + if (IDialogConstants.class.isInterface()) { + return IDialogConstants.class.getField(label).get(null).toString(); + } + Method get = IDialogConstants.class.getMethod("get"); //$NON-NLS-1$ + IDialogConstants invoke = (IDialogConstants) get.invoke(null); + return invoke.getClass().getField(label).get(invoke).toString(); + } catch (NoSuchMethodException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException | InvocationTargetException e) { + return ""; //$NON-NLS-1$ + } + } +} diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/viewport/ScrollBarScroller.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/viewport/ScrollBarScroller.java index 5e6d7e8f2..c993ee09b 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/viewport/ScrollBarScroller.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/viewport/ScrollBarScroller.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2021 Edwin Park and others. + * Copyright (c) 2013, 2025 Edwin Park and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.nebula.widgets.nattable.viewport; +import org.eclipse.nebula.widgets.nattable.util.PlatformHelper; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ScrollBar; @@ -81,12 +82,16 @@ public void setMaximum(int value) { @Override public int getPageIncrement() { - return this.scrollBar.getPageIncrement(); + Object result = PlatformHelper.callGetter(this.scrollBar, "getPageIncrement"); //$NON-NLS-1$ + if (result != null) { + return (int) result; + } + return 0; } @Override public void setPageIncrement(int value) { - this.scrollBar.setPageIncrement(value); + PlatformHelper.callSetter(this.scrollBar, "setPageIncrement", int.class, value); //$NON-NLS-1$ } @Override @@ -101,12 +106,16 @@ public void setThumb(int value) { @Override public int getIncrement() { - return this.scrollBar.getIncrement(); + Object result = PlatformHelper.callGetter(this.scrollBar, "getIncrement"); //$NON-NLS-1$ + if (result != null) { + return (int) result; + } + return 0; } @Override public void setIncrement(int value) { - this.scrollBar.setIncrement(value); + PlatformHelper.callSetter(this.scrollBar, "setIncrement", int.class, value); //$NON-NLS-1$ } @Override diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/widget/NatCombo.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/widget/NatCombo.java index 8c8b80027..69b98b351 100644 --- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/widget/NatCombo.java +++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/widget/NatCombo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2024 Original authors and others. + * Copyright (c) 2012, 2025 Original authors and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -520,11 +520,11 @@ public NatCombo(Composite parent, IStyle cellStyle, int maxVisibleItems, int sty getShell().addListener(SWT.Move, moveListener); addDisposeListener(e -> { - if (NatCombo.this.dropdownShell != null) { - NatCombo.this.dropdownShell.dispose(); - } - NatCombo.this.text.dispose(); NatCombo.this.getShell().removeListener(SWT.Move, moveListener); + + if (NatCombo.this.dropdownShell != null && !NatCombo.this.dropdownShell.isDisposed()) { + NatCombo.this.dropdownShell.close(); + } }); } @@ -752,7 +752,7 @@ public void keyPressed(KeyEvent event) { } event.doit = false; } - } else if (event.keyCode == SWT.SPACE) { + } else if (event.keyCode == ' ') { if (NatCombo.this.multiselect && NatCombo.this.useCheckbox && NatCombo.this.dropdownTable.getSelectionCount() >= 1) { TableItem[] selection = NatCombo.this.dropdownTable.getSelection(); boolean isSelected = selection[0].getChecked(); @@ -777,6 +777,12 @@ public void widgetSelected(SelectionEvent e) { boolean isShiftPressed = (e.stateMask & SWT.MODIFIER_MASK) == SWT.MOD2; TableItem chosenItem = (TableItem) e.item; + // if no item is set in the SelectionEvent, we simply do nothing + // this seems to only happen in Eclipse 3 compatibility mode on + // pressing CTRL + A when the dropdown table has focus + if (chosenItem == null) { + return; + } // Given the ability to filter we need to find the item's // table index which may not match the index in the itemList int itemTableIndex = NatCombo.this.dropdownTable.indexOf(chosenItem); @@ -1414,6 +1420,9 @@ public void notifyListeners(int eventType, Event event) { if (this.dropdownTable != null && !this.dropdownTable.isDisposed()) { this.dropdownTable.notifyListeners(eventType, event); } + if (!isDisposed()) { + super.notifyListeners(eventType, event); + } } public void addSelectionListener(SelectionListener listener) { diff --git a/pom.xml b/pom.xml index 12fdd2009..18af63a95 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ - 4.0.10 + 4.0.12 1.5.2 ${project.version} diff --git a/target-platform/target-platform.target b/target-platform/target-platform.target index 020eaa697..1fef77259 100644 --- a/target-platform/target-platform.target +++ b/target-platform/target-platform.target @@ -16,10 +16,11 @@ + - +