sketchucation logo sketchucation
    • Login
    πŸ€‘ SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    OnCancelEvent - Differentiating Undo from Redo

    Scheduled Pinned Locked Moved Developers' Forum
    6 Posts 2 Posters 421 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • fredo6F Offline
      fredo6
      last edited by fredo6

      In Sketchup Ruby API (at least up to version 8), the onCancel event uses the same flag with value 2 for both Undo and Redo. I presume this could be called a bug.

      Anyway, I needed to distinguish between the two operations and here is what I found

      1. At the time you receive an onCancel event, the Undo or Redo operations are not yet performed.

      2. So you can avoid the undo or redo by simply starting a fake operation with model_start_operation

      3. to know whether you have a redo or undo, the only way I found so far is to use the model observer

      You just need to add a few lines of code in your Tool class

      in the activate event

      Sketchup.active_model.add_observer self
      

      in the deactivate event

      Sketchup.active_model.remove_observer self
      

      You create two methods of your Tool class

      def onTransactionUndo(model) ; @undo_redo = ;undo ; end
      def onTransactionRedo(model) ; @undo_redo = ;redo ; end
      
      

      Finally, in the onCancel event

      
      def onCancel(flag, view)
         Sketchup.active_model.start_operation "fake"
         UI.start_timer(0) { execute_undo_redo }
      end
      
      

      When you are in your method execute_undo_redo, you have access to the variable @undo_redo which is either :undo or :redo.

      So you have some control on what you can do actually

      • either nothing (preventing the undo and/or redo) by invoking Sketchup.active_model.abort_operation
      • or an undo, by invoking Sketchup.undo
      • or a redo, by invoking Sketchup.send_action "editRedo:". CAUTION: this command actually reissue an onCancel event, so you have to protect infinite loop execution in some way. Sketchup.redo is another missing method in the SU API!

      Indeed, you may have to adapt depending on your context of operation, but these are principles

      If someone knows how to differentiate between undo and redo at the onCancel event firing, thanks to signal it.

      Fredo

      1 Reply Last reply Reply Quote 0
      • thomthomT Offline
        thomthom
        last edited by

        Instead of the timer - would you not just make the ModelObsever trigger that on the Undo/Redo events. Because that's what you are waiting for anyway. And making the ModelObsever trigger it avoid the risk of things getting out of sync for whatever reason.

        When you wrap the undo event in a start/commit operation - doesn't that interfere with the undo stack? Does it let the user undo backwards further?

        Does aborting the undo block the user from undoing completely?

        I'm a bit reluctant to interfering with the undo stack...

        Thomas Thomassen β€” SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund

        1 Reply Last reply Reply Quote 0
        • fredo6F Offline
          fredo6
          last edited by

          Tom,

          Overall, my post was more to ask if someone had found a way to find out about Undo or Redo.

          What I describe is cumbersome, and precisely by putting it in writing, I realize that this may lead to undesirable side effects (even if I found none so far), in particular if the SU Google team had the good idea to fix their API.

          To answer your question

          1) observer: the issue is that the observer methods onTransactionUndo and onTransactionRedo are fired several times (3 or 4, maybe more). So you cannot do any execution here, just noting if this is Undo or redo. In addition, I always take the principle not to perform changes within any observer methods, due to the rather unpredictable implemnetation that was done in the SU API for all observers (and changes from one version to the next one).

          1. The method of starting a fake transaction works fine to prevent Undo and Redo. My problems was actually that I wanted to prevent the Undo, not the Redo.

          2. Yes, you are right that scripts should not interfer with the undo stack in a preemptive way. My intention was simply to signal it via a confirmation dialog box before executing it.

          Anyway, all this gave me the opportunity to explore a little bit of the Undo, redo and onCancel behaviors. So at least I know how it works.

          Fredo

          1 Reply Last reply Reply Quote 0
          • thomthomT Offline
            thomthom
            last edited by

            I have been working with the undo/redo stack myself for BezierSurface which I'm currentlty working on.

            I also found that the tool event triggered before the undo/redo actually happened.

            I also figured that I should never make model changes in response to the undo/stack - as it's mess it up. But your idea of being able to cancel an event is interesting. Making users confirm it could be useful.

            However - I have not observed that the Undo/Redo event - for the ModelObserver or Tool triggers more than once. Sounds like you might have multiple observers attached...

            Thomas Thomassen β€” SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund

            1 Reply Last reply Reply Quote 0
            • fredo6F Offline
              fredo6
              last edited by

              @thomthom said:

              However - I have not observed that the Undo/Redo event - for the ModelObserver or Tool triggers more than once. Sounds like you might have multiple observers attached...

              Tom,

              You are right again.
              I found that you have to remove the observer (in the deactivate). Otherwise, in new instances of the Tool class, you will get the observer notifications of the ones previously created!

              I think I made my way now. My objective was simply to manage the history of modifications via the Sketchup standard undo and redo, while keeping some control of what is going on.

              Fredo

              1 Reply Last reply Reply Quote 0
              • thomthomT Offline
                thomthom
                last edited by

                @unknownuser said:

                You are right again.
                I found that you have to remove the observer (in the deactivate). Otherwise, in new instances of the Tool class, you will get the observer notifications of the ones previously created!

                I've begun to make my observers into Singletons. So I can use a factory method to get the singleton instance at any time when I need to add / remove the observer.

                Thomas Thomassen β€” SketchUp Monkey & Coding addict
                List of my plugins and link to the CookieWare fund

                1 Reply Last reply Reply Quote 0
                • 1 / 1
                • First post
                  Last post
                Buy SketchPlus
                Buy SUbD
                Buy WrapR
                Buy eBook
                Buy Modelur
                Buy Vertex Tools
                Buy SketchCuisine
                Buy FormFonts

                Advertisement