|
1 | 1 | /*- |
2 | | - * Copyright 2022-2023 QuPath developers, University of Edinburgh |
| 2 | + * Copyright 2022-2026 QuPath developers, University of Edinburgh |
3 | 3 | * |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
|
19 | 19 | import java.nio.file.Files; |
20 | 20 | import java.util.ResourceBundle; |
21 | 21 | import java.util.Set; |
22 | | -import java.util.concurrent.Callable; |
23 | 22 | import java.util.concurrent.ExecutionException; |
24 | 23 | import java.util.concurrent.Executors; |
| 24 | +import java.util.concurrent.Future; |
25 | 25 | import java.util.concurrent.TimeUnit; |
26 | 26 | import java.util.concurrent.TimeoutException; |
27 | 27 |
|
|
58 | 58 | import javafx.stage.Stage; |
59 | 59 | import qupath.ext.djl.DjlTools; |
60 | 60 | import qupath.fx.dialogs.Dialogs; |
| 61 | +import qupath.fx.utils.FXUtils; |
61 | 62 | import qupath.fx.utils.GridPaneUtils; |
62 | 63 | import qupath.lib.common.GeneralTools; |
63 | 64 | import qupath.lib.common.ThreadTools; |
@@ -166,36 +167,24 @@ private void init() { |
166 | 167 | status.get() == EngineStatus.AVAILABLE || status.get() == EngineStatus.PENDING, |
167 | 168 | status)); |
168 | 169 | btnDownload.textProperty().bind(Bindings.createStringBinding(() -> { |
169 | | - switch (status.get()) { |
170 | | - case AVAILABLE: |
171 | | - return bundle.getString("button.download.available"); |
172 | | - case FAILED: |
173 | | - return bundle.getString("button.download.failed"); |
174 | | - case PENDING: |
175 | | - return bundle.getString("button.download.pending"); |
176 | | - case UNAVAILABLE: |
177 | | - return bundle.getString("button.download.unavailable"); |
178 | | - case UNKNOWN: |
179 | | - default: |
180 | | - return bundle.getString("button.download.unknown"); |
181 | | - } |
| 170 | + return switch (status.get()) { |
| 171 | + case AVAILABLE -> bundle.getString("button.download.available"); |
| 172 | + case FAILED -> bundle.getString("button.download.failed"); |
| 173 | + case PENDING -> bundle.getString("button.download.pending"); |
| 174 | + case UNAVAILABLE -> bundle.getString("button.download.unavailable"); |
| 175 | + default -> bundle.getString("button.download.unknown"); |
| 176 | + }; |
182 | 177 | }, status)); |
183 | 178 |
|
184 | 179 | var tooltipDownload = new Tooltip(); |
185 | 180 | tooltipDownload.textProperty().bind(Bindings.createStringBinding(() -> { |
186 | | - switch (status.get()) { |
187 | | - case AVAILABLE: |
188 | | - return String.format(bundle.getString("tooltip.download.available"), name); |
189 | | - case FAILED: |
190 | | - return String.format(bundle.getString("tooltip.download.failed"), name); |
191 | | - case PENDING: |
192 | | - return String.format(bundle.getString("tooltip.download.pending"), name); |
193 | | - case UNAVAILABLE: |
194 | | - return String.format(bundle.getString("tooltip.download.unavailable"), name); |
195 | | - case UNKNOWN: |
196 | | - default: |
197 | | - return String.format(bundle.getString("tooltip.download.unknown"), name); |
198 | | - } |
| 181 | + return switch (status.get()) { |
| 182 | + case AVAILABLE -> String.format(bundle.getString("tooltip.download.available"), name); |
| 183 | + case FAILED -> String.format(bundle.getString("tooltip.download.failed"), name); |
| 184 | + case PENDING -> String.format(bundle.getString("tooltip.download.pending"), name); |
| 185 | + case UNAVAILABLE -> String.format(bundle.getString("tooltip.download.unavailable"), name); |
| 186 | + default -> String.format(bundle.getString("tooltip.download.unknown"), name); |
| 187 | + }; |
199 | 188 | }, status)); |
200 | 189 | btnDownload.setTooltip(tooltipDownload); |
201 | 190 |
|
@@ -254,12 +243,13 @@ private void init() { |
254 | 243 | stage.initOwner(QuPathGUI.getInstance().getStage()); |
255 | 244 | // stage.initModality(Modality.WINDOW_MODAL); |
256 | 245 | stage.setScene(new Scene(pane)); |
| 246 | + FXUtils.addCloseWindowShortcuts(stage); |
257 | 247 | } |
258 | 248 |
|
259 | 249 | private static void updateIconFromStatus(EngineStatus status, Node node) { |
260 | 250 | if (status == null) |
261 | 251 | status = EngineStatus.UNKNOWN; |
262 | | - node.getStyleClass().setAll("djl-engine-status", status.name().toString().toLowerCase()); |
| 252 | + node.getStyleClass().setAll("djl-engine-status", status.name().toLowerCase()); |
263 | 253 | } |
264 | 254 |
|
265 | 255 | private static void updateVersionFromStatus(EngineStatus status, String engineName, Label labelVersion) { |
@@ -336,23 +326,24 @@ private static String getCudaString() { |
336 | 326 |
|
337 | 327 | private void checkEngineStatus(String name, ObjectProperty<EngineStatus> status, long timeoutMillis, boolean doQuietly) { |
338 | 328 | // Request the engine in a background thread, triggering download if necessary |
339 | | - var pool = Executors.newSingleThreadExecutor(ThreadTools.createThreadFactory("djl-engine-request", true)); |
340 | | - updateStatus(status, EngineStatus.PENDING); |
341 | | - var future = pool.submit((Callable<Boolean>)() -> checkEngineAvailability(name, status, doQuietly)); |
342 | | - if (timeoutMillis <= 0) |
343 | | - return; |
344 | | - pool.shutdown(); |
| 329 | + Future<Boolean> future; |
| 330 | + try (var pool = Executors.newSingleThreadExecutor(ThreadTools.createThreadFactory("djl-engine-request", true))) { |
| 331 | + updateStatus(status, EngineStatus.PENDING); |
| 332 | + future = pool.submit(() -> checkEngineAvailability(name, status, doQuietly)); |
| 333 | + if (timeoutMillis <= 0) |
| 334 | + return; |
| 335 | + } |
345 | 336 | try { |
346 | 337 | // Wait until the timeout - engine might already be available & return quickly |
347 | 338 | var result = future.get(timeoutMillis, TimeUnit.MILLISECONDS); |
348 | | - if (result != null && result.booleanValue()) { |
| 339 | + if (result != null && result) { |
349 | 340 | Dialogs.showInfoNotification(TITLE, String.format(bundle.getString("notify.engine.available"), name)); |
350 | 341 | } else |
351 | 342 | logger.debug("No engine available for {}", name); |
352 | 343 | } catch (InterruptedException e) { |
353 | | - logger.error("Requesting for engine " + name + "interrupted!", e); |
| 344 | + logger.error("Request for engine {} interrupted!", name, e); |
354 | 345 | } catch (ExecutionException e) { |
355 | | - logger.error("Error requesting engine " + name + ": " + e.getLocalizedMessage(), e); |
| 346 | + logger.error("Error requesting engine {}: {}", name, e.getMessage(), e); |
356 | 347 | } catch (TimeoutException e) { |
357 | 348 | logger.debug("Request for engine {} timed out - likely either initializing or downloading", name); |
358 | 349 | } |
|
0 commit comments