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 2e399c63f9 Prevent the creation of invalid hops in a visual manner
#6281 (#6293)
2e399c63f9 is described below
commit 2e399c63f97c5d064901fa313a47086882bbc610
Author: Nicolas Adment <[email protected]>
AuthorDate: Tue Jan 6 11:20:04 2026 +0100
Prevent the creation of invalid hops in a visual manner #6281 (#6293)
---
.../java/org/apache/hop/pipeline/PipelineMeta.java | 51 +++---
.../org/apache/hop/pipeline/PipelinePainter.java | 16 +-
.../java/org/apache/hop/workflow/WorkflowMeta.java | 73 ++++-----
.../org/apache/hop/workflow/WorkflowPainter.java | 21 +--
.../hopgui/file/pipeline/HopGuiPipelineGraph.java | 160 ++++++++++--------
.../hopgui/file/workflow/HopGuiWorkflowGraph.java | 179 ++++++++++++---------
.../delegates/HopGuiWorkflowHopDelegate.java | 10 +-
.../workflow/messages/messages_en_US.properties | 5 +-
.../workflow/messages/messages_fr_FR.properties | 2 +-
.../ui/hopgui/messages/messages_en_US.properties | 2 +-
10 files changed, 287 insertions(+), 232 deletions(-)
diff --git a/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
b/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
index 02923524d5..b940234ce1 100644
--- a/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
+++ b/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
@@ -581,10 +581,10 @@ public class PipelineMeta extends AbstractMeta
* metadata at the specified index to the specified meta-data object.
*
* @param i The index into the hops list
- * @param hi The hop meta-data to set
+ * @param hop The hop meta-data to set
*/
- public void setPipelineHop(int i, PipelineHopMeta hi) {
- hops.set(i, hi);
+ public void setPipelineHop(int i, PipelineHopMeta hop) {
+ hops.set(i, hop);
clearCaches();
}
@@ -649,15 +649,12 @@ public class PipelineMeta extends AbstractMeta
* Searches the list of hops for a hop with a certain name.
*
* @param name The name of the hop to look for
- * @return The hop information or null if nothing was found.
+ * @return The hop found or null if nothing was found.
*/
public PipelineHopMeta findPipelineHop(String name) {
- int i;
-
- for (i = 0; i < nrPipelineHops(); i++) {
- PipelineHopMeta hi = getPipelineHop(i);
- if (hi.toString().equalsIgnoreCase(name)) {
- return hi;
+ for (PipelineHopMeta hop : hops) {
+ if (hop.toString().equalsIgnoreCase(name)) {
+ return hop;
}
}
return null;
@@ -667,13 +664,14 @@ public class PipelineMeta extends AbstractMeta
* Search all hops for a hop where a certain transform is at the start.
*
* @param fromTransform The transform at the start of the hop.
- * @return The hop or null if no hop was found.
+ * @return The first hop found or null if nothing was found.
*/
public PipelineHopMeta findPipelineHopFrom(TransformMeta fromTransform) {
- for (PipelineHopMeta hop : hops) {
- if (hop.getFromTransform() != null
- && hop.getFromTransform().equals(fromTransform)) { // return the
first
- return hop;
+ if (fromTransform != null) {
+ for (PipelineHopMeta hop : hops) {
+ if (fromTransform.equals(hop.getFromTransform())) { // return the first
+ return hop;
+ }
}
}
return null;
@@ -689,11 +687,11 @@ public class PipelineMeta extends AbstractMeta
/**
* Find a certain hop in the pipeline.
*
- * @param hi The hop information to look for.
+ * @param hop The hop information to look for.
* @return The hop or null if no hop was found.
*/
- public PipelineHopMeta findPipelineHop(PipelineHopMeta hi) {
- return findPipelineHop(hi.getFromTransform(), hi.getToTransform());
+ public PipelineHopMeta findPipelineHop(PipelineHopMeta hop) {
+ return findPipelineHop(hop.getFromTransform(), hop.getToTransform());
}
/**
@@ -712,13 +710,13 @@ public class PipelineMeta extends AbstractMeta
*
* @param from The transform at the start of the hop.
* @param to The transform at the end of the hop.
- * @param disabledToo the disabled too
+ * @param includeDisabled include disabled hop
* @return The hop or null if no hop was found.
*/
public PipelineHopMeta findPipelineHop(
- TransformMeta from, TransformMeta to, boolean disabledToo) {
+ TransformMeta from, TransformMeta to, boolean includeDisabled) {
for (PipelineHopMeta hop : hops) {
- if ((hop.isEnabled() || disabledToo)
+ if ((hop.isEnabled() || includeDisabled)
&& hop.getFromTransform() != null
&& hop.getToTransform() != null
&& hop.getFromTransform().equals(from)
@@ -733,13 +731,14 @@ public class PipelineMeta extends AbstractMeta
* Search all hops for a hop where a certain transform is at the end.
*
* @param toTransform The transform at the end of the hop.
- * @return The hop or null if no hop was found.
+ * @return The hop or null if nothing was found.
*/
public PipelineHopMeta findPipelineHopTo(TransformMeta toTransform) {
- for (PipelineHopMeta hop : hops) {
- if (hop.getToTransform() != null
- && hop.getToTransform().equals(toTransform)) { // Return the first!
- return hop;
+ if (toTransform != null) {
+ for (PipelineHopMeta hop : hops) {
+ if (toTransform.equals(hop.getToTransform())) { // Return the first!
+ return hop;
+ }
}
}
return null;
diff --git a/engine/src/main/java/org/apache/hop/pipeline/PipelinePainter.java
b/engine/src/main/java/org/apache/hop/pipeline/PipelinePainter.java
index ebf66406c1..80dd852873 100644
--- a/engine/src/main/java/org/apache/hop/pipeline/PipelinePainter.java
+++ b/engine/src/main/java/org/apache/hop/pipeline/PipelinePainter.java
@@ -323,15 +323,23 @@ public class PipelinePainter extends
BasePainter<PipelineHopMeta, TransformMeta>
drawTransformPerformanceTable(transformMeta);
}
- // Display an icon on the indicated location signaling to the user that
the transform in
- // question does not accept input
+ // Display a red cross on the indicated location signaling to the user
that the transform in
+ // question does not accept input or is not a good candidate for a hop
(duplicate hop or loop)
//
if (noInputTransform != null) {
gc.setLineWidth(2);
gc.setForeground(EColor.RED);
Point n = noInputTransform.getLocation();
- gc.drawLine(n.x - 5, n.y - 5, n.x + iconSize + 10, n.y + iconSize + 10);
- gc.drawLine(n.x - 5, n.y + iconSize + 5, n.x + iconSize + 5, n.y - 5);
+ gc.drawLine(
+ round(offset.x + n.x - 1),
+ round(offset.y + n.y - 1),
+ round(offset.x + n.x + iconSize + 1),
+ round(offset.y + n.y + iconSize + 1));
+ gc.drawLine(
+ round(offset.x + n.x - 1),
+ round(offset.y + n.y + iconSize + 1),
+ round(offset.x + n.x + iconSize + 1),
+ round(offset.y + n.y - 1));
}
try {
diff --git a/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
b/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
index a8cbe208a9..de0404aabd 100644
--- a/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
+++ b/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
@@ -662,7 +662,7 @@ public class WorkflowMeta extends AbstractMeta
/**
* Adds the action.
*
- * @param action the je
+ * @param action the action meta to add
*/
public void addAction(ActionMeta action) {
workflowActions.add(action);
@@ -673,7 +673,7 @@ public class WorkflowMeta extends AbstractMeta
/**
* Adds the workflow hop.
*
- * @param hop the hi
+ * @param hop the workflow hop meta to add
*/
public void addWorkflowHop(WorkflowHopMeta hop) {
workflowHops.add(hop);
@@ -683,23 +683,23 @@ public class WorkflowMeta extends AbstractMeta
/**
* Adds the action.
*
- * @param p the p
- * @param action the si
+ * @param index index at which the specified action is to be inserted
+ * @param action the action meta to add
*/
- public void addAction(int p, ActionMeta action) {
- workflowActions.add(p, action);
+ public void addAction(int index, ActionMeta action) {
+ workflowActions.add(index, action);
changedActions = true;
}
/**
* Adds the workflow hop.
*
- * @param p the p
- * @param hop the hi
+ * @param index index at which the specified hop is to be inserted
+ * @param hop the workflow hop meta to add
*/
- public void addWorkflowHop(int p, WorkflowHopMeta hop) {
+ public void addWorkflowHop(int index, WorkflowHopMeta hop) {
try {
- workflowHops.add(p, hop);
+ workflowHops.add(index, hop);
} catch (IndexOutOfBoundsException e) {
workflowHops.add(hop);
}
@@ -709,10 +709,10 @@ public class WorkflowMeta extends AbstractMeta
/**
* Removes the action.
*
- * @param i the i
+ * @param index the index of the action to be removed
*/
- public void removeAction(int i) {
- ActionMeta deleted = workflowActions.remove(i);
+ public void removeAction(int index) {
+ ActionMeta deleted = workflowActions.remove(index);
if (deleted != null) {
// give transform a chance to cleanup
deleted.setParentWorkflowMeta(null);
@@ -791,8 +791,8 @@ public class WorkflowMeta extends AbstractMeta
/**
* Find workflow hop.
*
- * @param name the name
- * @return the workflow hop meta
+ * @param name the name of the hop to look for
+ * @return the workflow hop meta or null if nothing was found.
*/
public WorkflowHopMeta findWorkflowHop(String name) {
for (WorkflowHopMeta hop : workflowHops) {
@@ -806,18 +806,15 @@ public class WorkflowMeta extends AbstractMeta
}
/**
- * Find workflow hop from.
+ * Find the first workflow hop from.
*
- * @param action the action meta
- * @return the workflow hop meta
+ * @param action the action meta at the start of the hop.
+ * @return the first hop found or null if nothing was found.
*/
public WorkflowHopMeta findWorkflowHopFrom(ActionMeta action) {
if (action != null) {
for (WorkflowHopMeta hop : workflowHops) {
-
- // Return the first we find!
- //
- if (hop != null && (hop.getFromAction() != null) &&
hop.getFromAction().equals(action)) {
+ if (action.equals(hop.getFromAction())) {
return hop;
}
}
@@ -828,9 +825,9 @@ public class WorkflowMeta extends AbstractMeta
/**
* Find workflow hop.
*
- * @param from the from
- * @param to the to
- * @return the workflow hop meta
+ * @param from the action meta at the start of the hop
+ * @param to the to action meta at the end of the hop.
+ * @return the workflow hop meta or null if nothing was found.
*/
public WorkflowHopMeta findWorkflowHop(ActionMeta from, ActionMeta to) {
return findWorkflowHop(from, to, false);
@@ -839,15 +836,14 @@ public class WorkflowMeta extends AbstractMeta
/**
* Find workflow hop.
*
- * @param from the from
- * @param to the to
- * @param includeDisabled the include disabled
- * @return the workflow hop meta
+ * @param from the action meta at the start of the hop
+ * @param to the to action meta at the end of the hop.
+ * @param includeDisabled include disabled hop
+ * @return the workflow hop meta or null if nothing was found.
*/
public WorkflowHopMeta findWorkflowHop(ActionMeta from, ActionMeta to,
boolean includeDisabled) {
for (WorkflowHopMeta hop : workflowHops) {
if ((hop.isEnabled() || includeDisabled)
- && hop != null
&& hop.getFromAction() != null
&& hop.getToAction() != null
&& hop.getFromAction().equals(from)
@@ -859,16 +855,17 @@ public class WorkflowMeta extends AbstractMeta
}
/**
- * Find workflow hop to.
+ * Find the first workflow hop to.
*
- * @param actionMeta the action meta
- * @return the workflow hop meta
+ * @param action the to action meta at the end of the hop.
+ * @return the first workflow hop meta or null if nothing was found.
*/
- public WorkflowHopMeta findWorkflowHopTo(ActionMeta actionMeta) {
- for (WorkflowHopMeta hop : workflowHops) {
- if (hop != null && hop.getToAction() != null &&
hop.getToAction().equals(actionMeta)) {
- // Return the first!
- return hop;
+ public WorkflowHopMeta findWorkflowHopTo(ActionMeta action) {
+ if (action != null) {
+ for (WorkflowHopMeta hop : workflowHops) {
+ if (action.equals(hop.getToAction())) {
+ return hop;
+ }
}
}
return null;
diff --git a/engine/src/main/java/org/apache/hop/workflow/WorkflowPainter.java
b/engine/src/main/java/org/apache/hop/workflow/WorkflowPainter.java
index 60ea1d2977..3cfce6792d 100644
--- a/engine/src/main/java/org/apache/hop/workflow/WorkflowPainter.java
+++ b/engine/src/main/java/org/apache/hop/workflow/WorkflowPainter.java
@@ -194,23 +194,24 @@ public class WorkflowPainter extends
BasePainter<WorkflowHopMeta, ActionMeta> {
drawAction(actionMeta);
}
- // Display an icon on the indicated location signaling to the user that
the action in
- // question does not accept input
+ // Display a red cross on the indicated location signaling to the user
that the action in
+ // question does not accept input or is not a good candidate for a hop
(duplicate hop or
+ // workflow loop)
//
if (noInputAction != null) {
gc.setLineWidth(2);
gc.setForeground(EColor.RED);
Point n = noInputAction.getLocation();
gc.drawLine(
- round(offset.x + n.x - 5),
- round(offset.y + n.y - 5),
- round(offset.x + n.x + iconSize + 5),
- round(offset.y + n.y + iconSize + 5));
+ round(offset.x + n.x - 1),
+ round(offset.y + n.y - 1),
+ round(offset.x + n.x + iconSize + 1),
+ round(offset.y + n.y + iconSize + 1));
gc.drawLine(
- round(offset.x + n.x - 5),
- round(offset.y + n.y + iconSize + 5),
- round(offset.x + n.x + iconSize + 5),
- round(offset.y + n.y - 5));
+ round(offset.x + n.x - 1),
+ round(offset.y + n.y + iconSize + 1),
+ round(offset.x + n.x + iconSize + 1),
+ round(offset.y + n.y - 1));
}
try {
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 1372f23149..659afb1431 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
@@ -145,7 +145,6 @@ import org.apache.hop.ui.core.dialog.TransformFieldsDialog;
import org.apache.hop.ui.core.gui.GuiResource;
import org.apache.hop.ui.core.gui.GuiToolbarWidgets;
import org.apache.hop.ui.core.gui.HopNamespace;
-import org.apache.hop.ui.core.widget.OsHelper;
import org.apache.hop.ui.hopgui.CanvasFacade;
import org.apache.hop.ui.hopgui.CanvasListener;
import org.apache.hop.ui.hopgui.HopGui;
@@ -383,7 +382,7 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
private Point endHopLocation;
private boolean startErrorHopTransform;
- private TransformMeta noInputTransform;
+ private TransformMeta forbiddenTransform;
private TransformMeta endHopTransform;
@@ -735,26 +734,21 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
return;
}
- if (candidate != null && !OsHelper.isMac()) {
- // Avoid duplicate pop-up for hop handling as candidate is never
null? */
- addCandidateAsHop(event.x, event.y);
- }
-
currentTransform = (TransformMeta) areaOwner.getOwner();
- for (ITransformSelectionListener listener :
currentTransformListeners) {
- listener.onUpdateSelection(currentTransform);
- }
-
- // ALT-Click: edit error handling
- //
- if (event.button == 1 && alt &&
currentTransform.supportsErrorHandling()) {
+ if (startHopTransform != null) {
+ // If we click on the start hop transform or a forbidden
transform, then we don't have a
+ // candidate hop, but we need to ignore this click to not start a
drag operation.
+ if (candidate != null) {
+ addCandidateAsHop(event.x, event.y);
+ }
+ } else if (event.button == 1 && alt &&
currentTransform.supportsErrorHandling()) {
+ // ALT-Click: edit error handling
+ //
pipelineTransformDelegate.editTransformErrorHandling(pipelineMeta,
currentTransform);
return;
- } else if (event.button == 1 && startHopTransform != null &&
endHopTransform == null) {
- candidate = new PipelineHopMeta(startHopTransform,
currentTransform);
} else if (event.button == 2 || (event.button == 1 && shift)) {
- // SHIFT CLICK is start of drag to create a new hop
+ // SHIFT CLICK: start drawing a new hop
//
canvas.setData("mode", "hop");
startHopTransform = currentTransform;
@@ -763,6 +757,11 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
dragSelection = true;
selectedTransforms = pipelineMeta.getSelectedTransforms();
selectedTransform = currentTransform;
+
+ for (ITransformSelectionListener listener :
currentTransformListeners) {
+ listener.onUpdateSelection(currentTransform);
+ }
+
//
// When an icon is moved that is not selected, it gets
// selected too late.
@@ -792,8 +791,8 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
}
}
- // Layer 2: click on hop links between transforms
- if (!done) {
+ // Layer 2: click on hop links between transforms and not drawing a hop
+ if (!done && startHopTransform == null) {
// hop links between transforms are found searching by (x,y) coordinates.
PipelineHopMeta hop = findPipelineHop(real.x, real.y);
if (hop != null) {
@@ -818,8 +817,11 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
}
}
- // Layer 3: click on a note
- if (!done && areaOwner != null && areaOwner.getAreaType() ==
AreaOwner.AreaType.NOTE) {
+ // Layer 3: click on a note and not drawing a hop
+ if (!done
+ && startHopTransform == null
+ && areaOwner != null
+ && areaOwner.getAreaType() == AreaOwner.AreaType.NOTE) {
currentNotePad = (NotePadMeta) areaOwner.getOwner();
selectedNotes = pipelineMeta.getSelectedNotes();
selectedNote = currentNotePad;
@@ -844,11 +846,12 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
// Layer 4: Click on the background of the graph
if (!done) {
- // If we're dragging a candidate hop around and click on the background
it simply needs to
+ // If we're drawing a candidate hop and click on the background it
simply needs to
// go away.
//
if (startHopTransform != null) {
startHopTransform = null;
+ endHopLocation = null;
candidate = null;
lastClick = null;
avoidContextDialog = true;
@@ -890,6 +893,7 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
@Override
public void mouseUp(MouseEvent e) {
resize = null;
+ forbiddenTransform = null;
// canvas.setData("mode", null); does not work.
canvas.setData("mode", "null");
@@ -904,6 +908,7 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
if (viewPortNavigation || viewDrag) {
viewDrag = false;
+ viewDragStart = null;
viewPortNavigation = false;
viewPortStart = null;
return;
@@ -914,8 +919,6 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
updateErrorMetaForHop(selectedHop);
boolean singleClick = false;
mouseOverName = null;
- viewDrag = false;
- viewDragStart = null;
SingleClickType singleClickType = null;
TransformMeta singleClickTransform = null;
NotePadMeta singleClickNote = null;
@@ -971,10 +974,7 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
break;
case TRANSFORM_ICON:
if (startHopTransform != null) {
- // Mouse up while dragging around a hop candidate
- //
- currentTransform = (TransformMeta) areaOwner.getOwner();
- candidate = new PipelineHopMeta(startHopTransform,
currentTransform);
+ // Mouse up while drawing a hop candidate
addCandidateAsHop(e.x, e.y);
redraw();
return;
@@ -987,14 +987,10 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
&& selectedNotes == null) {
// This is available only in single click mode...
//
- startHopTransform = null;
- selectionRegion = null;
-
TransformMeta transformMeta = (TransformMeta)
areaOwner.getParent();
editTransform(transformMeta);
}
return;
-
default:
break;
}
@@ -1057,10 +1053,10 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
// OK, we moved the transform, did we move it across a hop?
// If so, ask to split the hop!
if (splitHop) {
- PipelineHopMeta hi =
+ PipelineHopMeta hop =
findPipelineHop(icon.x + iconSize / 2, icon.y + iconSize / 2,
selectedTransform);
- if (hi != null) {
- splitHop(hi);
+ if (hop != null) {
+ splitHop(hop);
}
splitHop = false;
}
@@ -1409,7 +1405,6 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
@Override
public void mouseMove(MouseEvent event) {
boolean shift = (event.stateMask & SWT.SHIFT) != 0;
- noInputTransform = null;
mouseMovedSinceClick = true;
boolean doRedraw = false;
@@ -1417,6 +1412,16 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
//
toolTip.setVisible(false);
+ // First, check for operations that have been started, such as move
selection, dragging the
+ // view, creating a hop or resizing a note.
+
+ // Drag the view around with middle button on the background?
+ //
+ if (viewDrag && lastClick != null) {
+ dragView(viewDragStart, new Point(event.x, event.y));
+ return;
+ }
+
// Check to see if we're navigating with the view port
//
if (viewPortNavigation) {
@@ -1563,53 +1568,66 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
doRedraw = true;
} else if ((startHopTransform != null && endHopTransform == null)
|| (endHopTransform != null && startHopTransform == null)) {
+
// Are we creating a new hop with the middle button or pressing SHIFT?
//
-
TransformMeta transformMeta = pipelineMeta.getTransform(real.x, real.y,
iconSize);
endHopLocation = new Point(real.x, real.y);
- if (transformMeta != null
- && ((startHopTransform != null &&
!startHopTransform.equals(transformMeta))
- || (endHopTransform != null &&
!endHopTransform.equals(transformMeta)))) {
+ if (transformMeta != null) {
ITransformIOMeta ioMeta =
transformMeta.getTransform().getTransformIOMeta();
- if (candidate == null) {
- // See if the transform accepts input. If not, we can't create a new
hop...
- //
+
+ // Checks if mouse over another transformn
+ if ((startHopTransform != null &&
!startHopTransform.equals(transformMeta))
+ || (endHopTransform != null &&
!endHopTransform.equals(transformMeta))) {
+
if (startHopTransform != null) {
- if (ioMeta.isInputAcceptor()) {
- candidate = new PipelineHopMeta(startHopTransform,
transformMeta);
- endHopLocation = null;
- } else {
- noInputTransform = transformMeta;
+
+ // Check if the transform accepts input. If not, we can't create a
new hop...
+ //
+ if (!ioMeta.isInputAcceptor()) {
+ forbiddenTransform = transformMeta;
toolTip.setText("This transform does not accept any input from
other transforms");
- showToolTip(new org.eclipse.swt.graphics.Point(real.x, real.y));
+ showToolTip(new org.eclipse.swt.graphics.Point(event.x,
event.y));
+ }
+ // Check if the hop already exists
+ else if (pipelineMeta.findPipelineHop(startHopTransform,
transformMeta, true) != null) {
+ forbiddenTransform = transformMeta;
+ toolTip.setText(BaseMessages.getString(PKG,
"HopGui.Dialog.HopExists.Message"));
+ showToolTip(new org.eclipse.swt.graphics.Point(event.x,
event.y));
+ }
+ // Check if the hop candidate creates a loop
+ else {
+ candidate = new PipelineHopMeta(startHopTransform,
transformMeta);
+ pipelineMeta.addPipelineHop(candidate);
+ boolean hasLoop = pipelineMeta.hasLoop(transformMeta);
+ pipelineMeta.removePipelineHop(candidate);
+
+ if (hasLoop) {
+ candidate = null;
+ forbiddenTransform = transformMeta;
+ toolTip.setText(
+ BaseMessages.getString(PKG,
"PipelineGraph.Dialog.HopCausesLoop.Message"));
+ showToolTip(new org.eclipse.swt.graphics.Point(event.x,
event.y));
+ }
}
} else if (endHopTransform != null) {
if (ioMeta.isOutputProducer()) {
candidate = new PipelineHopMeta(transformMeta, endHopTransform);
endHopLocation = null;
} else {
- noInputTransform = transformMeta;
+ forbiddenTransform = transformMeta;
toolTip.setText(
"This transform doesn't pass any output to other transforms.
(except perhaps for targeted output)");
- showToolTip(new org.eclipse.swt.graphics.Point(real.x, real.y));
+ showToolTip(new org.eclipse.swt.graphics.Point(event.x,
event.y));
}
}
}
} else {
- if (candidate != null) {
- candidate = null;
- doRedraw = true;
- }
+ candidate = null;
+ forbiddenTransform = null;
}
doRedraw = true;
- } else {
- // Drag the view around with middle button on the background?
- //
- if (viewDrag && lastClick != null) {
- dragView(viewDragStart, new Point(event.x, event.y));
- }
}
// Move around notes and transforms
@@ -1710,11 +1728,17 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
private void addCandidateAsHop(int mouseX, int mouseY) {
- boolean forward = startHopTransform != null;
+ if (candidate == null) {
+ return;
+ }
+ boolean forward = startHopTransform != null;
TransformMeta fromTransform = candidate.getFromTransform();
TransformMeta toTransform = candidate.getToTransform();
- if (fromTransform.equals(toTransform)) {
+
+ // A couple of sanity checks...
+ //
+ if (fromTransform == null || toTransform == null ||
fromTransform.equals(toTransform)) {
return; // Don't add
}
@@ -1815,7 +1839,6 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
return;
}
- candidate = null;
selectedTransforms = null;
startHopTransform = null;
endHopLocation = null;
@@ -1833,7 +1856,10 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
if (candidate == null) {
return;
}
- this.startHopTransform = null;
+
+ startHopTransform = null;
+ endHopLocation = null;
+
switch (stream.getStreamType()) {
case ERROR:
addErrorHop();
@@ -2102,7 +2128,7 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
public void clearSettings() {
selectedTransform = null;
- noInputTransform = null;
+ forbiddenTransform = null;
selectedNote = null;
selectedTransforms = null;
selectionRegion = null;
@@ -3435,7 +3461,7 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
pipelinePainter.setTransformLogMap(transformLogMap);
pipelinePainter.setStartHopTransform(startHopTransform);
pipelinePainter.setEndHopLocation(endHopLocation);
- pipelinePainter.setNoInputTransform(noInputTransform);
+ pipelinePainter.setNoInputTransform(forbiddenTransform);
pipelinePainter.setEndHopTransform(endHopTransform);
pipelinePainter.setCandidateHopType(candidateHopType);
pipelinePainter.setStartErrorHopTransform(startErrorHopTransform);
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 89d04f10bf..303e340d40 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
@@ -325,7 +325,7 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
private Point endHopLocation;
private ActionMeta endHopAction;
- private ActionMeta noInputAction;
+ private ActionMeta forbiddenAction;
private Point[] previousActionLocations;
private Point[] previousNoteLocations;
private ActionMeta currentAction;
@@ -584,9 +584,12 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
currentAction = (ActionMeta) areaOwner.getOwner();
- if (hopCandidate != null) {
- addCandidateAsHop();
-
+ if (startHopAction != null) {
+ // If we click on the start hop action or a forbidden action, then
we don't have a
+ // candidate hop, but we need to ignore this click to not start a
drag operation
+ if (hopCandidate != null) {
+ addCandidateAsHop();
+ }
} else if (event.button == 2 || (event.button == 1 && shift)) {
// SHIFT CLICK is start of drag to create a new hop
//
@@ -654,7 +657,7 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
}
// Layer 2: click on hop links between actions
- if (!done) {
+ if (!done && startHopAction == null) {
// Hop links between actions are found searching by (x,y) coordinates.
WorkflowHopMeta hop = findWorkflowHop(real.x, real.y);
if (hop != null) {
@@ -681,7 +684,10 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
}
// Layer 3: click on a note
- if (!done && areaOwner != null && areaOwner.getAreaType() ==
AreaOwner.AreaType.NOTE) {
+ if (!done
+ && startHopAction == null
+ && areaOwner != null
+ && areaOwner.getAreaType() == AreaOwner.AreaType.NOTE) {
currentNotePad = (NotePadMeta) areaOwner.getOwner();
selectedNotes = workflowMeta.getSelectedNotes();
selectedNote = currentNotePad;
@@ -719,6 +725,7 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
if (startHopAction != null) {
startHopAction = null;
hopCandidate = null;
+ endHopLocation = null;
lastClick = null;
redraw();
return;
@@ -758,6 +765,7 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
public void mouseUp(MouseEvent event) {
resize = null;
dragSelection = false;
+ forbiddenAction = null;
// canvas.setData("mode", null); does not work.
canvas.setData("mode", "null");
@@ -771,6 +779,7 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
if (viewPortNavigation || viewDrag) {
viewDrag = false;
+ viewDragStart = null;
viewPortNavigation = false;
viewPortStart = null;
return;
@@ -783,8 +792,6 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
ActionMeta singleClickAction = null;
NotePadMeta singleClickNote = null;
WorkflowHopMeta singleClickHop = null;
- viewDrag = false;
- viewDragStart = null;
mouseOverName = null;
if (iconOffset == null) {
@@ -832,8 +839,7 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
switch (areaOwner.getAreaType()) {
case ACTION_ICON:
if (startHopAction != null) {
- currentAction = (ActionMeta) areaOwner.getOwner();
- hopCandidate = new WorkflowHopMeta(startHopAction, currentAction);
+ // Mouse up while drawing a hop candidate
addCandidateAsHop();
redraw();
}
@@ -844,9 +850,6 @@ public class HopGuiWorkflowGraph extends HopGuiAbstractGraph
&& selectedActions == null
&& selectedNotes == null) {
// This is available only in single click mode...
- //
- startHopAction = null;
- selectionRegion = null;
ActionMeta actionMeta = (ActionMeta) areaOwner.getParent();
editAction(actionMeta);
return;
@@ -1153,13 +1156,22 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
@Override
public void mouseMove(MouseEvent event) {
boolean shift = (event.stateMask & SWT.SHIFT) != 0;
- noInputAction = null;
boolean doRedraw = false;
// disable the tooltip
//
hideToolTips();
+ // First, check for operations that have been started, such as move
selection, dragging the
+ // view, creating a hop or resizing a note.
+
+ // Drag the view around with middle button on the background?
+ //
+ if (viewDrag && lastClick != null) {
+ dragView(viewDragStart, new Point(event.x, event.y));
+ return;
+ }
+
// Check to see if we're navigating with the view port
//
if (viewPortNavigation) {
@@ -1173,6 +1185,12 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
//
lastMove = real;
+ // Resizing the current note
+ if (resize != null) {
+ resizeNote(selectedNote, real);
+ return;
+ }
+
if (iconOffset == null) {
iconOffset = new Point(0, 0);
}
@@ -1183,23 +1201,6 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
}
Point note = new Point(real.x - noteOffset.x, real.y - noteOffset.y);
- // First, check for operations that have been started, such as move
selection, dragging the
- // view, creating a hop or
- // resizing a note.
-
- // Drag the view around with middle button on the background?
- //
- if (viewDrag && lastClick != null) {
- dragView(viewDragStart, new Point(event.x, event.y));
- return;
- }
-
- // Resizing the current note
- if (resize != null) {
- resizeNote(selectedNote, real);
- return;
- }
-
// Moved over an area?
//
AreaOwner areaOwner = getVisibleAreaOwner(real.x, real.y);
@@ -1300,36 +1301,54 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
doRedraw = true;
} else if ((startHopAction != null && endHopAction == null)
|| (endHopAction != null && startHopAction == null)) {
+
// Are we creating a new hop with the middle button or pressing SHIFT?
//
-
ActionMeta actionMeta = workflowMeta.getAction(real.x, real.y, iconSize);
endHopLocation = new Point(real.x, real.y);
- if (actionMeta != null
- && ((startHopAction != null && !startHopAction.equals(actionMeta))
- || (endHopAction != null && !endHopAction.equals(actionMeta)))) {
- if (hopCandidate == null) {
- // See if the transform accepts input. If not, we can't create a new
hop...
- //
+ if (actionMeta != null) {
+
+ // Checks if mouse over another action
+ if ((startHopAction != null && !startHopAction.equals(actionMeta))
+ || (endHopAction != null && !endHopAction.equals(actionMeta))) {
+
if (startHopAction != null) {
- if (!actionMeta.isStart()) {
- hopCandidate = new WorkflowHopMeta(startHopAction, actionMeta);
- endHopLocation = null;
- } else {
- noInputAction = actionMeta;
- toolTip.setText("The start action can only be used at the start
of a Workflow");
+ // Check if the start action
+ if (actionMeta.isStart()) {
+ forbiddenAction = actionMeta;
+ toolTip.setText(
+ BaseMessages.getString(PKG,
"WorkflowGraph.Hop.CreateHopToStartAction.Tooltip"));
+ showToolTip(new org.eclipse.swt.graphics.Point(event.x,
event.y));
+ }
+ // Check if the hop already exists
+ else if (workflowMeta.findWorkflowHop(startHopAction, actionMeta,
true) != null) {
+ forbiddenAction = actionMeta;
+ toolTip.setText(
+ BaseMessages.getString(PKG,
"WorkflowGraph.Dialog.HopExists.Message"));
showToolTip(new org.eclipse.swt.graphics.Point(event.x,
event.y));
}
+ // Check if the hop candidate creates a loop
+ else {
+ hopCandidate = new WorkflowHopMeta(startHopAction, actionMeta);
+ workflowMeta.addWorkflowHop(hopCandidate);
+ boolean hasLoop = workflowMeta.hasLoop(actionMeta);
+ workflowMeta.removeWorkflowHop(hopCandidate);
+ if (hasLoop) {
+ hopCandidate = null;
+ forbiddenAction = actionMeta;
+ toolTip.setText(
+ BaseMessages.getString(PKG,
"WorkflowGraph.Dialog.HopCausesLoop.Message"));
+ showToolTip(new org.eclipse.swt.graphics.Point(event.x,
event.y));
+ }
+ }
} else if (endHopAction != null) {
hopCandidate = new WorkflowHopMeta(actionMeta, endHopAction);
endHopLocation = null;
}
}
} else {
- if (hopCandidate != null) {
- hopCandidate = null;
- doRedraw = true;
- }
+ hopCandidate = null;
+ forbiddenAction = null;
}
doRedraw = true;
@@ -1398,42 +1417,44 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
}
private void addCandidateAsHop() {
- if (hopCandidate != null) {
- // A couple of sanity checks...
- //
- if (hopCandidate.getFromAction() == null || hopCandidate.getToAction()
== null) {
- return;
- }
- if (hopCandidate.getFromAction().equals(hopCandidate.getToAction())) {
- return;
- }
+ if (hopCandidate == null) {
+ return;
+ }
- if (!hopCandidate.getFromAction().isEvaluation()
- && hopCandidate.getFromAction().isUnconditional()) {
- hopCandidate.setUnconditional();
- } else {
- hopCandidate.setConditional();
- int nr = workflowMeta.findNrNextActions(hopCandidate.getFromAction());
-
- // If there is one green link: make this one red! (or
- // vice-versa)
- if (nr == 1) {
- ActionMeta actionMeta =
workflowMeta.findNextAction(hopCandidate.getFromAction(), 0);
- WorkflowHopMeta other =
- workflowMeta.findWorkflowHop(hopCandidate.getFromAction(),
actionMeta);
- if (other != null) {
- hopCandidate.setEvaluation(!other.isEvaluation());
- }
+ // A couple of sanity checks...
+ //
+ if (hopCandidate.getFromAction() == null || hopCandidate.getToAction() ==
null) {
+ return;
+ }
+ if (hopCandidate.getFromAction().equals(hopCandidate.getToAction())) {
+ return;
+ }
+
+ if (!hopCandidate.getFromAction().isEvaluation()
+ && hopCandidate.getFromAction().isUnconditional()) {
+ hopCandidate.setUnconditional();
+ } else {
+ hopCandidate.setConditional();
+ int nr = workflowMeta.findNrNextActions(hopCandidate.getFromAction());
+
+ // If there is one green link: make this one red! (or
+ // vice-versa)
+ if (nr == 1) {
+ ActionMeta actionMeta =
workflowMeta.findNextAction(hopCandidate.getFromAction(), 0);
+ WorkflowHopMeta other =
+ workflowMeta.findWorkflowHop(hopCandidate.getFromAction(),
actionMeta);
+ if (other != null) {
+ hopCandidate.setEvaluation(!other.isEvaluation());
}
}
+ }
- // Stop drawing the hop candidate
- startHopAction = null;
+ // Stop drawing the hop candidate
+ startHopAction = null;
- workflowHopDelegate.newHop(workflowMeta, hopCandidate);
- clearSettings();
- }
+ workflowHopDelegate.newHop(workflowMeta, hopCandidate);
+ clearSettings();
}
public boolean checkIfHopAlreadyExists(WorkflowMeta workflowMeta,
WorkflowHopMeta newHop) {
@@ -2993,7 +3014,7 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
workflowPainter.setStartHopAction(startHopAction);
workflowPainter.setEndHopLocation(endHopLocation);
workflowPainter.setEndHopAction(endHopAction);
- workflowPainter.setNoInputAction(noInputAction);
+ workflowPainter.setNoInputAction(forbiddenAction);
if (workflow != null) {
workflowPainter.setActionResults(workflow.getActionResults());
} else {
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowHopDelegate.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowHopDelegate.java
index f67c3675fc..a24aa21e0f 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowHopDelegate.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/delegates/HopGuiWorkflowHopDelegate.java
@@ -29,7 +29,7 @@ import org.eclipse.swt.SWT;
public class HopGuiWorkflowHopDelegate {
- private static final Class<?> PKG = HopGui.class;
+ private static final Class<?> PKG = HopGuiWorkflowGraph.class;
private HopGui hopGui;
private HopGuiWorkflowGraph workflowGraph;
@@ -42,8 +42,8 @@ public class HopGuiWorkflowHopDelegate {
}
public void newHop(WorkflowMeta workflowMeta, ActionMeta fr, ActionMeta to) {
- WorkflowHopMeta hi = new WorkflowHopMeta(fr, to);
- newHop(workflowMeta, hi);
+ WorkflowHopMeta hop = new WorkflowHopMeta(fr, to);
+ newHop(workflowMeta, hop);
}
public void newHop(WorkflowMeta workflowMeta, WorkflowHopMeta hopMeta) {
@@ -78,8 +78,8 @@ public class HopGuiWorkflowHopDelegate {
MessageBox mb = new MessageBox(hopGui.getShell(), SWT.OK |
SWT.ICON_ERROR);
mb.setMessage(
BaseMessages.getString(
- PKG, "HopGui.Dialog.HopExists.Message")); // "This hop already
exists!"
- mb.setText(BaseMessages.getString(PKG,
"HopGui.Dialog.HopExists.Title")); // Error!
+ PKG, "WorkflowGraph.Dialog.HopExists.Message")); // "This hop
already exists!"
+ mb.setText(BaseMessages.getString(PKG,
"WorkflowGraph.Dialog.HopExists.Title")); // Error!
mb.open();
ok = false;
}
diff --git
a/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_en_US.properties
index 220e466963..e265a65009 100644
---
a/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_en_US.properties
@@ -119,8 +119,10 @@ WorkflowGraph.DeprecatedEntry.Tooltip.Title=Deprecated
WorkflowGraph.Dialog.EditDescription.Message=Edit description
WorkflowGraph.Dialog.EditDescription.Title=Description
WorkflowGraph.Dialog.EditNote.Title=Edit note
-WorkflowGraph.Dialog.HopCausesLoop.Message=This hop causes a loop. This is
not allowed.
+WorkflowGraph.Dialog.HopCausesLoop.Message=This hop causes a loop in the
workflow.
WorkflowGraph.Dialog.HopCausesLoop.Title=Loop\!
+WorkflowGraph.Dialog.HopExists.Message=This hop already exists\!
+WorkflowGraph.Dialog.HopExists.Title=Error
WorkflowGraph.Dialog.HopInfo=Hop information\:
WorkflowGraph.Dialog.HopInfo.Disable=Disabled
WorkflowGraph.Dialog.HopInfo.Enable=Enabled
@@ -137,6 +139,7 @@
WorkflowGraph.ExecutionResultsPanel.CloseButton.Tooltip=Close the execution resu
WorkflowGraph.ExecutionResultsPanel.MaxButton.Tooltip=Maximize the execution
results panel
WorkflowGraph.ExecutionResultsPanel.MinButton.Tooltip=Minimize the execution
results panel
WorkflowGraph.ExecutionResultsPanel.RotateButton.Tooltip=Rotate the execution
results panel
+WorkflowGraph.Hop.CreateHopToStartAction.Tooltip=The start action can only be
used at the start of a Workflow
WorkflowGraph.Hop.Tooltip.EvaluatingFalse=After the execution of {0}, the
result of the execution will be evaluated.{1}If the result is false (with
errors) this path will be taken.
WorkflowGraph.Hop.Tooltip.EvaluatingTrue=After the execution of {0}, the
result of the execution will be evaluated.{1}If the result is true (without
errors) this path will be taken.
WorkflowGraph.Hop.Tooltip.Parallel=Parallel execution.{1}All actions after {0}
will be executed in parallel.{1}That is ALL actions, not just the next
ones.{1}If you want to resume serial processing, put the parallel actions in a
sub-workflow.
diff --git
a/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_fr_FR.properties
b/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_fr_FR.properties
index c90c605992..d610f1aa60 100644
---
a/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_fr_FR.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/hopgui/file/workflow/messages/messages_fr_FR.properties
@@ -68,7 +68,7 @@ HopWorkflowFileType.New.Text=Nouveau workflow
WorkflowGraph.Dialog.EditDescription.Message=Editer la description
WorkflowGraph.Dialog.EditDescription.Title=Description
WorkflowGraph.Dialog.EditNote.Title=Editer la note
-WorkflowGraph.Dialog.HopCausesLoop.Message=Ce lien provoque une boucle. Ceci
n''est pas autoris\u00E9.
+WorkflowGraph.Dialog.HopCausesLoop.Message=Ce lien provoque une boucle dans le
workflow. Ceci n''est pas autoris\u00E9.
WorkflowGraph.Dialog.HopCausesLoop.Title=Boucle !
WorkflowGraph.Dialog.HopInfo.Disable=D\u00E9sactiv\u00E9
WorkflowGraph.Dialog.HopInfo.Enable=Activ\u00E9
diff --git
a/ui/src/main/resources/org/apache/hop/ui/hopgui/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/hopgui/messages/messages_en_US.properties
index 9c6f2700fc..c7a7081a4f 100644
---
a/ui/src/main/resources/org/apache/hop/ui/hopgui/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/hopgui/messages/messages_en_US.properties
@@ -39,7 +39,7 @@ HopGui.Dialog.HopExists.Message=This hop already exists\!
HopGui.Dialog.HopExists.Title=Error
HopGui.Dialog.OnlyUseStartOnce.Message=You can only use the start icon once in
a workflow.
HopGui.Dialog.OnlyUseStartOnce.Title=ERROR
-HopGui.Dialog.TransformnameExists.Message=This transform name already exists.
HopGui changed the transform name to [{0}]
+HopGui.Dialog.TransformnameExists.Message=This transform name already exists.
HopGui changed the transform name to [{0}]
HopGui.Dialog.TransformnameExists.Title=Note
HopGui.Dialog.UnableCreateNewTransform.Message=I was unable to create a new
transform
HopGui.Dialog.UnableCreateNewTransform.Title=Error creating transform