[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: the mysterious wake of copy-instance
- To: info-mcl@ministry.cambridge.apple.com
- Subject: Re: the mysterious wake of copy-instance
- From: John_Gersh@aplmail.jhuapl.edu (John R. Gersh)
- Date: Tue, 7 Dec 1993 20:26:53 GMT
- Followup-to: comp.lang.lisp.mcl
- Newsgroups: comp.lang.lisp.mcl
- Organization: The Johns Hopkins University Applied Physics Lab
- References: <9312062250.AA16305@merle.acns.nwu.edu>
- Sender: usenet@aplcomm.jhuapl.edu
In article <9312062250.AA16305@merle.acns.nwu.edu>, christian e. crone
wrote:
> i need to be able to make copies of view hierarchies (e.g., views inside of
> views inside of views) whether on-screen or off. it is fairly obvious that
> macl's copy-instance cannot be directly applied, since it only changes the
> top level pointers.
[Discussion of the consequences of this.]
> but, why is it incorrect to recursively do the following --
[Remove and save subviews, copy the containing view, add copies of the
subviews
to the new copy, replace the subviews in their original views]
> anyway, implemented as follows:
>
> (defmethod rec-copy-instance ((view view))
> (let ((new-view nil)
> (subview-list nil))
> (do-subviews (subview view)
> (setq subview-list (cons subview subview-list)) ;; step 1
> (remove-subviews view subview)) ;; step 2
> (setq new-view (copy-instance view)) ;; step 3
> (dolist (subview subview-list)
> (add-subviews new-view (rec-copy-instance subview)) ;; 4 & 5, p 2
> (add-subviews view subview)) ;; 5, part 1
> new-view))
>
> yields the result:
[The copied view _and_ the original view contain _both_ the original
subviews
and their copies.]
The problem here is that the slot that defines a view's subviews is the
view-subviews slot, whose value is a vector; the subviews are elements of
that vector. The add-subviews method (by calling the set-view-container
method) destructively modifies that vector by vector-push-extending the new
subview into it.
The copy-instance in the above code, as noted, only carries over the
top-level pointers to the instance's slots, so that both new-view and view
have the
_same_ view-subviews vector. The add-subviews actions, therefore,
effectively add the copies and the original subviews into _both_ view and
new-view at the same time.
Giving the copy of the emptied-out view a fresh view-subviews vector seems
to fix things; it also eliminates the need to remove and restore the
original view's subviews:
(defmethod rec-copy-instance ((view named-view))
(let ((new-view nil)
(subview-list (subviews view)))
(setq new-view (copy-instance view))
(setf (slot-value new-view 'view-subviews)
(make-array 1 :adjustable t :fill-pointer 0))
(dolist (subview subview-list)
(add-subviews new-view (rec-copy-instance subview)))
new-view))
With, for demonstration:
(defclass named-view (view)
((name :initarg :name :accessor name)))
(defmethod contents ((n named-view))
(when (subviews n)
(format *standard-output* "~A contains ~{~A ~}~&"
(name n) (mapcar #'name (subviews n)))
(mapcar #'contents (subviews n)))
(values))
? (setf Baltimore (make-instance 'named-view :name "Baltimore"))
#<NAMED-VIEW #x4CCE31>
? (setf Maryland (make-instance 'named-view :name "Maryland"))
#<NAMED-VIEW #x4CCF31>
? (setf Massachusetts (make-instance 'named-view :name "Massachusetts"))
#<NAMED-VIEW #x4CD029>
? (setf USA (make-instance 'named-view :name "USA"))
#<NAMED-VIEW #x4CD121>
? (add-subviews Maryland Baltimore)
NIL
? (add-subviews USA Maryland Massachusetts)
NIL
? (contents USA)
USA contains Maryland Massachusetts
Maryland contains Baltimore
? (setf America (rec-copy-instance USA))
#<NAMED-VIEW #x4CD349>
? (contents America)
USA contains Maryland Massachusetts
Maryland contains Baltimore
? (contents USA)
USA contains Maryland Massachusetts
Maryland contains Baltimore
? (remove-subviews USA Maryland)
NIL
? (contents USA)
USA contains Massachusetts
? (contents America)
USA contains Maryland Massachusetts
Maryland contains Baltimore
--
=== John R. Gersh John_Gersh@aplmail.jhuapl.edu
=== The Johns Hopkins University Applied Physics Laboratory
=== Laurel, MD 20723 +1(301)953-5503