CLIM mail archive


"Grouping" of presentations

    Date: Wed, 20 May 1992 06:05 PDT
    From: Stefan Bernemann <>

    this time :-) I want to implement a feature of drawing applications or
    graph editors, namely the grouping of presentations. That means, I want
    to *replace* a set of presentations (no matter of what type) by ONE
    other presentation (e.g. of type "group").

    That is, I don't want to keep the old presentations of the objects (at
    least I want to change their types), because otherwise there would be
    the same access to objects be they contained in a group or not -- but it
    makes not sense (in my application) e.g. to drag a single presentation
    "inside a group" -- only the group as a whole may be manipulated. 

    However, I don't want to erase and readraw any graphical output done to
    the screen, for efficienc reasons but mostly to minimize unnecessary
    screen flicker. 

    Can this be done with CLIM? How must I fiddle with the output record and
    the history? Or am I completely off the road and the CLIM approach is
    totally different? (parameterized presentations?)

I have included some sample code below.  It basically takes the
existing presentations and makes them children of a new "group"
presentation, and then splices that new presentation in to the output
record tree.

I would have specified :ALLOW-SENSITIVE-INFERIORS NIL when creating
the parent presentation, but that is not yet supported.  This means
that the individual members of the group remain sensitive, even while
the group as a whole is sensitive.  If that isn't what you want, you
can try suppressing inner sensitivity by either directly altering the
presentation types of the inferiors when they are grouped (of course
you will have to keep track of the old type so that it can be restored
when they are ungrouped), or maybe by writing a presentation
translator that tests to see whether a presentation is a child of a
group before allowing sensitivity.

Try this out and let me know if you have any questions.

;;; -*- Mode: LISP; Syntax: Common-Lisp; Base: 10; Package: CLIM-USER -*-

(in-package :clim-user)

;;; Group the supplied output records in a new parent presentation.
;;; The type and object of the new parent are passed as arguments.
(defun group-output-records (output-record-list presentation-type presentation-object)
  ;; All the output records must share the same parent.
  (assert (reduce #'(lambda (a b)
		      (and (eql a b) a))
		  output-record-list :key #'output-record-parent)
	  "All output records must all have the same parent.")
  ;; Make a new presentation to hold the others.
  (let ((new-parent (make-instance 'standard-presentation 
				   :type presentation-type
				   :object presentation-object
				   ;; :SINGLE-BOX means to make one
				   ;; box around the whole group.
				   :single-box t))
	(original-parent (output-record-parent (first output-record-list))))
    (dolist (child output-record-list)
      ;; Remove the records from their old parent.
      (delete-output-record-element original-parent child)
      ;; Make them children of the new presentation.
      (add-output-record-element new-parent child))
    ;; Add the new parent presentation as a child of the original parent.
    (add-output-record-element original-parent new-parent)

;;; This test function creates two presentations, asks the user to select one,
;;; then groups the presentations and asks the user to select again.
(defun test (win)
  ;; Assumes that the window is ~200 pixels high.
  (window-clear win)
  (window-expose win)
  (let ((records nil))
    (push (with-output-as-presentation (:stream win
					:object 2
					:type 'integer)
	    (draw-rectangle* win 10 100 20 110))
    (push (with-output-as-presentation (:stream win
					:object 3
					:type 'integer)
	    (draw-rectangle* win 50 150 60 160))
    (accept 'integer :stream win)
    (group-output-records records 'integer 1)
    (accept 'integer :stream win)))


Main Index | Thread Index