CLIM mail archive

[Prev][Next][Index][Thread]

Dragging nodes of a formatting graph



   Date: Wed, 4 Nov 92 15:15:20 PST
   From: Brian Anderson <bha@atc.boeing.com>

   I want to use clim:formatting-graph-from-root to layout an *initial*
   version of a graph.  Then, I want the user to be able to drag graph
   nodes to a desired position, and redraw the node and connecting
   links at the new position.  I also want to be able to capture the
   position of each graph node so that I can write an external
   representation of the graph and redraw it at a later time (possibly in
   another Lisp session).

   Has anyone done anything like this beast?  Does anyone have any
   suggestions on how to approach this?  Is this going to be mega-hard?

(in-package :clim)

(defun move-graph-node (stream node new-x new-y)
  (let* ((graph (output-record-parent node))
	 (orientation (slot-value graph 'orientation)))
    (draw-related-edges stream node +background+ orientation)
    (with-bounding-rectangle* (left top right bottom) node
      (with-output-recording-options (stream :record-p nil)
	(draw-rectangle* stream left top right bottom :ink +background+)))
    (output-record-set-position* node new-x new-y)
    (replay node stream)
    (draw-related-edges stream node +foreground+ orientation)))

(defun draw-related-edges (stream node ink orientation)
  (labels ((parent-attachment-position (node)
	     (with-bounding-rectangle* (left top right bottom) node
	       (case orientation
		 ((:horizontal :right)
		  (values (1+ right) (the fixnum (+ top (floor (- bottom top) 2)))))
		 ((:vertical :down)
		  (values (the fixnum (+ left (floor (- right left) 2))) (1+ bottom))))))
	   (child-attachment-position (node)
	     (with-bounding-rectangle* (left top right bottom) node
	       (case orientation
		 ((:horizontal :right)
		  (values (1- left) (the fixnum (+ top (floor (- bottom top) 2)))))
		 ((:vertical :down)
		  (values (the fixnum (+ left (floor (- right left) 2))) (1- top))))))
	   (draw-edge (parent child)
	     (multiple-value-bind (parent-x parent-y)
		 (parent-attachment-position parent)
	       (multiple-value-bind (child-x child-y)
		   (child-attachment-position child)
		 (draw-line* stream parent-x parent-y child-x child-y
			     :ink ink)))))
    (declare (dynamic-extent #'parent-attachment-position
			     #'child-attachment-position))
    ;; Assuming a tree for simplicity
    (let ((parent (first (graph-node-parents node)))
	  (children (graph-node-children node)))
      (when parent
	(draw-edge parent node))
      (dolist (child children)
	(draw-edge node child)))))

0,,

References:

Main Index | Thread Index