Reactor that detects when you will close a drawing, but then cancelled

Reactor that detects when you will close a drawing, but then cancelled

wai1954
Advocate Advocate
859 Views
5 Replies
Message 1 of 6

Reactor that detects when you will close a drawing, but then cancelled

wai1954
Advocate
Advocate

G'day,

 

I have a reactor that detects when you are about to close AutoCAD which then updates some information. It works well, however when the file are modified so you get an alert with the option to cancel the close and you select it, only the information gets updated when you are effectively canceling the close.

 

The reactor is a command reactor and it has to use the command will begin option.

 

Is it possible to somehow nest the two reactors so that the comandCancelled function can be triggered after the command will begin one?

 

Thanks.

 

This is part of the reactor code

 

  (if (not wai:acad_close)
    (progn
      (setq wai:acad_close (vlr-command-reactor nil '((:vlr-commandWillStart . wai:acadclose))))
    )
  )

 

This is wai:acadclose does

 

  (defun wai:acadclose (calling_reactor command_list)
    (if (member (nth 0 command_list) (list "CLOSE"))

      (if (member "doslib20x64.arx" (arx))
        (progn
          (dos_capslock)
        )
      )

    )

  )

 

The example is trivial, but I use it to update a whole lot of information including this. How do I detect that the command has been cancelled and this does not need to be done?

 

I tried to use :vlr-commandCancelled but the :vlrcommandWillStart has already been handled control so is ignored.

 

Can the reactors be nested?

 

Thanks.

wai1954 (Ian A. White)
0 Likes
860 Views
5 Replies
Replies (5)
Message 2 of 6

dbroad
Mentor
Mentor

Have you read these reactor guidelines?

 

You cannot or should not use a reactor to cancel a pending command or to do interactive input.  You cannot depend on the order of reactor events.  Events themselves are not nested and you should be very careful in a reactor callback not to trigger other events, especially those that would lead to an infinite loop.  It is possible to remove an event during a callback and then add it back in at the end of the callback.  Using (dos_capslock t) does nothing useful in a close reactor IMO.

 

You can have the same callback function process two different events but I'm not sure that is wise.  Suggested edit.

 

(setq wai:acad_close 
  (vlr-command-reactor 
      nil '((:vlr-commandWillStart . wai:acadclose)
            (:vlr-commandcancelled . wai:acadclose_cancel)

)))

Instead of using the member function just use the equal function or = function.  Use the member function if the same callback can be used for more that one command.

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 3 of 6

wai1954
Advocate
Advocate

Thanks.

 

The (dos_capslock) is only one part of a routine that does a whole lot of things to a drawing and the system for things like document management, document control, time recording, etc.. The reason I used it is that it is a good way of testing to see if something like a close is successful as if the command completes, then you lose the feedback, so even putting a debug string into indicate where you are will be lost. The caps lock toggles the indicator LED and so is a way of letting you know where you are 🙂

 

Ok, after many hours, it comes down to a standard dialog (as opposed to a DCL dialog) and how to detect it closing/cancelling/failing.

 

If you have a drawing that has been modified and you close the editor, a standard dialog is shown. The problem is that no matter what you do, a reactor monitoring a command will ALWAYS report back as the command has ended, even if it fails or is cancelled. As far as the reactor is concerned, the command has always ended although the end state is different.

 

With a DCL type dialog, you have DIASTAT that monitors how the DCL dialog has been retired (0 for cancelled and 1 for OK). From the hours spent on this, there does not appear to be a way of detecting how a standard dialog is retired. The only other way I can think of to do this is to somehow check if the editor is still open and the drawing has not been closed, and the trick is finding a way to achieve that.

 

Is there a way of detecting how a standard dialog has closed? I do not want to go through redefining the close commands as operators have ingenious ways of bypassing things and then there are issues with trying to stitch management systems back together, particularly with automated time billing.

 

It's giving the brain exercise, but playing havoc with sleep patterns 🙂

wai1954 (Ian A. White)
0 Likes
Message 4 of 6

dbroad
Mentor
Mentor

A few suggestions:

1) Never use AutoCAD to keep track of your time.  It won't work well. Use a spreadsheet and check-in and out of projects.  It does date math and can perform billing automatically.

2) Don't use the caps lock for testing reactors.  Use the built-in diagnostic facilities like vlr-trace-reactionas illustrated below.  Use the trace window to discover what is going on.  When AutoCAD is in MDI mode, closing a drawing does not close the application.  You still have access to the vlide trace window.

3) Use more than the command reactors to test the operation around the close operations.

4) Interactive operations cannot be managed from reactor callbacks.

 

//sample code to test reactions
(vlr-editor-reactor  nil '((:vlr-beginclose . vlr-trace-reaction)
			   (:vlr-commandWillStart . vlr-trace-reaction)
			   (:vlr-commandEnded . vlr-trace-reaction)
			   (:vlr-commandCancelled . vlr-trace-reaction)
			   (:vlr-beginSave . vlr-trace-reaction)
			   (:vlr-saveComplete . vlr-trace-reaction)
			   (:vlr-commandFailed . vlr-trace-reaction)
			   ))

 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 5 of 6

dgorsman
Consultant
Consultant

And, of course, LISP can only run in the active document so trying to monitor whether a document has closed (at which point the LISP *must* terminate) or not is asking for trouble.

 

Once things get this complicated its best to leave LISP and move to dotNET.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


0 Likes
Message 6 of 6

wai1954
Advocate
Advocate

Thanks.

 

No, I do not use AutoCAD itself to keep track of time, but get it to feed the current time to a spreadheet.

 

The reason I used caps lock was when I picked close AutoCAD (the QUIT or EXIT command), this closed everything down and there is no way to find out what the reactor did as AutoCAD had shut down. If AutoCAD did close, there was no way of knowing if things had worked properly or not.

 

The reactor was never intended to be interactive. The only reason I ended up with the option to cancel was because I had two (or more) drawings open and the currently inactive ones had been used to get elements from. When I saved the active one and then went to close AutoCAD. AutoCAD detected that one or more of other the drawings (as it cycled through them) was considered modified and so asked if I wanted to keep the changes.

 

I have looked at command, editor, dwg, docmanager (there may be a few others as well) reactors.

 

Thanks, I will look into the vlr-trace-reaction.

wai1954 (Ian A. White)
0 Likes