How to implement FlipHorizontal and FlipVertical dynamically?

How to implement FlipHorizontal and FlipVertical dynamically?
We want to implement FlipHorizontal & FlipVertical of image of nodes.
How to implement dynamically change flip value?
I am checking GoJS Pictures -- Northwoods Software.
This is static.
We want it dynamically.

Just set or bind the Picture | GoJS API property.

As with any other GraphObject property, simply setting it gets you the visual results that you want. But having a TwoWay Binding on that property means that that setting will be saved in the model. Alternatively, use a OneWay Binding and call Model.set to change the model state.

Can we perform flip on

$(go.Panel, “Vertical”, {
name: “img”
}, new go.Binding(“angle”, “angle”).makeTwoWay(),

We want to implement flip on go.Panel.

When we call

$(go.Panel, “Vertical”, {
name: “img”,
flip: go.GraphObject.None,
}, new go.Binding(“angle”, “angle”).makeTwoWay(),new go.Binding(“flip”),

We are getting error “Error: Trying to set undefined property “flip” on object: Panel([object Object])#695”.

We did not implement flip on GraphObject partly because people normally do not want their text to be flipped. And they really wanted to rearrange the contents of their panels in non-systematic ways. So even if you don’t have any text in your panel and really do want to flip it, that’s why we didn’t go to the trouble to implement that property on GraphObject.

So you will need to implement the functionality yourself, rather than “flipping a switch”.

We have image & ports around it.
We want to flip image & ports all together.
Also we want to slip value in DB & show it as it after flip.

Well, you know how to flip a Picture. How are the ports defined and arranged? Can you provide an outline of that panel template?

I know how to flip a Picture.
Ports are dynamically generated.

Sample Code

var node = (go.Node, "Auto", new go.Binding("location", "pos", go.Point.parse), { rotatable: true, rotateObjectName: "img", // rotate the Shape, not the Node locationSpot: go.Spot.Center, locationObjectName: "img", rotateAdornmentTemplate: // specify appearance of rotation handle (go.Adornment, {
locationSpot: go.Spot.Center,
background: “transparent”
},
$(go.Shape, “BpmnActivityLoop”, {
width: 12,
height: 12,
stroke: “dodgerblue”,
strokeWidth: 2
})),
selectionObjectName: “SHAPE”
},

            {
                toolTip: myToolTips
            },
            nodeStyle(), {
                width: 90
            },
            $(go.Shape, "Rectangle", {
                fill: background,
                stroke: null,
                spot1: go.Spot.TopLeft,
                spot2: go.Spot.BottomRight,
                angle: 90
            }, new go.Binding("stroke"), new go.Binding("fill")),
            $(go.Panel, "Vertical",
                $(go.TextBlock, "Center", typename, {
                    row: 2,
                    font: "9pt sans-serif",
                    wrap: go.TextBlock.WrapFit,
                    textAlign: "center",
                    width: 40,
                    margin: 5,
                    editable: true,
                    name: "LABEL"
                }, new go.Binding("text")),

                $(go.Panel, "Vertical", {
                        name: "img"
                    }, new go.Binding("angle", "angle").makeTwoWay(),
                    $(go.Panel, "Table", {
                            width: panel_width
                        },
                        TL,
                        T,
                        TR
                    ),

                    $(go.Panel, "Table", {
                            width: 60
                        },
                        L,
                        $(go.Panel, "TableColumn", {
                                column: 1,
                                row: 0,
                                toSpot: go.Spot.Center,
                                alignment: go.Spot.Center
                            },
                            $(go.Panel, "Position", {
                                    column: 1,
                                    row: 0,
                                    toSpot: go.Spot.Center,
                                    alignment: go.Spot.Center
                                },
                                $(go.Picture, {
                                    name: "actualimg",
                                    source: icon,
                                    flip: ''
                                }),

                                IN1,
                                IN2,
                                IN3,
                                OUT1,
                                OUT2,
                                OUT3,
                            ),
                        ),
                        R
                    ),

                    $(go.Panel, "Table", {
                            width: 60
                        },
                        BL,
                        B,
                        BR,
                    )
                ),

It might be best to define separate templates for each of the permitted “flip” states.

How to do that .

Can you give an example using

```
var node = $(go.Node, "Auto",
		new go.Binding("location", "pos", go.Point.parse), {
			rotatable: true,
			rotateObjectName: "img", // rotate the Shape, not the Node
			locationSpot: go.Spot.Center,
			locationObjectName: "img",
			rotateAdornmentTemplate: // specify appearance of rotation handle
				$(go.Adornment, {
						locationSpot: go.Spot.Center,
						background: "transparent"
					},
					$(go.Shape, "BpmnActivityLoop", {
						width: 12,
						height: 12,
						stroke: "dodgerblue",
						strokeWidth: 2
					})),
			selectionObjectName: "SHAPE"
		},

		{
			toolTip: myToolTips
		},
		nodeStyle(), {
			width: 90
		},
		$(go.Shape, "Rectangle", {
			fill: background,
			stroke: null,
			spot1: go.Spot.TopLeft,
			spot2: go.Spot.BottomRight,
			angle: 90
		}, new go.Binding("stroke"), new go.Binding("fill")),
		$(go.Panel, "Vertical",
			$(go.TextBlock, "Center", typename, {
				row: 2,
				font: "9pt sans-serif",
				wrap: go.TextBlock.WrapFit,
				textAlign: "center",
				width: 40,
				margin: 5,
				editable: true,
				name: "LABEL"
			}, new go.Binding("text")),

			$(go.Panel, "Vertical", {
					name: "img"
				}, new go.Binding("angle", "angle").makeTwoWay(),
				$(go.Panel, "Table", {
						width: panel_width
					},
					TL,
					T,
					TR
				),

				$(go.Panel, "Table", {
						width: 60
					},
					L,
					$(go.Panel, "TableColumn", {
							column: 1,
							row: 0,
							toSpot: go.Spot.Center,
							alignment: go.Spot.Center
						},
						$(go.Panel, "Position", {
								column: 1,
								row: 0,
								toSpot: go.Spot.Center,
								alignment: go.Spot.Center
							},
							$(go.Picture, {
								name: "actualimg",
								source: icon,
								flip: ''
							}),

							IN1,
							IN2,
							IN3,
							OUT1,
							OUT2,
							OUT3,
						),
					),
					R
				),

				$(go.Panel, "Table", {
						width: 60
					},
					BL,
					B,
					BR,
				)
			),
```

Define separate templates for each flip state. Then “flipping” is just a matter of changing the category appropriately.

Not getting.
Can you give an example?

<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2019 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="go.js"></script>
<script id="code">
  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          {
            "undoManager.isEnabled": true
          });

    function flipCat(cat, dir) {
      switch (cat) {
        case "FH":
          switch (dir) {
            case "H": return "";
            case "V": return "FB";
            default: return "FH";
          }
        case "FV":
          switch (dir) {
            case "H": return "FB";
            case "V": return "";
            default: return "FV";
          }
        case "FB":
          switch (dir) {
            case "H": return "FV";
            case "V": return "FH";
            default: return "FB";
          }
        default:
          switch (dir) {
            case "H": return "FH";
            case "V": return "FV";
            default: return "";
          }
      }
    }

    function flip(node, dir) {
      node.diagram.commit(function(d) {
        node.category = flipCat(node.category, dir);
      }, "flip " + dir);
    }

    function defineBody() {
      return [
        { locationObjectName: "BODY", locationSpot: go.Spot.Center, selectionObjectName: "BODY" },
        $(go.Panel, "Auto",
          { name: "BODY" },
          $(go.Shape,
            { fill: "white", portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer" },
            new go.Binding("fill", "color")),
          $(go.TextBlock,
            { margin: 8, editable: true },
            new go.Binding("text").makeTwoWay())
        ),
        {
          contextMenu:
            $("ContextMenu",
              $("ContextMenuButton",
                $(go.TextBlock, "Flip Horizontally"),
                { click: function(e, button) { flip(button.part.adornedPart, "H"); }}
              ),
              $("ContextMenuButton",
                $(go.TextBlock, "Flip Vertically"),
                { click: function(e, button) { flip(button.part.adornedPart, "V"); }}
              )
            )
        }
      ];
    }

    myDiagram.nodeTemplate =
      $(go.Node, "Spot",
        defineBody(),
        $(go.Shape, "Triangle",
          { alignment: go.Spot.TopRight, width: 10, height: 10, fill: "yellow" }),
        $(go.TextBlock, "F",
          { alignment: new go.Spot(0.25, 1), alignmentFocus: go.Spot.Top, stroke: "green" })
      );

    myDiagram.nodeTemplateMap.add("FH",
      $(go.Node, "Spot",
        defineBody(),
        $(go.Shape, "Triangle",
          { alignment: go.Spot.TopLeft, width: 10, height: 10, fill: "yellow" }),
        $(go.TextBlock, "F",
          { alignment: new go.Spot(0.75, 1), alignmentFocus: go.Spot.Top, stroke: "green", flip: go.GraphObject.FlipHorizontal })
      ));

    myDiagram.nodeTemplateMap.add("FV",
      $(go.Node, "Spot",
        defineBody(),
        $(go.Shape, "Triangle",
          { alignment: go.Spot.BottomRight, width: 10, height: 10, fill: "yellow", angle: 180 }),
        $(go.TextBlock, "F",
          { alignment: new go.Spot(0.25, 0), alignmentFocus: go.Spot.Bottom, stroke: "green", flip: go.GraphObject.FlipVertical })
      ));

    myDiagram.nodeTemplateMap.add("FB",
      $(go.Node, "Spot",
        defineBody(),
        $(go.Shape, "Triangle",
          { alignment: go.Spot.BottomLeft, width: 10, height: 10, fill: "yellow", angle: 180 }),
        $(go.TextBlock, "F",
          { alignment: new go.Spot(0.75, 0), alignmentFocus: go.Spot.Bottom, stroke: "green", angle: 180 })
      ));

    myDiagram.model = new go.GraphLinksModel(
    [
      { key: 1, text: "Normal\n(unflipped)", color: "lightblue", category: "" },
      { key: 2, text: "Flipped\nHorizontal", color: "orange", category: "FH" },
      { key: 3, text: "Flipped\nVertical", color: "lightgreen", category: "FV" },
      { key: 4, text: "Flipped\nBoth", color: "pink", category: "FB" }
    ],
    [
      { from: 1, to: 2 },
      { from: 1, to: 3 },
      { from: 3, to: 4 },
      { from: 4, to: 1 }
    ]);
  }
</script>
</head>
<body onload="init()">
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
</body>
</html>