Author Topic: vlr-erased - start before cancellation  (Read 10508 times)

0 Members and 1 Guest are viewing this topic.

Lupo76

  • Bull Frog
  • Posts: 343
vlr-erased - start before cancellation
« on: February 08, 2012, 08:03:55 AM »
Hello everyone,
is the first time you use the reactors and I have a problem.
I wrote the following code that starts when I edit a line containing the XData:
 
(setq lineReactor   
(vlr-object-reactor (list vlaent) "TEST"
   '((:vlr-modified . modificaT)
   (:vlr-erased . cancellaT)  ) )
)
 
then the following function:
 
(defun cancellaT (notifier-object reactor-object parameter-list / )
   (setq ogg (vlax-vla-object->ename notifier-object))
   (if (= ogg nil)(alert "nil")) ;*******probably the object has already been deleted and then the rest of the code can not work!
   (setq id (ReadXdata ogg "TESTXDATA" "ID"))
)
 
Can you help?

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-erased - start before cancellation
« Reply #1 on: February 08, 2012, 08:23:18 AM »
Don't think ALERT is allowed in a reactor.
Try (princ "\nnil value)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: vlr-erased - start before cancellation
« Reply #2 on: February 08, 2012, 09:01:27 AM »
Don't think ALERT is allowed in a reactor.
Try (princ "\nnil value)
I swear it has worked for me in the past. :?
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-erased - start before cancellation
« Reply #3 on: February 08, 2012, 09:15:56 AM »
I was just guessing. Didn't feel like testing it.  :-(
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: vlr-erased - start before cancellation
« Reply #4 on: February 08, 2012, 09:22:55 AM »
I was just guessing. Didn't feel like testing it.  :-(
I figured as much, just wanted to share my experience... or at least try and remember it. :lol:
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

Lupo76

  • Bull Frog
  • Posts: 343
Re: vlr-erased - start before cancellation
« Reply #5 on: February 08, 2012, 09:39:35 AM »
Don't think ALERT is allowed in a reactor.
Try (princ "\nnil value)

The problem is not "alert".
The real problem is that ogg=nil so I can not get the xdata stored in it before deleting it.

Let's take an example:
The object that I have to cancel, is a block with attributes
The reactor should behave in this way:
1. The user starts the command "erase", select the object and hit return
2. The reactor part, reads the value of an attribute of the selected block, and performs other operations with this
3. The object is removed permanently.

How can I do?
Do you have any advice?

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: vlr-erased - start before cancellation
« Reply #6 on: February 08, 2012, 09:44:01 AM »
The :vlr-erased Event will fire after the object is erased, hence the vlax-vla-object->ename will return nil when passed a VLA Object that is erased.

Maybe use a Command Reactor instead, triggered by the :vlr-commandwillstart Event, and test for the Erase command in the callback function. If the Erase command has been used, store the xData for the object.

Then, have another callback function triggered by the :vlr-commandended Event; again, testing for the Erase command and also for the data collected in the :vlr-commandwillstart callback function.


Lupo76

  • Bull Frog
  • Posts: 343
Re: vlr-erased - start before cancellation
« Reply #7 on: February 08, 2012, 10:57:24 AM »
Thank you!
finally a serious answer.
it is from this morning that I surf and I write on various forums.

Unfortunately I still have not understand how to solve the problem.
Surely it is because of my low knowledge of reactors: oops:

Thanks to your information and taken some indication on the internet I wrote the following code.
It does not quite understand how I can intercept the objects that the user decides to select to manipulate them before deleting them.
Can you give me some advice if possible with a little 'code? I hope not to ask too: oops:


(setq hyp-rctCmds (vlr-command-reactor nil '((:vlr-commandCancelled . hyp-cmdAbort)
        (:vlr-commandEnded . AnnullaCmd)
        (:vlr-commandCancelled . AnnullaCmd)
        (:vlr-commandWillStart . StartCmd)
      )
    )
)
 

(defun AnnullaCmd (param1 param2)
  (if (= (car param2) "ERASE")
    (progn
      (alert "The End")
    )
  )
)
 
 
(defun StartCmd (param1 param2 / currentlayer)
    (if (= (car param2) "ERASE")
      (progn
        (alert "Erase Started")
        ;Adesso come faccio ad intercettare gli oggetti che l'utente desidera cancellare?
      )
    )
)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-erased - start before cancellation
« Reply #8 on: February 08, 2012, 02:17:55 PM »
What are you trying to do to the objects before the erase?

Code - Auto/Visual Lisp: [Select]
  1. (defun C:CmdOn () (Vlr_Cmd t))
  2.  
  3. (defun C:CmdOff () (Vlr_Cmd nil))
  4.  
  5. (defun Vlr_Cmd (mode)
  6.   (cond
  7.     (mode
  8.       ;; Load only once, if already loaded reactivate it if inactive
  9.       (and *vlr-CWS (not (vlr-added-p *vlr-CWS)) (vlr-add *vlr-CWS))
  10.       (and *vlr-CE (not (vlr-added-p *vlr-CE)) (vlr-add *vlr-CE))
  11.       (and *vlr-CC (not (vlr-added-p *vlr-CC)) (vlr-add *vlr-CC))
  12.       (or *vlr-CWS
  13.          (setq *vlr-CWS (vlr-command-reactor nil '((:vlr-commandwillstart . CmdStartCommand)))))
  14.       (or *vlr-CE
  15.          (setq *vlr-CE (vlr-command-reactor nil '((:vlr-commandEnded . CmdEndCommand)))))
  16.       (or *vlr-CC
  17.          (setq *vlr-CC (vlr-command-reactor nil '((:vlr-commandCancelled . CmdCancelCommand)))))
  18.       (print "Command Reactor is ON!")
  19.     )
  20.  
  21.     ;;  Turn the reactors off
  22.     (t
  23.       (and *vlr-CWS (vlr-added-p *vlr-CWS) (vlr-remove *vlr-CWS))
  24.       (and *vlr-CE (vlr-added-p *vlr-CE) (vlr-remove *vlr-CE))
  25.       (and *vlr-CC (vlr-added-p *vlr-CC) (vlr-remove *vlr-CC))
  26.       (print "Command Reactor is OFF!")
  27.     )
  28.   )
  29.   (princ)
  30. )
  31.  
  32.  
  33.  
  34. (defun CmdEndCommand (Call CallBack)
  35.   (if (= (strcase (car CallBack)) "ERASE")
  36.     (progn
  37.       (alert "The End")
  38.     )
  39.   )
  40. )
  41.  
  42.  
  43. (defun CmdStartCommand (Call CallBack / ss slen)
  44.     (if (= (strcase (car CallBack)) "ERASE")
  45.       (progn
  46.         (if (setq ss (cadr(ssgetfirst)))
  47.           (setq slen (sslength ss))
  48.           (setq slen 0)
  49.         )
  50.         (alert (strcat "Erase Started with " (rtos slen 2 0) " items selected."))
  51.       )
  52.     )
  53. )
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lupo76

  • Bull Frog
  • Posts: 343
Re: vlr-erased - start before cancellation
« Reply #9 on: February 09, 2012, 03:32:29 AM »
What are you trying to do to the objects before the erase?


Your example is very good, but does not work.
The function must check every object selected by the user for the erase operation;
If the group selection there are blocks with a given name must obtain the value of an attribute, and only later, delete objects in the selection set.

At the time, your example is fine, that is, to get me to say how many items have been selected by the user.
With your code:
1. Load the file with your lisp code in AutoCAD
2. Start the command "CmdOn"
3. Start the command "erase" and select eg. 3 items
4. get an alert that always says 0 objects have been selected.

In practice, the selection set (setq ss (CADR (ssgetfirst)) is always zero! My problem is just that!: Cry:

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: vlr-erased - start before cancellation
« Reply #10 on: February 09, 2012, 11:23:52 AM »
I hope I'm understanding this properly: You want to save some data (attribute or xdata) from a block just before it gets erased. I'm not sure where you want to save (backup) the data though.

The principle (since there's no such thing as a reactor for objectAboutToBeErased) is to extract that data before the erase happens, then after the erase happened to actually save it into wherever you want.

AFAIK the "simplest" way you can effectively get at this would be to use a vlr-acdb-reactor ... on a :vlr-objectOpenedForModify event you test if the ename refers to an insert of the name you know. If so extract the data from that insert into a global association list (key being the ename of the object), add this to the list - since there could be more than one block erased at the same time. Then on the :vlr-objectErased event, check using assoc on the ename of the erased object if there's data storeds in the global list, if so save this to your choice of backup medium and remove the item from the global list. You might also need to run a :vlr-objectModified event to remove the item from the list if it was only modified but not erased.

You could play around with the command reactor, but as you've noted the selection would be nil if erase was started without a PickFirst selection set. So I'm guessing this would not work in all cases.

An alternative idea would be to open a vlr-object-reactor on all the inserts matching your block name, every time the DWG opens (or make it persistent). Then you could use the :vlr-erased event since this fires when a flag is changed for the object to be erased - it only gets erased when the :vlr-goodbye event fires. Though I wouldn't recommend this idea as I've had bad experiences with object reactors. Not to mention, this would not work on blocks inserted after the DWG was opened - unless you add yet another vlr-acdb-reactor on :vlr-objectAppended.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lupo76

  • Bull Frog
  • Posts: 343
Re: vlr-erased - start before cancellation
« Reply #11 on: February 09, 2012, 11:42:52 AM »
The problem is very simple.
The solution perhaps a bit less: cry:

From your response you seem to want to solve a problem much more complicated than mine. :-(
I am also willing to pay, just to solve the simple example of "CAB" or to issue an "alert" with the number of selected objects.
Obviously has to work, both running the command "erase" or by pressing the DEL key on the keyboard.

I tried to solve the problem with the reactor object but did not succeed (see my first post).
There are at least 4 days I try to solve this problem:  :x
If you had the sample code I would be very grateful!   :lol:
I do not know where to head-banging

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-erased - start before cancellation
« Reply #12 on: February 10, 2012, 03:13:08 PM »
Very little testing but this may be what you are looking for.

Code - Auto/Visual Lisp: [Select]
  1. (defun C:CmdOn () (Vlr_Cmd t))
  2.  
  3. (defun C:CmdOff () (Vlr_Cmd nil))
  4.  
  5. (defun Vlr_Cmd (mode)
  6.  (cond
  7.    (mode
  8.      ;; Load only once, if already loaded reactivate it if inactive
  9.      (and *vlr-CWS (not (vlr-added-p *vlr-CWS)) (vlr-add *vlr-CWS))
  10.      (and *vlr-CE (not (vlr-added-p *vlr-CE)) (vlr-add *vlr-CE))
  11.      (and *vlr-CC (not (vlr-added-p *vlr-CC)) (vlr-add *vlr-CC))
  12.      (or *vlr-CWS
  13.         (setq *vlr-CWS (vlr-command-reactor nil '((:vlr-commandwillstart . CmdStartCommand)))))
  14.      (or *vlr-CE
  15.         (setq *vlr-CE (vlr-command-reactor nil '((:vlr-commandEnded . CmdEndCommand)))))
  16.      (or *vlr-CC
  17.         (setq *vlr-CC (vlr-command-reactor nil '((:vlr-commandCancelled . CmdCancelCommand)))))
  18.      (princ "\nCommand Reactor is ON!")
  19.    )
  20.  
  21.    ;;  Turn the reactors off
  22.    (t
  23.      (and *vlr-CWS (vlr-added-p *vlr-CWS) (vlr-remove *vlr-CWS))
  24.      (and *vlr-CE (vlr-added-p *vlr-CE) (vlr-remove *vlr-CE))
  25.      (and *vlr-CC (vlr-added-p *vlr-CC) (vlr-remove *vlr-CC))
  26.      (princ "\nCommand Reactor is OFF!")
  27.    )
  28.  )
  29.  (princ)
  30. )
  31.      
  32.      
  33.      
  34.    
  35.      
  36. (defun CmdStartCommand (Call CallBack / ssErase slen)
  37.    (if (= (strcase (car CallBack)) "ERASE")
  38.      (progn
  39.        (setq *EraseStarted* t)
  40.        ;;(or *orApp (setq *orApp (vlr-acdb-reactor nil '((:vlr-objectappended . _ObjAdded)))))
  41.        (or *orEra (setq *orEra (vlr-acdb-reactor nil '((:vlr-objecterased . _ObjErased)))))
  42.        (if (setq ssErase (cadr(ssgetfirst)))
  43.          (setq slen (sslength ssErase))
  44.          (setq slen 0)
  45.        )
  46.        (alert (strcat "Erase Started with " (rtos slen 2 0) " items selected."))
  47.      )
  48.    )
  49.   (princ)
  50. )
  51.  
  52.  
  53. (defun CmdEndCommand (Call CallBack / slen)
  54.  (if (= (strcase (car CallBack)) "ERASE")
  55.    (progn
  56.      (setq *EraseStarted* nil) ; need for Canceled too
  57.      (if (and *ErasedList (> (length *ErasedList) 0))
  58.        (setq slen (length *ErasedList))
  59.        (setq slen 0)
  60.      )
  61.      (setq *ErasedList nil)
  62.      (alert (strcat "Erase Ended with " (rtos slen 2 0) " items erased."))
  63.    )
  64.  )
  65.   (princ)
  66. )
  67.  
  68. (defun CmdCancelCommand (Call CallBack / slen)
  69.  (if (= (strcase (car CallBack)) "ERASE")
  70.    (progn
  71.      (setq *EraseStarted* nil) ; need for Canceled too
  72. )))
  73.  
  74.      
  75. (defun _ObjAdded (a b / nent)
  76.   (if *EraseStarted*
  77.     (progn
  78.       (setq nent (vl-princ-to-string (cadr b)))
  79.       (princ (strcat "\n" nent " Added to Drawing"))
  80.     )
  81.   )
  82. )
  83.      
  84. (defun _ObjErased (a b / delent)
  85.   (if *EraseStarted*
  86.     (progn
  87.       (if (not (vl-position (cadr b) *ErasedList))
  88.         (setq *ErasedList (cons (cadr b) *ErasedList))
  89.       )              
  90.       (setq delent (vl-princ-to-string (cadr b)))
  91.       (princ (strcat "\n" delent " Deleted From Drawing"))
  92.     )
  93.   )
  94. )
« Last Edit: February 10, 2012, 03:39:28 PM by CAB »
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-erased - start before cancellation
« Reply #13 on: February 11, 2012, 09:20:38 AM »
Another version where the objecterased reactor is only on during the ERASE command.
Code - Auto/Visual Lisp: [Select]
  1. (defun C:CmdOn () (Vlr_Cmd t))
  2.  
  3. (defun C:CmdOff () (Vlr_Cmd nil))
  4.  
  5. (setq *CmdEraseDebug* t)
  6.  
  7. (defun Vlr_Cmd (mode)
  8.  (and *orEra (vlr-added-p *orEra) (vlr-remove *orEra)) ; only on during the erase command
  9.  ;; (and *orApp (vlr-added-p *orApp) (vlr-remove *orApp)) ; only on during the erase command
  10.  
  11.  (cond
  12.    (mode
  13.      ;; Load only once, if already loaded reactivate it if inactive
  14.      (and *vlr-CWS (not (vlr-added-p *vlr-CWS)) (vlr-add *vlr-CWS))
  15.      (and *vlr-CE  (not (vlr-added-p *vlr-CE))  (vlr-add *vlr-CE))
  16.      (and *vlr-CC  (not (vlr-added-p *vlr-CC))  (vlr-add *vlr-CC))
  17.      (or *vlr-CWS
  18.         (setq *vlr-CWS (vlr-command-reactor nil '((:vlr-commandwillstart . CmdStartCommand)))))
  19.      (or *vlr-CE
  20.         (setq *vlr-CE (vlr-command-reactor nil '((:vlr-commandEnded . CmdEndCommand)))))
  21.      (or *vlr-CC
  22.         (setq *vlr-CC (vlr-command-reactor nil '((:vlr-commandCancelled . CmdCancelCommand)))))
  23.      (princ "\nCommand Reactor is ON!")
  24.    
  25.      (or *orEra (setq *orEra (vlr-acdb-reactor nil '((:vlr-objecterased . _ObjErased)))))
  26.      ;; (or *orApp (setq *orApp (vlr-acdb-reactor nil '((:vlr-objectappended . _ObjAdded)))))
  27.   )
  28.  
  29.    ;;  Turn the reactors off
  30.    (t
  31.      (and *vlr-CWS (vlr-added-p *vlr-CWS) (vlr-remove *vlr-CWS))
  32.      (and *vlr-CE (vlr-added-p *vlr-CE) (vlr-remove *vlr-CE))
  33.      (and *vlr-CC (vlr-added-p *vlr-CC) (vlr-remove *vlr-CC))
  34.      (princ "\nCommand Reactor is OFF!")
  35.    )
  36.  )
  37.  (princ)
  38. )
  39.      
  40.      
  41.      
  42.    
  43.      
  44. (defun CmdStartCommand (Call CallBack / ssErase slen)
  45.    (if (= (strcase (car CallBack)) "ERASE")
  46.      (progn
  47.        (and *orEra (not (vlr-added-p *orEra)) (vlr-add *orEra)) ; trun on during the erase command
  48.        ;; (and *orApp (not (vlr-added-p *orApp)) (vlr-add *orApp)) ; trun on during the erase command
  49.        (setq *EraseStarted* t)
  50.        (if (setq ssErase (cadr(ssgetfirst)))
  51.          (setq slen (sslength ssErase))
  52.          (setq slen 0)
  53.        )
  54.        (and *CmdEraseDebug*
  55.             (alert (strcat "Erase Started with " (rtos slen 2 0) " items selected.")))
  56.      )
  57.    )
  58.   (princ)
  59. )
  60.  
  61.  
  62. (defun CmdEndCommand (Call CallBack / slen)
  63.  (if (= (strcase (car CallBack)) "ERASE")
  64.    (progn
  65.      (and *orEra (vlr-added-p *orEra) (vlr-remove *orEra)) ; turn OFF
  66.      ;; (and *orApp (vlr-added-p *orApp) (vlr-remove *orApp)) ; turn OFF
  67.      (setq *EraseStarted* nil) ; reset Erase command flag
  68.      (if (and *ErasedList (> (length *ErasedList) 0))
  69.        (setq slen (length *ErasedList))
  70.        (setq slen 0)
  71.      )
  72.      (setq *ErasedList nil)
  73.      (and *CmdEraseDebug*
  74.           (alert (strcat "Erase Ended with " (rtos slen 2 0) " items erased.")))
  75.    )
  76.  )
  77.   (princ)
  78. )
  79.  
  80. (defun CmdCancelCommand (Call CallBack)
  81.  (if (= (strcase (car CallBack)) "ERASE")
  82.    (progn
  83.      (and *orEra (vlr-added-p *orEra) (vlr-remove *orEra)) ; turn OFF
  84.      ;; (and *orApp (not (vlr-added-p *orApp)) (vlr-remove *orApp)) ; turn OFF
  85.      (setq *EraseStarted* nil) ; reset Erase command flag
  86.      (and *CmdEraseDebug* (princ "\nErase command canceled."))
  87.  
  88. )))
  89.  
  90. ;|  This function is not used
  91. (defun _ObjAdded (a b / nent)
  92.   (if *EraseStarted*
  93.     (progn
  94.       ;;  >>---> message to mommand line
  95.       (and *CmdEraseDebug*
  96.            (princ (strcat "\n" (vl-princ-to-string (cadr b)) " Added to Drawing")))
  97.       ;;  <---<<  end message
  98.     )
  99.   )
  100. )
  101. |;
  102.  
  103.  
  104. ;;  If ERASE command then collect ename of all erased entities
  105. (defun _ObjErased (a b / delent)
  106.   (if *EraseStarted*  ; flag for ERASE command started
  107.     (progn
  108.       ;;  may not be necessary but check the ent list to be
  109.       ;;  sure the ename is not there already
  110.       (if (not (vl-position (cadr b) *ErasedList))
  111.         (setq *ErasedList (cons (cadr b) *ErasedList)) ; collect the ename
  112.       )
  113.       ;;  >>---> message to mommand line
  114.       (and *CmdEraseDebug*
  115.            (princ (strcat "\n" (vl-princ-to-string (cadr b)) " Deleted From Drawing")))
  116.       ;;  <---<<  end message
  117.     )
  118.   )
  119. )
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lupo76

  • Bull Frog
  • Posts: 343
Re: vlr-erased - start before cancellation
« Reply #14 on: February 14, 2012, 01:33:35 AM »
Another version where the objecterased reactor is only on during the ERASE command.

Sorry for the delay of my answer.
I do not know how to thank you for the enormous job you did!

Indeed you have solved the problem that I had requested last post, but in a way that does not fit my actual needs.  :cry:
If you read my first post you'll see that I must find the value of some XDATA stored inside objects before they are deleted.
I try to explain better:

each object can contain the following XDATA:
(-3 ("NAMEAPP" (1000 . "ID=5")))

To extract the xdata ID of an object, usually using the following function:
Code: [Select]
(setq id_obj (ReadXdata obj "NAMEAPP" "ID"))

Code: [Select]
(defun ReadXdata (ogg nomeapp labeldato / dato elist exlist thexdata labelfind dato nX sublista)
   (setq nX 0)
   (setq elist (entget ogg (list nomeapp)))
   (setq exlist (assoc -3 elist))
   (if (/= exlist nil)
     (progn
   (setq thexdata (cdr (car (cdr exlist))))
   ;--
   (setq sublista (nth nX thexdata))
   (if sublista
       (setq labelfind (splittaemi (cdr sublista) "=" 0))
       (setq labelfind nil)
   )
   (while (/= labelfind nil)
       (if (= labelfind labeldato)
(progn
    (setq sublista (nth nX thexdata))
    (if sublista (setq dato (splittaemi (cdr sublista) "=" 1)))
    (setq labelfind nil)
)
(progn
   (setq nX (+ nX 1))
   (setq sublista (nth nX thexdata))
   (if sublista
     (setq labelfind (splittaemi (cdr sublista) "=" 0))
     (setq labelfind nil)

   )
)
       )
   )
   (setq dato dato)
      )
    )
   ;--
)

Everything works fine when the object is present in the drawing.
Now I need to obtain the xdata "ID" immediately before it is deleted.
With your function unfortunately I can not do it ....

I'm sorry you missed all this time.
I am so insistent because I absolutely need to solve this problem, otherwise the interruption of the entire application.  :cry:
Hope you can help me some more ....