Newsgroups: comp.lang.lisp.mcl
Path: cantaloupe.srv.cs.cmu.edu!europa.chnt.gtegsc.com!news.mathworks.com!news.bluesky.net!news.sprintlink.net!demon!uknet!sunsite.doc.ic.ac.uk!susx.ac.uk!news.bton.ac.uk!news
From: mick@darmstadt.gmd.de (Michael O'Donnell)
Subject: Contrib: Easy to Use Grapher Interface
X-Nntp-Posting-Host: ross.itri.bton.ac.uk
Message-ID: <D9K3GM.CEK@bton.ac.uk>
Sender: news@bton.ac.uk
Reply-To: mick@darmstadt.gmd.de
Organization: No Thanks!
References: <3q7chn$e1n@worm.inch.com>
Date: Fri, 2 Jun 1995 17:33:57 GMT
Lines: 146


  I have uploaded some MCL code which provides a very easy to use
set of extensions to the MCL grapher. To download, anonymous ftp to ftp.digitool.com, cd pub/mcl2/contrib, get Micks-Grapher1.0.sea.hqx.

Description
-----------

The typed-node grapher offers an easy-to-use interface
to the MCL Grapher. Each node is assigned both a name
and a type. Each node-type can have its own characteristics.
New types of graphs are easy to define. For instance,
the following defines a CLOS class node-type.

(def-graph-node-type :class
  :children ccl::class-direct-subclasses 
  :child-type :class
  :display-function ccl::class-name)

  The three fields of the node-type definition tell us the
following about the :class nodes:

   :children - the function to use to get children nodes.
   :child-type - the node type of the children. Children can be of a different
           types to the parent, as explained below.
   :display-function - if supplied, this function is applied
      to the node-name to get the string actually displayed in the graph.

To graph the class heirarchy under any class, we just use one function
call:

   (graph-object (find-class 'ccl::view) :class 3)


  So, making new graphs is easy. 4 lines to defines the class-node-type,
and one to mke a graph.


Customising Graphs
------------------

Micks Grapher offers various customisable options:

  o Graphs may be Vertical or Horizontal

  o You can define font size/style, underline, case etc.
    individually for each node-type

  o Graphs can be square or angled, e.g.,
                          b
        - b             /
     a-|         or    a 
        - c             \
                          c

  o Graphs can be limited by depth (how many levels from root
    to leaves), and you can selectively go deeper into the graph as needed.

  o You can define what happens when you double-click or option-click
     on a node.

  o If you click down on a node, a menu of options appears, allowing
    various user-defined actions to occur.

  o A window-based interface allows you to call up a graph of a defined
    type in a few key-strokes.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; An Example - A File System Browser
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  The following two node-types define a rudimentary file-system grapher.
From a user-supplied starting directory, the files and sub-directories are presented.
Double-clicking on a directory will bring up a sub-graph showing that directory
to more depth. Double-clicking on a filename will bring up that file in 
an editing window.

---------------------------------------------------------------------

(def-graph-node-type :directory
  :children (directory  (make-pathname   :name "*" :defaults $name) 
                        :directories t)
  :child-type (if (directoryp $child-name)
                :directory
                :file)
  :font-size 10
  :print-case :upcase
  :layout-direction :horizontal
  :child-link-type :square
  :display-function dir-name
  :double-click-function (graph-object $name :directory))


(def-graph-node-type :file
  :font-size 10
  ;:print-case :downcase
  :display-function ccl::mac-file-namestring
  :menu-items (("Compile File" compile-file))
  :double-click-function (make-instance 'ccl::fred-window :filename $name))

(defun dir-name (dir)
"Returns the current Directory component of the directory path."
  (car (last (ccl::pathname-directory (mac-directory-namestring dir)))))

;(graph-object "HomeDir;" :directory 2)

---------------------------------------------------------------------

  Two types of nodes are defined -- one for directories, one for files.
The child-function of :directory nodes is defined by some user-defined code.
The '$name' which appears in the code will be substituted for by
the name of any instance of this node.

  Similarly for the :child-type field -- the type of each child
will be determined individually, depending on whether the name
of the child-node (substituted for $child-name) is directory or not.

  Other fields specify that a :directory node appears in 10 point,
uppercase, that square-bracketing is used, in a horizontal direction
(across the page).

 The function dir-name (code also provided) is used to produce the string
actually displayed on the graph.

  Double-Clicking on the :directory node produces another graph, with that node as 
the starting point. Clicking on a :file node will bring that file up in an editor.

  Clicking down on a node produces a list of menu options.
Users can add options to this menu using the
:menu-items field. Note its use in the :file definitionto allow selected files to be compiled.
We could also add file-deletion, printing, searching etc.
---------

  Once these node-types are defined, a simple function-call will make
a graph:

   (graph-object "HomeDir;" :directory 2)

The three arguments here are:

1) "HomeDir;" (Node-Name) a directory name
2) :directory (Node-Type) the type of the node 
3) 2 (Graph-Depth) How many nodes deep the graph should go.




