This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 500313afed Add selection tracker for shortcuts, fixes #6218, #6217 
(#6304)
500313afed is described below

commit 500313afed4b00b1d75f13bffa8c5464395053df
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Wed Jan 7 21:08:16 2026 +0100

    Add selection tracker for shortcuts, fixes #6218, #6217 (#6304)
---
 .../org/apache/hop/ui/hopgui/HopGuiKeyHandler.java |  2 +-
 .../hopgui/file/pipeline/HopGuiPipelineGraph.java  | 59 ++++++++++++++++
 .../hopgui/file/workflow/HopGuiWorkflowGraph.java  | 32 +++++++++
 .../perspective/explorer/ExplorerPerspective.java  | 10 +++
 .../hopgui/selection/HopGuiSelectionTracker.java   | 81 ++++++++++++++++++++++
 5 files changed, 183 insertions(+), 1 deletion(-)

diff --git a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGuiKeyHandler.java 
b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGuiKeyHandler.java
index c56400829a..2498f3efc1 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/HopGuiKeyHandler.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/HopGuiKeyHandler.java
@@ -156,7 +156,7 @@ public class HopGuiKeyHandler extends KeyAdapter {
         Method method = parentClass.getMethod(shortcut.getParentMethodName());
         if (method != null) {
           method.invoke(parentObject);
-          return true; // Stop looking after 1 execution
+          // return true; // disable for now until we can clean this up
         }
       } catch (Exception ex) {
         LogChannel.UI.logError(
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
index 1ce78d8b3c..4ec638fb22 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
@@ -178,6 +178,7 @@ import 
org.apache.hop.ui.hopgui.file.shared.HopGuiTooltipExtension;
 import org.apache.hop.ui.hopgui.perspective.execution.ExecutionPerspective;
 import org.apache.hop.ui.hopgui.perspective.execution.IExecutionViewer;
 import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
+import org.apache.hop.ui.hopgui.selection.HopGuiSelectionTracker;
 import org.apache.hop.ui.hopgui.shared.SwtGc;
 import org.apache.hop.ui.pipeline.dialog.PipelineDialog;
 import org.apache.hop.ui.util.EnvironmentUtils;
@@ -758,6 +759,10 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
             selectedTransforms = pipelineMeta.getSelectedTransforms();
             selectedTransform = currentTransform;
 
+            // Track that a transform was selected
+            HopGuiSelectionTracker.getInstance()
+                
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
+
             for (ITransformSelectionListener listener : 
currentTransformListeners) {
               listener.onUpdateSelection(currentTransform);
             }
@@ -825,6 +830,9 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
       currentNotePad = (NotePadMeta) areaOwner.getOwner();
       selectedNotes = pipelineMeta.getSelectedNotes();
       selectedNote = currentNotePad;
+      // Track that a note was selected
+      HopGuiSelectionTracker.getInstance()
+          
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
       Point loc = currentNotePad.getLocation();
 
       previousNoteLocations = pipelineMeta.getSelectedNoteLocations();
@@ -957,6 +965,12 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
         pipelineMeta.unselectAll();
         selectInRect(pipelineMeta, selectionRegion);
         selectionRegion = null;
+        // Track that transforms were selected via region selection
+        if (!pipelineMeta.getSelectedTransforms().isEmpty()
+            || !pipelineMeta.getSelectedNotes().isEmpty()) {
+          HopGuiSelectionTracker.getInstance()
+              
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
+        }
         updateGui();
         return;
       }
@@ -1005,6 +1019,11 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
           // Flip selection when control is pressed!
           if (control) {
             selectedTransform.flipSelected();
+            // Track that a transform selection changed (if it's now selected)
+            if (selectedTransform.isSelected()) {
+              HopGuiSelectionTracker.getInstance()
+                  
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
+            }
           } else {
             singleClick = true;
             singleClickType = SingleClickType.Transform;
@@ -1016,11 +1035,19 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
               pipelineMeta.unselectAll();
               selectedTransform.setSelected(true);
             }
+            // Track that a transform was selected
+            HopGuiSelectionTracker.getInstance()
+                
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
           }
         } else {
           // Find out which Transforms & Notes are selected
           selectedTransforms = pipelineMeta.getSelectedTransforms();
           selectedNotes = pipelineMeta.getSelectedNotes();
+          // Track that transforms were selected
+          if (!selectedTransforms.isEmpty() || !selectedNotes.isEmpty()) {
+            HopGuiSelectionTracker.getInstance()
+                
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
+          }
 
           // We moved around some items: store undo info...
           //
@@ -1079,6 +1106,11 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
             // Flip selection when control is pressed!
             if (control) {
               selectedNote.flipSelected();
+              // Track that a note selection changed (if it's now selected)
+              if (selectedNote.isSelected()) {
+                HopGuiSelectionTracker.getInstance()
+                    
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
+              }
             } else {
               // single click on a note: ask what needs to happen...
               //
@@ -1092,11 +1124,19 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
                 pipelineMeta.unselectAll();
                 selectedNote.setSelected(true);
               }
+              // Track that a note was selected
+              HopGuiSelectionTracker.getInstance()
+                  
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
             }
           } else {
             // Find out which Transforms & Notes are selected
             selectedTransforms = pipelineMeta.getSelectedTransforms();
             selectedNotes = pipelineMeta.getSelectedNotes();
+            // Track that notes were selected
+            if (!selectedTransforms.isEmpty() || !selectedNotes.isEmpty()) {
+              HopGuiSelectionTracker.getInstance()
+                  
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
+            }
 
             // We moved around some items: store undo info...
 
@@ -1516,6 +1556,9 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
       selectedTransforms = new ArrayList<>();
       selectedTransforms.add(selectedTransform);
       previousTransformLocations = new Point[] 
{selectedTransform.getLocation()};
+      // Track that a transform was selected
+      HopGuiSelectionTracker.getInstance()
+          
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
       doRedraw = true;
     } else if (selectedNote != null && !selectedNote.isSelected()) {
       pipelineMeta.unselectAll();
@@ -1523,6 +1566,9 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
       selectedNotes = new ArrayList<>();
       selectedNotes.add(selectedNote);
       previousNoteLocations = new Point[] {selectedNote.getLocation()};
+      // Track that a note was selected
+      HopGuiSelectionTracker.getInstance()
+          
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
       doRedraw = true;
     } else if (selectionRegion != null && startHopTransform == null) {
       // Did we select a region...?
@@ -5243,6 +5289,19 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
   @GuiKeyboardShortcut(key = SWT.DEL)
   @Override
   public void deleteSelected() {
+    // Only handle delete if a pipeline graph item was the last selected item
+    // OR if there are actually selected transforms/notes in the pipeline
+    HopGuiSelectionTracker selectionTracker = 
HopGuiSelectionTracker.getInstance();
+    boolean hasPipelineSelection =
+        !pipelineMeta.getSelectedTransforms().isEmpty()
+            || !pipelineMeta.getSelectedNotes().isEmpty();
+    boolean isLastPipelineSelection =
+        
selectionTracker.isLastSelection(HopGuiSelectionTracker.SelectionType.PIPELINE_GRAPH);
+
+    if (!isLastPipelineSelection || !hasPipelineSelection) {
+      return;
+    }
+
     delSelected(null);
     updateGui();
   }
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
index fc9cbfe573..a8883521f2 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
@@ -134,6 +134,7 @@ import 
org.apache.hop.ui.hopgui.file.workflow.extension.HopGuiWorkflowGraphExten
 import org.apache.hop.ui.hopgui.perspective.execution.ExecutionPerspective;
 import org.apache.hop.ui.hopgui.perspective.execution.IExecutionViewer;
 import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
+import org.apache.hop.ui.hopgui.selection.HopGuiSelectionTracker;
 import org.apache.hop.ui.hopgui.shared.SwtGc;
 import org.apache.hop.ui.util.EnvironmentUtils;
 import org.apache.hop.ui.util.HelpUtils;
@@ -691,6 +692,9 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
       currentNotePad = (NotePadMeta) areaOwner.getOwner();
       selectedNotes = workflowMeta.getSelectedNotes();
       selectedNote = currentNotePad;
+      // Track that a note was selected
+      HopGuiSelectionTracker.getInstance()
+          
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.WORKFLOW_GRAPH);
       Point loc = currentNotePad.getLocation();
 
       previousNoteLocations = workflowMeta.getSelectedNoteLocations();
@@ -828,6 +832,12 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
         workflowMeta.unselectAll();
         selectInRect(workflowMeta, selectionRegion);
         selectionRegion = null;
+        // Track that actions/notes were selected via region selection
+        if (!workflowMeta.getSelectedActions().isEmpty()
+            || !workflowMeta.getSelectedNotes().isEmpty()) {
+          HopGuiSelectionTracker.getInstance()
+              
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.WORKFLOW_GRAPH);
+        }
         updateGui();
         return;
       }
@@ -880,11 +890,19 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
               workflowMeta.unselectAll();
               selectedAction.setSelected(true);
             }
+            // Track that an action was selected
+            HopGuiSelectionTracker.getInstance()
+                
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.WORKFLOW_GRAPH);
           }
         } else {
           // Find out which Transforms & Notes are selected
           selectedActions = workflowMeta.getSelectedActions();
           selectedNotes = workflowMeta.getSelectedNotes();
+          // Track that actions/notes were selected
+          if (!selectedActions.isEmpty() || !selectedNotes.isEmpty()) {
+            HopGuiSelectionTracker.getInstance()
+                
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.WORKFLOW_GRAPH);
+          }
 
           // We moved around some items: store undo info...
           //
@@ -977,11 +995,19 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
                 workflowMeta.unselectAll();
                 selectedNote.setSelected(true);
               }
+              // Track that a note was selected
+              HopGuiSelectionTracker.getInstance()
+                  
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.WORKFLOW_GRAPH);
             }
           } else {
             // Find out which Transforms & Notes are selected
             selectedActions = workflowMeta.getSelectedActions();
             selectedNotes = workflowMeta.getSelectedNotes();
+            // Track that actions/notes were selected
+            if (!selectedActions.isEmpty() || !selectedNotes.isEmpty()) {
+              HopGuiSelectionTracker.getInstance()
+                  
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.WORKFLOW_GRAPH);
+            }
 
             // We moved around some items: store undo info...
             boolean also = false;
@@ -2070,6 +2096,12 @@ public class HopGuiWorkflowGraph extends 
HopGuiAbstractGraph
   @GuiKeyboardShortcut(key = SWT.DEL)
   @Override
   public void deleteSelected() {
+    // Only handle delete if a workflow graph item was the last selected item
+    HopGuiSelectionTracker selectionTracker = 
HopGuiSelectionTracker.getInstance();
+    if 
(!selectionTracker.isLastSelection(HopGuiSelectionTracker.SelectionType.WORKFLOW_GRAPH))
 {
+      return;
+    }
+
     deleteSelected(null);
   }
 
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
index 3990d52213..acc57af337 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
@@ -92,6 +92,7 @@ import 
org.apache.hop.ui.hopgui.perspective.explorer.file.ExplorerFileType;
 import 
org.apache.hop.ui.hopgui.perspective.explorer.file.IExplorerFileTypeHandler;
 import org.apache.hop.ui.hopgui.perspective.explorer.file.types.FolderFileType;
 import 
org.apache.hop.ui.hopgui.perspective.explorer.file.types.GenericFileType;
+import org.apache.hop.ui.hopgui.selection.HopGuiSelectionTracker;
 import org.apache.hop.workflow.WorkflowMeta;
 import org.apache.hop.workflow.engine.IWorkflowEngine;
 import org.eclipse.swt.SWT;
@@ -1541,6 +1542,12 @@ public class ExplorerPerspective implements 
IHopPerspective, TabClosable {
   @GuiKeyboardShortcut(key = SWT.DEL)
   @GuiOsxKeyboardShortcut(key = SWT.DEL)
   public void deleteFile() {
+    // Only handle delete if a file was the last selected item
+    HopGuiSelectionTracker selectionTracker = 
HopGuiSelectionTracker.getInstance();
+    if 
(!selectionTracker.isLastSelection(HopGuiSelectionTracker.SelectionType.FILE_EXPLORER))
 {
+      return;
+    }
+
     TreeItem[] selection = tree.getSelection();
     if (selection == null || selection.length == 0) {
       return;
@@ -1872,6 +1879,9 @@ public class ExplorerPerspective implements 
IHopPerspective, TabClosable {
       if (tif == null) {
         return;
       }
+      // Track that a file was selected
+      HopGuiSelectionTracker.getInstance()
+          
.setLastSelectionType(HopGuiSelectionTracker.SelectionType.FILE_EXPLORER);
     }
 
     boolean isFolderSelected = tif != null && tif.fileType instanceof 
FolderFileType;
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/selection/HopGuiSelectionTracker.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/selection/HopGuiSelectionTracker.java
new file mode 100644
index 0000000000..6957873f95
--- /dev/null
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/selection/HopGuiSelectionTracker.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.ui.hopgui.selection;
+
+/**
+ * Tracks the last selected item type to help route keyboard shortcuts 
correctly. This is needed
+ * when multiple components (like file explorer and pipeline graph) share the 
same keyboard
+ * shortcuts but need to act on different types of items.
+ */
+public class HopGuiSelectionTracker {
+
+  private static HopGuiSelectionTracker instance;
+
+  /** The type of item that was last selected */
+  public enum SelectionType {
+    /** A file or folder in the file explorer */
+    FILE_EXPLORER,
+    /** A transform, note, or hop in a pipeline graph */
+    PIPELINE_GRAPH,
+    /** An action, note, or hop in a workflow graph */
+    WORKFLOW_GRAPH,
+    /** No specific selection */
+    NONE
+  }
+
+  private SelectionType lastSelectionType = SelectionType.NONE;
+
+  private HopGuiSelectionTracker() {
+    // Singleton
+  }
+
+  public static HopGuiSelectionTracker getInstance() {
+    if (instance == null) {
+      instance = new HopGuiSelectionTracker();
+    }
+    return instance;
+  }
+
+  /**
+   * Set the last selected item type
+   *
+   * @param selectionType The type of item that was selected
+   */
+  public void setLastSelectionType(SelectionType selectionType) {
+    this.lastSelectionType = selectionType;
+  }
+
+  /**
+   * Get the last selected item type
+   *
+   * @return The type of item that was last selected
+   */
+  public SelectionType getLastSelectionType() {
+    return lastSelectionType;
+  }
+
+  /**
+   * Check if the last selection matches the given type
+   *
+   * @param selectionType The type to check against
+   * @return true if the last selection matches the given type
+   */
+  public boolean isLastSelection(SelectionType selectionType) {
+    return lastSelectionType == selectionType;
+  }
+}

Reply via email to