This is an automated email from the ASF dual-hosted git repository.
mattcasters 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 148577f00c Add support for dynamically adding plugin tabs in workflow
and pipeline graphs. #7385 (#7386)
148577f00c is described below
commit 148577f00c81e182c0b83f1a0d1f124d85e5436c
Author: Nicolas Adment <[email protected]>
AuthorDate: Wed Jul 1 10:19:38 2026 +0200
Add support for dynamically adding plugin tabs in workflow and pipeline
graphs. #7385 (#7386)
Nice!
---
.../hopgui/file/pipeline/HopGuiPipelineGraph.java | 55 ++++++++++++++++++++++
.../hopgui/file/workflow/HopGuiWorkflowGraph.java | 54 +++++++++++++++++++++
2 files changed, 109 insertions(+)
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 695102723d..601e29dddd 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
@@ -18,11 +18,13 @@
package org.apache.hop.ui.hopgui.file.pipeline;
import java.io.OutputStream;
+import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -61,12 +63,14 @@ import org.apache.hop.core.gui.Point;
import org.apache.hop.core.gui.Rectangle;
import org.apache.hop.core.gui.SnapAllignDistribute;
import org.apache.hop.core.gui.plugin.GuiPlugin;
+import org.apache.hop.core.gui.plugin.GuiRegistry;
import org.apache.hop.core.gui.plugin.IGuiActionLambda;
import org.apache.hop.core.gui.plugin.IGuiRefresher;
import org.apache.hop.core.gui.plugin.action.GuiAction;
import org.apache.hop.core.gui.plugin.action.GuiActionType;
import org.apache.hop.core.gui.plugin.key.GuiKeyboardShortcut;
import org.apache.hop.core.gui.plugin.key.GuiOsxKeyboardShortcut;
+import org.apache.hop.core.gui.plugin.tab.GuiTabItem;
import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElement;
import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElementType;
import org.apache.hop.core.logging.DefaultLogLevel;
@@ -188,6 +192,7 @@ import org.apache.hop.ui.util.HelpUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
@@ -289,6 +294,8 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
public static final String PIPELINE_GRAPH_DIALOG_HOP_CAUSES_LOOP_MESSAGE =
"PipelineGraph.Dialog.HopCausesLoop.Message";
+ public static final String PIPELINE_GRAPH_TABS =
"HopGuiPipelineGraph.Tabs.ID";
+
private final ILogChannel log;
private static final int HOP_SEL_MARGIN = 9;
@@ -4386,6 +4393,53 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
}
}
+ private static final String EXTRA_TAB_ID = "EXTRA_TAB_ID";
+
+ private void addPluginTabs() {
+ GuiRegistry guiRegistry = GuiRegistry.getInstance();
+ List<GuiTabItem> tabsList =
guiRegistry.getGuiTabsMap().get(PIPELINE_GRAPH_TABS);
+ if (tabsList != null) {
+ tabsList.sort(Comparator.comparing(GuiTabItem::getId));
+ for (GuiTabItem tabItem : tabsList) {
+
+ // Check if tab already exist
+ if (checkTabExist(tabItem)) {
+ continue;
+ }
+
+ // Create the tab
+ try {
+ Class<?> pluginTabClass = tabItem.getMethod().getDeclaringClass();
+ Constructor<?> constructor =
+ pluginTabClass.getConstructor(HopGui.class,
HopGuiPipelineGraph.class);
+ Object object = constructor.newInstance(hopGui, this);
+ CTabItem tab = (CTabItem) tabItem.getMethod().invoke(object,
extraViewTabFolder);
+ tab.setData(EXTRA_TAB_ID, tabItem.getId());
+ } catch (Exception e) {
+ new ErrorDialog(
+ getShell(),
+ CONST_ERROR,
+ "Hop was unable to invoke @GuiTab method "
+ + tabItem.getMethod().getName()
+ + " with the parent composite as argument",
+ e);
+ }
+ }
+ extraViewTabFolder.layout();
+ }
+ }
+
+ private boolean checkTabExist(GuiTabItem guiTabItem) {
+ if (extraViewTabFolder != null) {
+ for (CTabItem item : this.extraViewTabFolder.getItems()) {
+ if (guiTabItem.getId().equals(item.getData(EXTRA_TAB_ID))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
@Override
public void close() {
perspective.remove(this);
@@ -4867,6 +4921,7 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
pipelineLogDelegate.addPipelineLog();
pipelineGridDelegate.addPipelineGrid();
pipelineCheckDelegate.addPipelineCheck();
+ addPluginTabs();
if (extraViewTabFolder.getSelectionIndex() == -1) {
extraViewTabFolder.setSelection(0);
}
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 fc87bc46f9..2161bdb2e0 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
@@ -18,10 +18,12 @@
package org.apache.hop.ui.hopgui.file.workflow;
import java.io.OutputStream;
+import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -58,12 +60,14 @@ import org.apache.hop.core.gui.Rectangle;
import org.apache.hop.core.gui.SnapAllignDistribute;
import org.apache.hop.core.gui.WorkflowTracker;
import org.apache.hop.core.gui.plugin.GuiPlugin;
+import org.apache.hop.core.gui.plugin.GuiRegistry;
import org.apache.hop.core.gui.plugin.IGuiActionLambda;
import org.apache.hop.core.gui.plugin.IGuiRefresher;
import org.apache.hop.core.gui.plugin.action.GuiAction;
import org.apache.hop.core.gui.plugin.action.GuiActionType;
import org.apache.hop.core.gui.plugin.key.GuiKeyboardShortcut;
import org.apache.hop.core.gui.plugin.key.GuiOsxKeyboardShortcut;
+import org.apache.hop.core.gui.plugin.tab.GuiTabItem;
import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElement;
import org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElementType;
import org.apache.hop.core.logging.HopLogStore;
@@ -159,6 +163,7 @@ import org.apache.hop.workflow.engine.WorkflowEngineFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
@@ -233,6 +238,8 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
public static final String TOOLBAR_ITEM_TO_EXECUTION_INFO =
"HopGuiWorkflowGraph-ToolBar-10475-ToExecutionInfo";
+ public static final String WORKFLOW_GRAPH_TABS =
"HopGuiWorkflowGraph.Tabs.ID";
+
private static final String STRING_PARALLEL_WARNING_PARAMETER =
"ParallelActionsWarning";
private static final int HOP_SEL_MARGIN = 9;
@@ -4036,6 +4043,7 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
workflowLogDelegate.addWorkflowLog();
workflowGridDelegate.addWorkflowGrid();
workflowCheckDelegate.addWorkflowCheck();
+ addPluginTabs();
if (extraViewTabFolder.getSelectionIndex() == -1) {
extraViewTabFolder.setSelection(0);
}
@@ -4049,6 +4057,52 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
hopGui.refreshSidebarToolbarButtonStates();
}
+ private static final String EXTRA_TAB_ID = "EXTRA_TAB_ID";
+
+ private void addPluginTabs() {
+ List<GuiTabItem> tabsList =
GuiRegistry.getInstance().getGuiTabsMap().get(WORKFLOW_GRAPH_TABS);
+ if (tabsList != null) {
+ tabsList.sort(Comparator.comparing(GuiTabItem::getId));
+ for (GuiTabItem tabItem : tabsList) {
+
+ // Check if tab already exists
+ if (checkTabExist(tabItem)) {
+ continue;
+ }
+
+ // Create the tab
+ try {
+ Class<?> pluginTabClass = tabItem.getMethod().getDeclaringClass();
+ Constructor<?> constructor =
+ pluginTabClass.getConstructor(HopGui.class,
HopGuiWorkflowGraph.class);
+ Object object = constructor.newInstance(hopGui, this);
+ CTabItem tab = (CTabItem) tabItem.getMethod().invoke(object,
extraViewTabFolder);
+ tab.setData(EXTRA_TAB_ID, tabItem.getId());
+ } catch (Exception e) {
+ new ErrorDialog(
+ getShell(),
+ CONST_ERROR,
+ "Hop was unable to invoke @GuiTab method "
+ + tabItem.getMethod().getName()
+ + " with the parent composite as argument",
+ e);
+ }
+ }
+ extraViewTabFolder.layout();
+ }
+ }
+
+ private boolean checkTabExist(GuiTabItem guiTabItem) {
+ if (extraViewTabFolder != null) {
+ for (CTabItem item : this.extraViewTabFolder.getItems()) {
+ if (guiTabItem.getId().equals(item.getData(EXTRA_TAB_ID))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
@Override
public void close() {
perspective.remove(this);