Undo/Redo with GoStroke


#1

Hi.

My custom object consists of several GoShapes.

  1. Move the object and record the transaction.
  2. Move the object without transaction recording.
  3. After Undoing, GoStroke does not appear in the expected location.

What is the problem?

※ In my actual project, some custom objects are automatically aligned to the right as the view size changes
The automatic alignment behavior should not be recorded in transactions.

Here is the test source code.

s

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Northwoods.Go;
using System.Threading;

namespace GoStrokeTest
{
public partial class Form1 : Form
{
private GoView view;

    public Form1()
    {
        this.InitializeComponent();

        this.Init();
    }

    private void Init()
    {
        this.view = new GoView() { Dock = DockStyle.Fill };

        this.Controls.Add(this.view);

        this.view.Document.UndoManager = new GoUndoManager();
        this.view.Document.UndoManager.ChecksTransactionLevel = true;

        var button = new GoButton()
        {
            Text = "Test",
            Location = new PointF(10, 150),
        };

        this.view.Document.Add(button);

        var text = new GoText()
        {
            Text = "Ready",
            Location = new PointF(50, 150),
            FontSize = 14,
        };

        this.view.Document.Add(text);

        button.Action += (s, e) =>
        {
            this.view.StartTransaction();

            var tg = new TestGroup("Test");
            this.view.Document.Add(tg);

            this.view.FinishTransaction("Add");

            text.Text = "Add(Record)";

            Application.DoEvents();
            Thread.Sleep(2000);

            this.view.StartTransaction();

            tg.Location = new PointF(100, 0);

            this.view.FinishTransaction("Move");

            text.Text = "Move(Record)";

            Application.DoEvents();
            Thread.Sleep(2000);

            tg.Location = new PointF(200, 0);

            text.Text = "Move(Not Record)";

            Application.DoEvents();
            Thread.Sleep(2000);

            this.view.Undo();

            text.Text = "Undo Move";
        };
    }

    public class TestGroup : GoGroup
    {
        public TestGroup(string text)
        {
            this.Resizable = false;
            this.PickableBackground = true;

            var t = new GoText() { Selectable = false, Text = text, };
            this.Add(t);

            var e = new GoEllipse()
            {
                Selectable = false,
                BrushColor = Color.Purple,
                Location = new PointF(50, 0),
                Size = new SizeF(50, 50),
            };
            this.Add(e);

            var r = new GoRectangle()
            {
                Selectable = false,
                BrushColor = Color.IndianRed,
                Location = new PointF(0, 50),
                Size = new SizeF(50, 50),
            };
            this.Add(r);

            var s1 = new GoStroke() { Selectable = true };
            s1.AddPoint(70, 60);
            s1.AddPoint(90, 90);
            this.Add(s1);

            var s2 = new GoStroke() { Selectable = true };
            s2.AddPoint(90, 60);
            s2.AddPoint(70, 90);
            this.Add(s2);
        }
    }
}

}


#2

Try adding

  bool oldskips = this.view.Document.SkipsUndoManager;
  this.view.Document.SkipsUndoManager = true;
         your code
  this.view.Document.SkipsUndoManager = oldskips;

around the non-undoable changes.


#3

Thanks! Jake.

I’ve already tried SkipsUndoManager, but it did not work.

var oldskips = this.view.Document.SkipsUndoManager;
this.view.Document.SkipsUndoManager = true;

tg.Location = new PointF(200, 0);

this.view.Document.SkipsUndoManager = oldskips;

The point is after undoing,
Of the children of TestGroup, only the GoStroke is different from the initial location.
(GoText, GoEllipse, GoRectangle ← ok)

Please run the code and take a look at it again.
Sorry for my bad english.


#4

You’re right… on further examination, that doesn’t work on GoStroke. Capturing some moves in transactions on GoStroke and not others isn’t going to behave the same as other objects that are defined by their Bounds. The same is true for GoDrawing…

Maybe there is another solution. Can you tell me more about the goal behind this?


#5

Hi Jake.

I thought this problem is somekind of bug.
But it does not seem to be a bug.

Current situation

  1. Empty diagram

  2. Add some object.
    Depending on the object type, they are arranged on the right side of the diagram.

  3. Change the view size.
    Depending on the view size change, certain objects can be aligned right side.
    ※ Object location changes due to alignment should not be treated as transactions(not diagram edit).

  4. Perform Undo, Redo, …
    GoStroke is missing.

thank you for your help.

and…
Can GoLayout be used to solve this problem?


#6

In this case, are you wrapping all changes in StartTransaction, FinishTransaction?

How is line with INV S R constructed? It sounds like it isn’t a GoLabeledLink.

In state 4… if you hide / show the whole window, do the missing lines come back?

This is a ladder diagram, right?


#7

In this case, are you wrapping all changes in StartTransaction, FinishTransaction?
→ Yes. But state 3 changes not recorded.

How is line with INV S R constructed? It sounds like it isn’t a GoLabeledLink.
→ All missing parts is GoStroke.
sss
Only the red line is GoLink.

In state 4… if you hide / show the whole window, do the missing lines come back?
→ No.

This is a ladder diagram, right?
→ Yes


#8

ok… so the [ INV ], ( S ) and ( R ) are all separate nodes? and the red lines are separate GoLinks? and you have an invisible node to the left of the INV?

The [ ] and () are GoStrokes too? They seem to be disappearing too. I’d make them part of the node (using a Horizontal GoListGroup to align them).

and I’d make that vertical GoStrokes GoLinks too… either a separate one, or more likely a single GoLink that runs from the 0000 link to the [ INV ] node. Either hide another node in the 0000 link or use a Fishbone sample logic to do link to link.

Is this a new app, or an older one you’ve just discovered this Undo issue? A big fix may be more than you want to do in a legacy app.