Skip to content

Commit eeb20d9

Browse files
committed
Impl #158 - [Export] Extend ExportCommand to configure success action
Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
1 parent 5569d4e commit eeb20d9

3 files changed

Lines changed: 175 additions & 22 deletions

File tree

org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/NatExporter.java

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.eclipse.nebula.widgets.nattable.util.PlatformHelper;
4141
import org.eclipse.swt.SWT;
4242
import org.eclipse.swt.graphics.Rectangle;
43+
import org.eclipse.swt.widgets.Display;
4344
import org.eclipse.swt.widgets.ProgressBar;
4445
import org.eclipse.swt.widgets.Shell;
4546
import org.slf4j.Logger;
@@ -107,6 +108,16 @@ public class NatExporter {
107108
*/
108109
private boolean useProgressDialog = false;
109110

111+
/**
112+
* The {@link Runnable} that should be executed after the export finished
113+
* successfully. Useful in case {@link #openResult} is set to
114+
* <code>false</code> so an alternative for reporting the export success can
115+
* be configured.
116+
*
117+
* @since 2.6
118+
*/
119+
private Runnable successRunnable;
120+
110121
/**
111122
* Create a new {@link NatExporter}.
112123
*
@@ -160,13 +171,56 @@ public NatExporter(Shell shell, boolean executeSynchronously) {
160171
* is made based on whether a {@link Shell} is set or not. If a
161172
* {@link Shell} is set and this flag is set to <code>true</code>
162173
* the execution is performed synchronously.
174+
* @param useProgressDialog
175+
* Configure whether the progress should be reported via
176+
* {@link ProgressMonitorDialog}. If set to <code>false</code> a
177+
* custom shell with a {@link ProgressBar} will be shown if the
178+
* shell parameter is not <code>null</code>.
163179
*
164180
* @since 2.3
165181
*/
166182
public NatExporter(Shell shell, boolean executeSynchronously, boolean useProgressDialog) {
183+
this(shell, executeSynchronously, useProgressDialog, true, null);
184+
}
185+
186+
/**
187+
* Create a new {@link NatExporter}.
188+
*
189+
* @param shell
190+
* The {@link Shell} that should be used to open sub-dialogs and
191+
* perform export operations in a background thread. Can be
192+
* <code>null</code> but could lead to
193+
* {@link NullPointerException}s if {@link IExporter} are
194+
* configured, that use a {@link FileOutputStreamProvider}.
195+
* @param executeSynchronously
196+
* Configure whether the export should be performed
197+
* asynchronously or synchronously. By default the decision
198+
* whether the execution should be performed synchronously or not
199+
* is made based on whether a {@link Shell} is set or not. If a
200+
* {@link Shell} is set and this flag is set to <code>true</code>
201+
* the execution is performed synchronously.
202+
* @param useProgressDialog
203+
* Configure whether the progress should be reported via
204+
* {@link ProgressMonitorDialog}. If set to <code>false</code> a
205+
* custom shell with a {@link ProgressBar} will be shown if the
206+
* shell parameter is not <code>null</code>.
207+
* @param openResult
208+
* Configure if the created export result should be opened after
209+
* the export is finished.
210+
* @param successRunnable
211+
* The {@link Runnable} that should be executed after the export
212+
* finished successfully. Useful in case {@link #openResult} is
213+
* set to <code>false</code> so an alternative for reporting the
214+
* export success can be configured.
215+
*
216+
* @since 2.6
217+
*/
218+
public NatExporter(Shell shell, boolean executeSynchronously, boolean useProgressDialog, boolean openResult, Runnable successRunnable) {
167219
this.shell = shell;
168220
this.runAsynchronously = !executeSynchronously;
169221
this.useProgressDialog = useProgressDialog;
222+
this.openResult = openResult;
223+
this.successRunnable = successRunnable;
170224
}
171225

172226
/**
@@ -946,17 +1000,29 @@ protected void setClientAreaToMaximum(ILayer layer) {
9461000
* @since 1.5
9471001
*/
9481002
protected void openExport(IExporter exporter) {
949-
if (this.exportSucceeded
950-
&& this.openResult
951-
&& exporter.getResult() != null
952-
&& exporter.getResult() instanceof File) {
1003+
if (this.exportSucceeded) {
9531004

954-
try {
955-
Class<?> program = Class.forName("org.eclipse.swt.program.Program"); //$NON-NLS-1$
956-
Method launch = program.getMethod("launch", String.class); //$NON-NLS-1$
957-
launch.invoke(null, ((File) exporter.getResult()).getAbsolutePath());
958-
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
959-
LOG.info("Could not open the export because org.eclipse.swt.program.Program, you are probably running a RAP application."); //$NON-NLS-1$
1005+
if (this.successRunnable != null) {
1006+
if (this.shell != null) {
1007+
this.shell.getDisplay().syncExec(() -> {
1008+
this.successRunnable.run();
1009+
});
1010+
} else {
1011+
this.successRunnable.run();
1012+
}
1013+
}
1014+
1015+
if (this.openResult
1016+
&& exporter.getResult() != null
1017+
&& exporter.getResult() instanceof File) {
1018+
1019+
try {
1020+
Class<?> program = Class.forName("org.eclipse.swt.program.Program"); //$NON-NLS-1$
1021+
Method launch = program.getMethod("launch", String.class); //$NON-NLS-1$
1022+
launch.invoke(null, ((File) exporter.getResult()).getAbsolutePath());
1023+
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
1024+
LOG.info("Could not open the export because org.eclipse.swt.program.Program, you are probably running a RAP application."); //$NON-NLS-1$
1025+
}
9601026
}
9611027
}
9621028
}
@@ -1061,4 +1127,20 @@ public boolean isUseProgressDialog() {
10611127
public void setUseProgressDialog(boolean useProgressDialog) {
10621128
this.useProgressDialog = useProgressDialog;
10631129
}
1130+
1131+
/**
1132+
* Configure a {@link Runnable} that should be executed after a successful
1133+
* export operation. If a {@link #shell} is set, the {@link Runnable} is
1134+
* executed using {@link Display#syncExec(Runnable)}.
1135+
*
1136+
* @param successRunnable
1137+
* The {@link Runnable} that should be executed after the export
1138+
* finished successfully. Useful in case {@link #openResult} is
1139+
* set to <code>false</code> so an alternative for reporting the
1140+
* export success can be configured.
1141+
* @since 2.6
1142+
*/
1143+
public void setSuccessRunnable(Runnable successRunnable) {
1144+
this.successRunnable = successRunnable;
1145+
}
10641146
}

org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/command/ExportCommand.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2012, 2023 Original authors and others.
2+
* Copyright (c) 2012, 2025 Original authors and others.
33
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
@@ -31,6 +31,8 @@ public class ExportCommand extends AbstractContextFreeCommand {
3131
private final boolean executeSynchronously;
3232
private final boolean useProgressDialog;
3333
private final ILayerExporter exporter;
34+
private final boolean openResult;
35+
private final Runnable successRunnable;
3436

3537
/**
3638
* Creates a new {@link ExportCommand}.
@@ -124,11 +126,59 @@ public ExportCommand(IConfigRegistry configRegistry, Shell shell, boolean execut
124126
* @since 2.3
125127
*/
126128
public ExportCommand(IConfigRegistry configRegistry, Shell shell, boolean executeSynchronously, boolean useProgressDialog, ILayerExporter exporter) {
129+
this(configRegistry, shell, executeSynchronously, useProgressDialog, exporter, true, null);
130+
}
131+
132+
/**
133+
* Creates a new {@link ExportCommand}.
134+
*
135+
* @param configRegistry
136+
* The {@link IConfigRegistry} that contains the necessary export
137+
* configurations.
138+
* @param shell
139+
* The {@link Shell} that should be used to open sub-dialogs and
140+
* perform export operations in a background thread. Can be
141+
* <code>null</code> which definitely leads to synchronous
142+
* execution but could cause errors in case sub-dialogs should be
143+
* opened before exporting.
144+
* @param executeSynchronously
145+
* Configure if the export should be performed synchronously even
146+
* if a {@link Shell} is set.
147+
* @param useProgressDialog
148+
* Configure whether the progress should be reported via
149+
* {@link ProgressMonitorDialog}. If set to <code>false</code> a
150+
* custom shell with a {@link ProgressBar} will be shown if the
151+
* shell parameter is not <code>null</code>.
152+
* @param exporter
153+
* The {@link ILayerExporter} that should be used. Can be
154+
* <code>null</code>, which causes the usage of the exporter
155+
* registered in the {@link IConfigRegistry}.
156+
* @param openResult
157+
* Configure if the created export result should be opened after
158+
* the export is finished.
159+
* @param successRunnable
160+
* The {@link Runnable} that should be executed after the export
161+
* finished successfully. Useful in case {@link #openResult} is
162+
* set to <code>false</code> so an alternative for reporting the
163+
* export success can be configured.
164+
* @since 2.6
165+
*/
166+
public ExportCommand(
167+
IConfigRegistry configRegistry,
168+
Shell shell,
169+
boolean executeSynchronously,
170+
boolean useProgressDialog,
171+
ILayerExporter exporter,
172+
boolean openResult,
173+
Runnable successRunnable) {
174+
127175
this.configRegistry = configRegistry;
128176
this.shell = shell;
129177
this.executeSynchronously = executeSynchronously;
130178
this.useProgressDialog = useProgressDialog;
131179
this.exporter = exporter;
180+
this.openResult = openResult;
181+
this.successRunnable = successRunnable;
132182
}
133183

134184
/**
@@ -185,4 +235,26 @@ public boolean isUseProgressDialog() {
185235
public ILayerExporter getExporter() {
186236
return this.exporter;
187237
}
238+
239+
/**
240+
*
241+
* @return <code>true</code> if the created export file should be opened
242+
* after the export finished successfully, <code>false</code> if not
243+
* @since 2.6
244+
*/
245+
public boolean isOpenResult() {
246+
return this.openResult;
247+
}
248+
249+
/**
250+
*
251+
* @return The {@link Runnable} that should be executed after the export
252+
* finished successfully. Useful in case {@link #openResult} is set
253+
* to <code>false</code> so an alternative for reporting the export
254+
* success can be configured.
255+
* @since 2.6
256+
*/
257+
public Runnable getSuccessRunnable() {
258+
return this.successRunnable;
259+
}
188260
}

org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/export/command/ExportCommandHandler.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2012, 2023 Original authors and others.
2+
* Copyright (c) 2012, 2025 Original authors and others.
33
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
@@ -37,18 +37,17 @@ public ExportCommandHandler(ILayer layer) {
3737

3838
@Override
3939
public boolean doCommand(final ExportCommand command) {
40+
NatExporter natExporter = new NatExporter(
41+
command.getShell(),
42+
command.isExecuteSynchronously(),
43+
command.isUseProgressDialog(),
44+
command.isOpenResult(),
45+
command.getSuccessRunnable());
46+
4047
if (command.getExporter() == null) {
41-
new NatExporter(
42-
command.getShell(),
43-
command.isExecuteSynchronously(),
44-
command.isUseProgressDialog())
45-
.exportSingleLayer(this.layer, command.getConfigRegistry());
48+
natExporter.exportSingleLayer(this.layer, command.getConfigRegistry());
4649
} else {
47-
new NatExporter(
48-
command.getShell(),
49-
command.isExecuteSynchronously(),
50-
command.isUseProgressDialog())
51-
.exportSingleLayer(command.getExporter(), this.layer, command.getConfigRegistry());
50+
natExporter.exportSingleLayer(command.getExporter(), this.layer, command.getConfigRegistry());
5251
}
5352

5453
return true;

0 commit comments

Comments
 (0)