From 21c82e6a1570419aa52ec35e338a3f0b276dcbe6 Mon Sep 17 00:00:00 2001 From: RobertoRoos Date: Fri, 23 Oct 2026 10:57:52 +0200 Subject: [PATCH 1/2] Enabled file drag-n-drop on application itself (over menu bar and toolbar) --- .../ui/application/PhoebusApplication.java | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/core/ui/src/main/java/org/phoebus/ui/application/PhoebusApplication.java b/core/ui/src/main/java/org/phoebus/ui/application/PhoebusApplication.java index f4bc0b9dd6..e52bf9b7a2 100644 --- a/core/ui/src/main/java/org/phoebus/ui/application/PhoebusApplication.java +++ b/core/ui/src/main/java/org/phoebus/ui/application/PhoebusApplication.java @@ -48,11 +48,7 @@ import javafx.scene.control.SeparatorMenuItem; import javafx.scene.control.ToolBar; import javafx.scene.control.Tooltip; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyCodeCombination; -import javafx.scene.input.KeyCombination; -import javafx.scene.input.KeyEvent; -import javafx.scene.input.MouseEvent; +import javafx.scene.input.*; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; @@ -479,6 +475,29 @@ public ToolBar getToolbar() { return toolbar; } + /** + * Event handler for when a file is being dragged into the application to open it. + */ + private void onDragOverFile(DragEvent e) { + final Dragboard db = e.getDragboard(); + if (db.hasFiles()) // Allow any drag operation containing files + e.acceptTransferModes(TransferMode.MOVE); + + e.consume(); + } + + /** + * See `onDragOverFile` - this is called when the drag item was released. + */ + private void onDragDroppedFile(DragEvent e) { + final Dragboard db = e.getDragboard(); + + this.openDroppedResources(db); + + e.setDropCompleted(true); + e.consume(); + } + private void startUI(final MementoTree memento, final JobMonitor monitor) throws Exception { monitor.beginTask(Messages.MonitorTaskUi, 4); @@ -487,6 +506,11 @@ private void startUI(final MementoTree memento, final JobMonitor monitor) throws toolbar = createToolbar(); createTopResourcesMenu(); + menuBar.setOnDragOver(this::onDragOverFile); + menuBar.setOnDragDropped(this::onDragDroppedFile); + toolbar.setOnDragOver(this::onDragOverFile); + toolbar.setOnDragDropped(this::onDragDroppedFile); + DockStage.configureStage(main_stage); // Patch ID of main window // (in case we ever need to identify the main window) @@ -1153,6 +1177,25 @@ private AppResourceDescriptor findApplication(final URI resource, final boolean return applications.get(options.indexOf(result.get())); } + /** + * Callback to trigger the loading of dragged resources. + * For each file the "Choose editor" dialog is shown. + */ + public void openDroppedResources(final Dragboard db) { + + if (!db.hasFiles()) + return; + + var files = db.getFiles(); // Copy, because the event is going to be gone + + Platform.runLater(() -> { + // Run this delayed, closing the drag event first, such that the icon will disappear from the UI + for (File file : files) { + this.openResource(file.toURI(), true); + } + }); + } + /** * @param resource Resource received as command line argument * @param prompt Prompt if there are multiple applications, or use first one? From f2455c19503f25c0fe7d4149a5cf872093b85f20 Mon Sep 17 00:00:00 2001 From: RobertoRoos Date: Fri, 23 Oct 2026 11:25:07 +0200 Subject: [PATCH 2/2] WIP - Adding drop of file into any pane --- .../java/org/phoebus/ui/docking/DockPane.java | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/core/ui/src/main/java/org/phoebus/ui/docking/DockPane.java b/core/ui/src/main/java/org/phoebus/ui/docking/DockPane.java index 3453e21019..97bd79a027 100644 --- a/core/ui/src/main/java/org/phoebus/ui/docking/DockPane.java +++ b/core/ui/src/main/java/org/phoebus/ui/docking/DockPane.java @@ -32,8 +32,10 @@ import javafx.scene.control.SplitPane; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; +import javafx.scene.input.*; import org.phoebus.framework.jobs.JobManager; import org.phoebus.ui.application.Messages; +import org.phoebus.ui.application.PhoebusApplication; import org.phoebus.ui.dialog.DialogHelper; import org.phoebus.ui.javafx.ImageCache; import org.phoebus.ui.javafx.Styles; @@ -46,15 +48,9 @@ import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.input.ContextMenuEvent; -import javafx.scene.input.DragEvent; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; -import javafx.scene.input.TransferMode; import javafx.scene.layout.Border; import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; -import javafx.scene.paint.Color; import javafx.stage.Stage; /** Pane that contains {@link DockItem}s @@ -643,7 +639,8 @@ private void clearDropZoneStyle() */ private void handleDragOver(final DragEvent event) { - if (!isFixed() && DockItem.dragged_item.get() != null) + if (event.getDragboard().hasFiles() || + !isFixed() && DockItem.dragged_item.get() != null) { event.acceptTransferModes(TransferMode.MOVE); @@ -782,9 +779,21 @@ private static String splitEdgeStyle(final DropZone zone) */ private void handleDrop(final DragEvent event) { - if (!event.getDragboard().hasContent(DockItem.DOCK_ITEM)) - return; + boolean result = false; + if (event.getDragboard().hasContent(DockItem.DOCK_ITEM)) + result = handleDropDockItem(event); +// else if (event.getDragboard().hasFiles()) +// result = handleDropFile(event); + if (result) { // Only complete the drop event if a handler ended up handling it + event.setDropCompleted(true); + event.consume(); + } + } + + /** Open a drag-and-dropped dock item. */ + private boolean handleDropDockItem(final DragEvent event) + { // When the cursor is directly over a tab header, let DockItem's own // handler on name_tab manage the swap/insert. Clean up the pane border // since no further DockPane handler will run for this drop. @@ -792,12 +801,12 @@ private void handleDrop(final DragEvent event) { clearDropZoneStyle(); active_drop_zone = DropZone.CENTER; - return; + return false; } final DockItem item = DockItem.dragged_item.getAndSet(null); if (item == null) - return; + return false; final DropZone zone = getDropZone(event.getX(), event.getY()); clearDropZoneStyle(); @@ -813,8 +822,14 @@ private void handleDrop(final DragEvent event) splitAndPlaceTabAsync(item, zone); } - event.setDropCompleted(true); - event.consume(); + return true; + } + + /** Open a drag-and-dropped file item. */ + private boolean handleDropFile(final DragEvent event) + { + PhoebusApplication.INSTANCE.openDroppedResources(event.getDragboard()); + return true; } /** When a tab moves to a different scene, ensure that scene has the same stylesheets. */