Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Reactors and the UNDO command

10 REPLIES 10
Reply
Message 1 of 11
Anonymous
557 Views, 10 Replies

Reactors and the UNDO command

Hi,

I have written a program which sets reactors to certain objects which causes run a LISP program when they are modified - This bit works fine.

I have now added a bit to remove the reactor when the object is deleted by the user so that an error doesn't occur.

But I've noticed that if the user accidently deletes the object which has the modify reactor set on it, and then types UNDO to restore it - it comes back but the reactor is not restored.

AutoCAD users expect the UNDO command to restore everything back to its original state - this seems not to be the case with an object that has a reactor on it - The user wont realise that the restored objects will now not run the LISP program when modified?

(BTW I am using UNDO GROUP and UNDO END in the lisp program)

Is this the case - Or am I missing something??
10 REPLIES 10
Message 2 of 11
Anonymous
in reply to: Anonymous

It helps to see what you are doing.... or post the part of your code, you think is causing the problems. Anyway, here is little sample about Visual Lisp object reactors, to always change a block with two attributes the value of the fist attribute with the second one. In this case, notice if you delete/erase any of the blocks and when undo is issue, the reactor are kept or restore. Make a block made with two attributes, and then test the routine.... ;; code (vl-load-com) (defun commandended (reactor params / atts att1 att2 text_att1 text_att2) (if modified_list (foreach blk modified_list (setq atts (reverse (vlax-safearray->list (vlax-variant-value (vla-getattributes blk)))) att1 (car atts) att2 (cadr atts) text_att1 (vla-get-textstring att1) text_att2 (vla-get-textstring att2)) (if (/= text_att2 text_att1) (vla-put-textstring att1 (vla-get-textstring att2))))) (setq modified_list nil)) (defun subobjmodified (owner reactor params) (if (and (not (wcmatch (getvar "cmdnames") "UNDO,U,REDO,OOPS")) (not (vl-position owner modified_list))) (setq modified_list (cons owner modified_list)))) (defun C:TEST (/ obj obj_reactor) (setq obj (vlax-ename->vla-object (car (entsel "\nSelect block with two attributes: ")))) (if (not editor_reactor) (setq editor_reactor (vlr-editor-reactor "editor" '((:vlr-commandended . commandended))))) (setq obj_reactor (vlr-object-reactor (list obj) "obj" '((:vlr-subobjmodified . subobjmodified)))) (princ)) (princ) ;; code HTH LE. "archie999" wrote in message news:22601160.1112176006185.JavaMail.jive@jiveforum2.autodesk.com... > Hi, > > I have written a program which sets reactors to certain objects which causes run a LISP program when they are modified - This bit works fine. > > I have now added a bit to remove the reactor when the object is deleted by the user so that an error doesn't occur. > > But I've noticed that if the user accidently deletes the object which has the modify reactor set on it, and then types UNDO to restore it - it comes back but the reactor is not restored. > > AutoCAD users expect the UNDO command to restore everything back to its original state - this seems not to be the case with an object that has a reactor on it - The user wont realise that the restored objects will now not run the LISP program when modified? > > (BTW I am using UNDO GROUP and UNDO END in the lisp program) > > Is this the case - Or am I missing something??
Message 3 of 11
Anonymous
in reply to: Anonymous

> AutoCAD users expect the UNDO command to restore > everything back to its original state - this seems not to > be the case with an object that has a reactor on it - The > user wont realise that the restored objects will now not > run the LISP program when modified? The user shouldn't have to think about what happens when an object is modified. Users shouldn't be required to be that familiar with the details of customization. Why are you removing the reactor when the object is erased? What error occurs if you don't remove the reactor? -- http://www.caddzone.com AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005 http://www.acadxtabs.com
Message 4 of 11
Anonymous
in reply to: Anonymous

Tony / Luis,

The program is basically for adding the area of a polyline into a block attribute - so when the polyline is modified in amy way the area is then updated in the block attribute.

I have a reactor set on the polyline which run a LISP which measures the polylines area then updates the block attribute.

I also have a reactor on the block which warns the users when he deletes it - it tells the users that the block which was just deleted belonged to a polyline - (Just out of interest - if the user does delete the block and then type UNDO the reactor all is restored including the reactors).

The above works fine - the following conditions occur which I was trying to stop by removing the reactor;

- The block is delete - When the users now modifies the polyline the LISP program then fails and generates an error as the block doesn't exist.

- The polyline is deleted - Not much of a problem but for good housekeeping I would now like to remove the reactor on the block.

Also, if the reactor has owners which have been deleted it generates a non critical error the next time the drawing is loaded

This is the routine I use for removing the reactors which will be called when either the block or polyline is deleted. (this is the LISP which the UNDO command does seem to restore the reactors)

(defun check (qobject / ObjRea
foundreactor ReaLst reaitem
objrea-ename reaitem-ename objrea-handle
reaitem-handle
)

(setq ObjRea (vlax-ename->vla-object qobject)
foundreactor nil
ReaLst (mapcar
'(lambda (l)

(cons (car (vlr-owners l)) l)
)
(cdar (vlr-reactors :vlr-object-reactor))
)
)

(foreach reaitem realst

(setq objrea-ename (vlax-vla-object->ename objrea)
reaitem-ename (vlax-vla-object->ename (car reaitem))
objrea-handle (cdr (assoc 5 (entget objrea-ename)))
reaitem-handle (cdr (assoc 5 (entget reaitem-ename)))
)

(if (= reaitem-handle objrea-handle)
(setq foundreactor reaitem)
)

)

(princ foundreactor)

)



(defun c:removereactorboth (/ mainob otherob)

(command "undo" "group")

(setq mainob (check (car (entsel)))
otherob (check (handent (vlr-data (cdr mainob))))
)

(vlr-owner-remove (cdr mainob) (car mainob))
(vlr-owner-remove (cdr otherob) (car otherob))

(command "undo" "end")
(princ)

)

The programs a bit rough and ready and I have just put it together ...

Luis - I haven't had a chance to look at your routine - I'll do that now...
Message 5 of 11
Anonymous
in reply to: Anonymous

Luis,

I seem to be able to recreate the problem with your LISP.

If you load my program then type;

(setq mainob (check (car (entsel))))

And then select the block, then type:

(vlr-owner-remove (cdr mainob) (car mainob))

The reactor is removed - but UNDO doesn't bring the reactor back...
Message 6 of 11
Anonymous
in reply to: Anonymous

Oops - I should have written - load your routine first and set up a block and run your test routine on it and then load my routine and type:

(setq mainob (check (car (entsel))))
(vlr-owner-remove (cdr mainob) (car mainob))
Message 7 of 11
Anonymous
in reply to: Anonymous

Is Archie your real name? I added the erased event on my object reactor and remove the reactor and also I have a function to remove vlr-owners and vlr-data and I have no problems with the undo. LE "archie999" wrote in message news:6918155.1112268077456.JavaMail.jive@jiveforum2.autodesk.com... > Luis, > > I seem to be able to recreate the problem with your LISP. > > If you load my program then type; > > (setq mainob (check (car (entsel)))) > > And then select the block, then type: > > (vlr-owner-remove (cdr mainob) (car mainob)) > > The reactor is removed - but UNDO doesn't bring the reactor back...
Message 8 of 11
Anonymous
in reply to: Anonymous

Luis,

How did you get it to work? Did you use my routine?

"I have a function to remove vlr-owners and vlr-data "

Do you think its a problem with my code?
Message 9 of 11
Anonymous
in reply to: Anonymous

Yes.

In order to recreate the reactor, you must do the following:

1. Have the ERASED event in your reactor
2. Inside the ERASED function callback, do the appropriate for the DATA part.
[code]
(defun erased (owner reactor params)
(vlr-owner-remove reactor owner)
(vlr-data-set reactor nil)
(vlr-remove reactor))
[/code]

If I use your function, I am destroying the reactor before using erase, that is the reason the reactor is not being recreated.

Have fun,
Luis.
Message 10 of 11
Anonymous
in reply to: Anonymous

Hi Luis,

I still dont understand why I need to do as you suggets.

Although eventually I want to get the routine to deal with the user erasing the object with the reactor on it, the routine I posted just deals with removing a reactor - (I will do the erase bit later).

Check out this lisp in which I have put together the following functions;

c:test - This is your function which sets up a reactor which copies attributes

check - This is my fuction which returns the name of a reactor set on an object

erased - this from your previous post which removes the data and reactor from an object

c:killreactor - this is the main fuction which lets the user select an object then it run check and erased.



(defun commandended
(reactor params / atts att1 att2 text_att1 text_att2)
(if modified_list
(foreach blk modified_list
(setq atts
(reverse (vlax-safearray->list
(vlax-variant-value (vla-getattributes blk))
)
)
att1 (car atts)
att2 (cadr atts)
text_att1 (vla-get-textstring att1)
text_att2 (vla-get-textstring att2)
)
(if (/= text_att2 text_att1)
(vla-put-textstring att1 (vla-get-textstring att2))
)
)
)
(setq modified_list nil)
)

(defun subobjmodified (owner reactor params)
(if (and (not (wcmatch (getvar "cmdnames") "UNDO,U,REDO,OOPS"))
(not (vl-position owner modified_list))
)
(setq modified_list (cons owner modified_list))
)
)




(defun C:TEST (/ obj obj_reactor)
(setq obj (vlax-ename->vla-object
(car (entsel "\nSelect block with two attributes: "))
)
)

(if (not editor_reactor)
(setq editor_reactor
(vlr-editor-reactor
"editor"
'((:vlr-commandended . commandended))
)
)
)

(setq obj_reactor
(vlr-object-reactor
(list obj)
"obj"
'((:vlr-subobjmodified . subobjmodified))
)
)
(princ)
)

(princ)





(defun check (qobject /)

(setq ObjRea (vlax-ename->vla-object qobject)
foundreactor nil
ReaLst (mapcar
'(lambda (l)

(cons (car (vlr-owners l)) l)
)
(cdar (vlr-reactors :vlr-object-reactor))
)
)

(foreach reaitem realst


(setq objrea-ename (vlax-vla-object->ename objrea)
reaitem-ename (vlax-vla-object->ename (car reaitem))

)

(if (/= objrea-ename nil)
(setq objrea-handle (cdr (assoc 5 (entget objrea-ename))))
(setq objrea-handle nil)
)
(if (/= reaitem-ename nil)
(setq reaitem-handle (cdr (assoc 5 (entget reaitem-ename))))
(setq reaitem-ename nil)
)




(if (= reaitem-handle objrea-handle)
(setq foundreactor reaitem)
)

)
(princ foundreactor)

)




(defun erased (owner reactor params)
(princ "\nOK1")
(vlr-owner-remove reactor owner)
(princ "\nOK2")
(vlr-data-set reactor nil)
(princ "\nOK3")
(vlr-remove reactor)
(princ "\nOK4")
)



(defun c:killreactor ()

(setq getobject (car (entsel))) ; User picks object

(setq objectsreactor (check getobject))
; Finds the reactor on the object

(princ "\nOK to here")

(erased (car objectsreactor) (cdr objectsreactor) nil)
; Removes the reactor
)


If you now make a block with two attributes, then run test on it and then type "Killreactor" and select the block - it removes the reactor from the object.

But if I type UNDO - It doesn't come back (I'm not trying to erase anything at this point) - I'm just trying to get the UNDO command to restore the reactor just as it restores anything else which the user does.

Thanks for your help on this Luis - Any advise??
Message 11 of 11
Anonymous
in reply to: Anonymous

> I still dont understand why I need to do as you suggets. All will depend on you... I am just posting what I know. > Although eventually I want to get the routine to deal with the user erasing the object with the reactor on it, the routine I posted just deals with removing a reactor - (I will do the erase bit later). You can not use UNDO if you kill the reactor, the only way you can get it back is by having the erased event in your reactor. You may try to have a list of those objects [inside of the check function] and in the commandended event check for the UNDO,U command and re-create the reactor over there. LE.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report