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 2d96430392 change new to a menu and correctly switch perspective,
fixes #7455 (#7461)
2d96430392 is described below
commit 2d96430392f2a90091f26da8ff6d4a03d2967476
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Wed Jul 8 20:05:23 2026 +0200
change new to a menu and correctly switch perspective, fixes #7455 (#7461)
---
.../hop/ui/core/metadata/MetadataManager.java | 4 +-
.../ui/hopgui/delegates/HopGuiContextDelegate.java | 146 +++++++++++++++++++--
.../perspective/metadata/MetadataPerspective.java | 12 ++
3 files changed, 148 insertions(+), 14 deletions(-)
diff --git
a/ui/src/main/java/org/apache/hop/ui/core/metadata/MetadataManager.java
b/ui/src/main/java/org/apache/hop/ui/core/metadata/MetadataManager.java
index 47dbc23425..39d2cef91b 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/metadata/MetadataManager.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/metadata/MetadataManager.java
@@ -498,7 +498,9 @@ public class MetadataManager<T extends IHopMetadata> {
"MetadataManager.New.Label",
TranslateUtil.translate(this.getManagedName(), managedClass)));
- MetadataPerspective.getInstance().addEditor(editor);
+ MetadataPerspective perspective = MetadataPerspective.getInstance();
+ perspective.activate();
+ perspective.addEditor(editor);
return element;
} catch (Exception e) {
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/delegates/HopGuiContextDelegate.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/delegates/HopGuiContextDelegate.java
index 8ba6ce8f31..c920cdc827 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/delegates/HopGuiContextDelegate.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/delegates/HopGuiContextDelegate.java
@@ -17,11 +17,33 @@
package org.apache.hop.ui.hopgui.delegates;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hop.core.Const;
import org.apache.hop.core.gui.Point;
+import org.apache.hop.core.gui.plugin.IGuiActionLambda;
+import org.apache.hop.core.gui.plugin.action.GuiAction;
import org.apache.hop.core.gui.plugin.action.GuiActionType;
import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.ui.core.ConstUi;
+import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.core.gui.GuiResource;
import org.apache.hop.ui.hopgui.HopGui;
import org.apache.hop.ui.hopgui.context.GuiContextUtil;
+import org.apache.hop.ui.hopgui.context.IGuiContextHandler;
+import org.apache.hop.ui.hopgui.file.HopFileTypeRegistry;
+import org.apache.hop.ui.hopgui.file.IHopFileType;
+import org.apache.hop.ui.hopgui.perspective.metadata.MetadataPerspective;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
public class HopGuiContextDelegate {
@@ -32,22 +54,120 @@ public class HopGuiContextDelegate {
this.hopGui = hopGui;
}
- /** Create a new file, ask which type of file or object you want created */
+ /**
+ * Create a new file or metadata object. This pops up a regular drop-down
menu, anchored below the
+ * "New" toolbar button. The global file types (pipeline, workflow,
markdown, ...) are listed at
+ * the top; below a separator come all metadata types, grouped and ordered
exactly like the "new"
+ * button in the metadata perspective so both menus stay in sync.
+ */
public void fileNew() {
- // Click : shell location + 50, 50
+ Shell shell = hopGui.getShell();
+ Menu menu = new Menu(shell, SWT.POP_UP);
+
+ // 1) Global file types at the top (pipeline, workflow, markdown, ...).
//
- int x = 50 + hopGui.getShell().getLocation().x;
- int y = 50 + hopGui.getShell().getLocation().y;
+ List<GuiAction> fileActions = new ArrayList<>();
+ for (IHopFileType fileType :
HopFileTypeRegistry.getInstance().getFileTypes()) {
+ for (IGuiContextHandler handler : fileType.getContextHandlers()) {
+ fileActions.addAll(
+ GuiContextUtil.getInstance()
+ .filterActions(handler.getSupportedActions(),
GuiActionType.Create));
+ }
+ }
+ fileActions.sort(
+ Comparator.comparing((GuiAction a) -> Const.NVL(a.getCategoryOrder(),
"9999"))
+ .thenComparing(a -> Const.NVL(a.getName(), a.getId())));
+ for (GuiAction action : fileActions) {
+ addActionMenuItem(menu, action, shell);
+ }
- GuiContextUtil.getInstance()
- .handleActionSelection(
- hopGui.getShell(),
- BaseMessages.getString(PKG,
"HopGuiContextDelegate.SelectItemCreate.Dialog.Header"),
- new Point(x, y),
- hopGui,
- GuiActionType.Create,
- "FileNew",
- true);
+ // 2) All metadata types, grouped/ordered exactly like the metadata
perspective's "new" button.
+ //
+ boolean hasFileItems = menu.getItemCount() > 0;
+ if (hasFileItems) {
+ new MenuItem(menu, SWT.SEPARATOR);
+ }
+ MetadataPerspective perspective = HopGui.getMetadataPerspective();
+ int metadataItems = perspective != null ?
perspective.addNewMetadataTypeMenuItems(menu) : 0;
+ // Drop a dangling separator when there were no metadata types to add.
+ if (metadataItems == 0 && hasFileItems) {
+ menu.getItem(menu.getItemCount() - 1).dispose();
+ }
+
+ if (menu.getItemCount() == 0) {
+ menu.dispose();
+ return;
+ }
+
+ // Position the menu just below the "New" toolbar button. Fall back to the
mouse pointer when
+ // the
+ // toolbar item can't be located (e.g. triggered via keyboard shortcut
before the toolbar
+ // built).
+ //
+ ToolItem toolItem = null;
+ if (hopGui.getMainToolbarWidgets() != null) {
+ toolItem =
hopGui.getMainToolbarWidgets().findToolItem(HopGui.ID_MAIN_TOOLBAR_NEW);
+ }
+ if (toolItem != null && !toolItem.isDisposed()) {
+ ToolBar toolBar = toolItem.getParent();
+ Rectangle bounds = toolItem.getBounds();
+ menu.setLocation(toolBar.toDisplay(bounds.x, bounds.y + bounds.height));
+ } else {
+ menu.setLocation(shell.getDisplay().getCursorLocation());
+ }
+
+ // Dispose the menu once it is hidden to avoid leaking widgets.
+ //
+ menu.addListener(SWT.Hide, event ->
menu.getDisplay().asyncExec(menu::dispose));
+
+ menu.setVisible(true);
+ }
+
+ /** Adds a single push menu item for a {@link GuiAction} (icon, label and
its action lambda). */
+ private void addActionMenuItem(Menu menu, GuiAction action, Shell shell) {
+ MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
+ menuItem.setText(Const.NVL(action.getName(), action.getId()));
+
+ // Load the action image (SVG) when there is one.
+ //
+ if (StringUtils.isNotEmpty(action.getImage())) {
+ try {
+ ClassLoader classLoader = action.getClassLoader();
+ if (classLoader == null) {
+ classLoader = getClass().getClassLoader();
+ }
+ Image image =
+ GuiResource.getInstance()
+ .getImage(
+ action.getImage(),
+ classLoader,
+ ConstUi.SMALL_ICON_SIZE,
+ ConstUi.SMALL_ICON_SIZE);
+ menuItem.setImage(image);
+ } catch (Exception e) {
+ // Ignore image loading errors, the menu item text is enough.
+ }
+ }
+
+ menuItem.addListener(
+ SWT.Selection,
+ event -> {
+ boolean shiftClicked = (event.stateMask & SWT.SHIFT) != 0;
+ boolean ctrlClicked = (event.stateMask & SWT.CONTROL) != 0;
+ // Defer execution until the menu is fully closed.
+ //
+ hopGui
+ .getDisplay()
+ .asyncExec(
+ () -> {
+ try {
+ IGuiActionLambda<?> actionLambda =
action.getActionLambda();
+ actionLambda.executeAction(shiftClicked, ctrlClicked);
+ } catch (Exception e) {
+ new ErrorDialog(shell, "Error", "An error occurred
executing action", e);
+ }
+ });
+ });
}
/** Edit a metadata object... */
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
index d09f67a241..f482d7396a 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
@@ -1039,6 +1039,18 @@ public class MetadataPerspective implements
IHopPerspective, TabClosable, IMetad
addNewTypeMenuItems(menu, categoryId);
}
+ /**
+ * Appends one "new" item per metadata type to {@code menu}, grouped by
category (in the
+ * configured order, with a separator between groups) exactly like this
perspective's global "new"
+ * button. Used by the global HopGui "New" drop-down so both menus stay in
sync. Returns the
+ * number of items that were added.
+ */
+ public int addNewMetadataTypeMenuItems(Menu menu) {
+ int before = menu.getItemCount();
+ addNewTypeMenuItems(menu, null);
+ return menu.getItemCount() - before;
+ }
+
/**
* Toggle button controlling whether metadata types and categories with no
items are shown in the
* tree. The icon swaps to reflect the action a click will perform.