;;; -*- Mode: Lisp -*-

;;;  (c) copyright 1998,1999,2000 by Michael McDonald (mikemac@mikemac.com)
;;;  (c) copyright 2000 by 
;;;           Robert Strandh (strandh@labri.u-bordeaux.fr)
;;;  (c) copyright 2005-2006 by
;;;	      Andreas Fuchs (asf@boinkor.net)
;;;
;;; This library is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Library General Public
;;; License as published by the Free Software Foundation; either
;;; version 2 of the License, or (at your option) any later version.
;;;
;;; This library is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Library General Public License for more details.
;;;
;;; You should have received a copy of the GNU Library General Public
;;; License along with this library; if not, write to the 
;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
;;; Boston, MA  02111-1307  USA.


;;; Really, I wouldn't bother with anything but ASDF. Almost every lisp
;;; ships with it, and it has the added benefit of ASDF-INSTALL.
;;; Get ASDF, and be welcome to the 21st century. -- [2005-01-31:asf]

(defpackage :mcclim.system
  (:use :asdf :cl))
(in-package :mcclim.system)

(defparameter *clim-directory* (directory-namestring *load-truename*))

;;; Legacy CMUCL support stuff
#+cmu
(progn
  (unless (fboundp 'ext:stream-read-char)
    (unless (ignore-errors (ext:search-list "gray-streams:"))
      (setf (ext:search-list "gray-streams:")
	'("target:pcl/" "library:subsystems/")))
    (if (fboundp 'extensions:without-package-locks)
	(extensions:without-package-locks
	 (load "gray-streams:gray-streams-library"))
      (load "gray-streams:gray-streams-library")))
  #-clx
  (require :clx)
  #+mp (when (eq mp::*initial-process* mp::*current-process*)
	 (format t "~%~%You need to run (mp::startup-idle-and-top-level-loops) to start up the multiprocessing support.~%~%")))

;;; Make CLX asdf-loadable on Allegro 6.2
;;; possibly this should be further refined to funciton properly for
;;; Allegro on Windows platforms. [2005/04/18:rpg]
#+allegro
(progn
  (defclass requireable-system (asdf:system)
       ())
  (defmethod asdf:perform ((op asdf:load-op) (system requireable-system))
    (require (intern (slot-value system 'asdf::name) :keyword)))
  (defmethod asdf::traverse ((op asdf:load-op) (system requireable-system))
    (list (cons op system)))  
  (defsystem :clx
    :class requireable-system))

(defmacro clim-defsystem ((module &key depends-on) &rest components)
  `(progn
     (asdf:defsystem ,module
	 ,@(and depends-on
		`(:depends-on ,depends-on))
	 :serial t
	 :components
	 (,@(loop for c in components
		  for p = (merge-pathnames
			   (parse-namestring c)
			   (make-pathname :type "lisp"
					  :defaults *clim-directory*))
		  collect `(:file ,(namestring p) :pathname ,p))))))

(eval-when (:compile-toplevel :execute :load-toplevel)
  (defun fix (&optional (prefix "Lisp-Dep/"))
    (concatenate 'string prefix
                 #+cmu       "fix-cmu"
                 #+scl       "fix-scl"
                 #+excl      "fix-acl"
                 #+sbcl      "fix-sbcl"
                 #+openmcl   "fix-openmcl"
                 #+lispworks "fix-lispworks"
                 #+clisp     "fix-clisp"))
  (defun mp (&optional (prefix "Lisp-Dep/"))
    (concatenate 'string prefix
                 (first '(#+(and :cmu :mp (not :pthread))  "mp-cmu"
                          #+scl                     "mp-scl"
                          #+sb-thread               "mp-sbcl"
                          #+excl                    "mp-acl"
                          #+openmcl                 "mp-openmcl"
                          #+lispworks               "mp-lw"
                          #| fall back |#           "mp-nil"))))) 

(defsystem :clim
  :depends-on (:spatial-trees)
  :components
  (;; ex clim-lisp
   (:file "patch" :depends-on ())
   (:file "package" :depends-on (#.(fix)))   (:file #.(fix) :pathname #.(make-pathname :directory '(:relative "Lisp-Dep") :name (fix "") :type "lisp")
          :depends-on ("patch"))
   (:file #.(mp) :pathname #.(make-pathname :directory '(:relative "Lisp-Dep") :name (mp "") :type "lisp")
          :depends-on ("decls"))

   ;; ex clim-core
   (:file "decls" :depends-on ("package"))
   (:file "protocol-classes" :depends-on (#.(mp) "package"))
   (:file "utils" :depends-on (#.(mp) "package"))
   (:file "design" :depends-on (#.(mp) "decls" "protocol-classes" "package"))
   (:file "X11-colors" :depends-on (#.(mp) "design" "package"))
   (:file "coordinates" :depends-on (#.(mp) "package"))
   (:file "setf-star" :depends-on (#.(mp) "package"))
   (:file "transforms" :depends-on (#.(mp) "decls" "protocol-classes" "package"))
   (:file "regions" :depends-on (#.(mp) "setf-star" "utils" "decls"
                                   "protocol-classes" "package"))
   (:file "sheets" :depends-on (#.(mp) "regions" "decls" "protocol-classes"
                                  "package"))
   (:file "pixmap" :depends-on (#.(mp) "protocol-classes" "decls" "package"))
   (:file "events" :depends-on (#.(mp) "utils" "protocol-classes" "package"))
   (:file "ports" :depends-on (#.(mp) "pixmap" "sheets" "decls"
                                 "protocol-classes" "package"))
   (:file "grafts" :depends-on (#.(mp) "decls" "sheets" "package"))
   (:file "medium" :depends-on (#.(mp) "pixmap" "utils" "ports" "decls"
                                  "protocol-classes" "package" "X11-colors"))
   (:file "output" :depends-on (#.(mp) "utils" "medium" "pixmap" "decls"
                                  "package"))
   (:file "input" :depends-on (#.(mp) "events" "regions" "sheets" "package"))
   (:file "repaint" :depends-on (#.(mp) "events" "sheets" "decls" "package"))
   (:file "graphics" :depends-on (#.(mp) "design" "regions" "transforms" "decls"
                                    "medium" "pixmap" "output" "protocol-classes"
                                    "utils" "package"))
   (:file "views" :depends-on (#.(mp) "decls" "protocol-classes" "package"))
   (:file "stream-output" :depends-on (#.(mp) "input" "decls" "output"
                                         "protocol-classes" "utils" "setf-star"
                                         "package"))
   (:file "recording" :depends-on (#.(mp) "decls" "medium" "transforms"
                                     "graphics" "output" "stream-output"
                                     "protocol-classes" "regions" "utils"
                                     "setf-star" "package"))
   (:file "encapsulate" :depends-on (#.(mp) "recording" "stream-output" "medium"
                                       "decls" "sheets" "protocol-classes"
                                       "package"))
   (:file "stream-input" :depends-on (#.(mp) "decls" "sheets" "setf-star"
                                        "encapsulate" "events" "protocol-classes"
                                        "input" "package"))
   (:file "text-selection" :depends-on (#.(mp) "regions" "protocol-classes"
                                          "sheets" "graphics" "utils" "output"
                                          "decls" "events" "package"))

   ;; ex clim
   (:file "text-formatting" :depends-on (#.(mp) "protocol-classes" "encapsulate"
                                           "utils" "package"))
   (:file "input-editing" :depends-on (#.(mp) "utils" "stream-input"
                                         "encapsulate" "protocol-classes"
                                         "Goatee/editing-stream" "package"))
   (:file "presentations" :depends-on (#.(mp) "utils" "regions" "recording"
                                         "protocol-classes" "package"))
   (:file "defresource" :depends-on (#.(mp) "package"))
   (:file "presentation-defs" :depends-on (#.(mp) "views" "input-editing"
                                             "stream-input" "Goatee/kill-ring"
                                             "decls" "recording"
                                             "protocol-classes" "utils"
                                             "presentations" "package"))
   (:file "pointer-tracking" :depends-on (#.(mp) "protocol-classes" "regions"
                                            "graphics" "events" "output" "utils"
                                            "package"))
   (:file "commands" :depends-on (#.(mp) "utils" "input-editing" "views"
                                    "presentation-defs" "presentations"
                                    "protocol-classes" "package"))
   (:file "incremental-redisplay" :depends-on (#.(mp) "regions" "setf-star"
                                                 "output" "utils" "recording"
                                                 "decls" "protocol-classes"
                                                 "package"))
   (:file "frames" :depends-on (#.(mp) "stream-output" "graphics" "recording"
                                  "transforms" "regions" "pointer-tracking"
                                  "incremental-redisplay" "sheets" "events"
                                  "medium" "stream-input" "utils" "output"
                                  "presentation-defs" "protocol-classes" "decls"
                                  "package"))
   (:file "panes" :depends-on (#.(mp) "design" "medium" "encapsulate"
                                 "presentation-defs" "presentations"
                                 "text-selection" "recording"
                                 "incremental-redisplay" "setf-star" "graphics"
                                 "output" "utils" "commands" "regions" "events"
                                 "stream-input" "stream-output" "frames" "sheets"
                                 "input" "repaint" "protocol-classes" "decls"
                                 "package" "X11-colors"))
   (:file "gadgets" :depends-on (#.(mp) "recording" "stream-output"
                                   "pointer-tracking" "frames" "input" "graphics"
                                   "utils" "medium" "regions" "events" "sheets"
                                   "decls" "protocol-classes" "panes" "output"
                                   "package" "X11-colors"))
   (:file "menu" :depends-on (#.(mp) "panes" "decls" "events" "sheets" "regions"
                                "medium" "utils" "output" "gadgets" "package"))
   (:file "table-formatting" :depends-on (#.(mp) "regions" "presentation-defs"
                                            "utils" "recording" "protocol-classes"
                                            "package"))
   (:file "graph-formatting" :depends-on (#.(mp) "regions" "transforms"
                                            "protocol-classes" "utils" "recording"
                                            "package"))
   (:file "bordered-output" :depends-on (#.(mp) "transforms" "recording"
                                           "regions" "utils" "output" "package"))
   (:file "dialog-views" :depends-on (#.(mp) "recording" "bordered-output"
                                        "utils" "presentation-defs"
                                        "presentations" "incremental-redisplay"
                                        "views" "package"))
   (:file "dialog" :depends-on (#.(mp) "bordered-output" "recording" "views"
                                  "table-formatting" "presentation-defs" "utils"
                                  "presentations" "commands" "decls" "encapsulate"
                                  "incremental-redisplay" "package"))
   (:file "builtin-commands" :depends-on (#.(mp) "input-editing" "views"
                                            "presentation-defs" "stream-input"
                                            "presentations" "recording"
                                            "table-formatting" "dialog" "utils"
                                            "commands" "package"))
   (:file "describe" :depends-on (#.(mp) "recording" "table-formatting" "utils"
                                    "package"))
   (:file "menu-choose" :depends-on (#.(mp) "pointer-tracking" "regions"
                                       "stream-output" "frames" "recording"
                                       "presentation-defs" "presentations"
                                       "graphics" "utils" "medium" "package"))

   ;; ex goatee-core
   (:file "Goatee/conditions"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "conditions" :type "lisp")
          :depends-on (#.(mp) "package"))
   (:file "Goatee/dbl-list"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "dbl-list" :type "lisp")
          :depends-on (#.(mp) "package"))
   (:file "Goatee/flexivector"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "flexivector" :type "lisp")
          :depends-on (#.(mp) "Goatee/conditions" "package"))
   (:file "Goatee/buffer"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "buffer" :type "lisp")
          :depends-on (#.(mp) "Goatee/dbl-list" "Goatee/flexivector" "Goatee/conditions"
                         "setf-star" "package"))
   (:file "Goatee/editable-buffer"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "editable-buffer" :type "lisp")
          :depends-on (#.(mp) "Goatee/flexivector" "setf-star" "Goatee/buffer" "package"))
   (:file "Goatee/editable-area"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "editable-area" :type "lisp")
          :depends-on (#.(mp) "Goatee/dbl-list" "package"))
   (:file "Goatee/clim-area"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "clim-area" :type "lisp")
          :depends-on (#.(mp) "utils" "regions" "Goatee/buffer" "recording"
                         "Goatee/editable-area" "setf-star" "protocol-classes"
                         "stream-output" "package"))
   (:file "Goatee/kill-ring"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "kill-ring" :type "lisp")
          :depends-on (#.(mp) "utils" "Goatee/dbl-list" "package"))
   (:file "Goatee/goatee-command"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "goatee-command" :type "lisp")
          :depends-on (#.(mp) "stream-input" "Goatee/kill-ring" "Goatee/buffer"
                         "Goatee/editable-buffer" "Goatee/editable-area" "events"
                         "package"))
   (:file "Goatee/editing-stream"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "editing-stream" :type "lisp")
          :depends-on (#.(mp) "decls" "Goatee/editable-buffer" "utils" "recording"
                         "Goatee/buffer" "stream-output" "package"))
   (:file "Goatee/presentation-history"
          :pathname #.(make-pathname :directory '(:relative "Goatee") :name "presentation-history" :type "lisp")
          :depends-on (#.(mp) "stream-input" "Goatee/goatee-command" "package"))
   ))

;;; CLIM-PostScript is not a backend in the normal sense.
;;; It is an extension (Chap. 35.1 of the spec) and is an
;;; "included" part of McCLIM. Hence the defsystem is here.
(defsystem :clim-postscript
    :depends-on (:clim)
    :components
    ((:module "Backends/PostScript"
              :pathname #.(make-pathname :directory '(:relative "Backends" "PostScript"))
              :components
              ((:file "package")
               (:file "encoding" :depends-on ("package"))
               (:file "paper" :depends-on ("package"))
               (:file "class" :depends-on ("paper" "package"))
               (:file "font" :depends-on ("encoding" "class" "paper" "package"))
               (:file "graphics" :depends-on ("encoding" "paper" "class" "font" "package"))
               (:file "sheet" :depends-on ("paper" "class" "graphics" "package"))
               (:file "afm" :depends-on ("class" "paper" "font" "package"))
               (:file "standard-metrics" :depends-on ("font" "package"))))))

(defsystem :clim-clx
    :depends-on (:clim #+(or sbcl openmcl ecl allegro) :clx)
    :components
    ((:module "Backends/CLX"
              :pathname #.(make-pathname :directory '(:relative "Backends" "CLX"))
              :components
              ((:file "package")
               (:file "image" :depends-on ("package"))
               (:file "keysyms-common" :depends-on ("package"))
               (:file "keysyms" :depends-on ("keysyms-common" "package"))
               (:file "keysymdef" :depends-on ("keysyms-common" "package"))
               (:file "port" :depends-on ("keysyms-common" "keysyms" "package"))
               (:file "medium" :depends-on ("port" "keysyms" "package"))
               (:file "graft" :depends-on ("port" "package"))
               (:file "frame-manager" :depends-on ("medium" "port" "package"))))))

(defsystem :clim-null
    :depends-on (:clim)
    :components
    ((:module "Backends/Null"
	      :pathname #.(make-pathname :directory '(:relative "Backends" "Null"))
	      :components
	      ((:file "package")
	       (:file "port" :depends-on ("package"))
	       (:file "medium" :depends-on ("port" "package"))
	       (:file "graft" :depends-on ("port" "package"))
	       (:file "frame-manager" :depends-on ("medium" "port" "package"))))))

;;; TODO/asf: I don't have the required libs to get :clim-opengl to load. tough.
(clim-defsystem (:clim-opengl :depends-on (:clim))
   "Backends/OpenGL/opengl-x-frame-manager"
   "Backends/OpenGL/opengl-frame-manager"
   "Backends/OpenGL/opengl-x-port-before"
   "Backends/OpenGL/opengl-port"
   "Backends/OpenGL/opengl-x-port-after"
   "Backends/OpenGL/opengl-medium"
   "Backends/OpenGL/opengl-x-graft")

;;; A system that loads the appropriate backend for the current
;;; platform.
(defsystem :clim-looks
    :depends-on (:clim :clim-postscript
                 ;; If we're on an implementation that ships CLX, use
                 ;; it. Same if the user has loaded CLX already.
                 #+(or sbcl scl openmcl ecl clx allegro) :clim-clx
                 #+gl                        :clim-opengl
                 ;; OpenMCL and MCL support the beagle backend (native
                 ;; OS X look&feel on OS X).

                 ;; But until it's ready, it's no use forcing users to
                 ;; cope with possible bugs.
                 ;; #+(or openmcl mcl)          :clim-beagle

		 ;; null backend
		 :clim-null
                 )
    :components ((:file "Looks/pixie"
                        :pathname #.(make-pathname :directory '(:relative "Looks") :name "pixie" :type "lisp"))))

;;; name of :clim-clx-user chosen by mikemac for no good reason
(defsystem :clim-clx-user
    :depends-on (:clim :clim-clx))

;;; CLIM-Examples depends on having at least one backend loaded.
(defsystem :clim-examples
    :depends-on (:clim :clim-looks)
    :components
    ((:module "Examples"
              :components
              ((:file "calculator")
               (:file "colorslider")
	       (:file "menutest") ; extra
               (:file "address-book")
               (:file "traffic-lights")
               (:file "clim-fig")
               (:file "postscript-test")
               (:file "puzzle")
               (:file "transformations-test")
	       (:file "demodemo")
               (:file "stream-test")
               (:file "presentation-test")
               (:file "dragndrop")
               #+clx (:file "gadget-test")
               (:file "accepting-values")
               (:file "method-browser")
	       (:file "dragndrop-translator")))
     (:module "Goatee"
	      :components
	      ((:file "goatee-test")))))

;;; This won't load in SBCL, either. I have really crappy code to
;;; extract dependency information from :serial t ASDF systems, but
;;; this comment is too narrow to contain it.
(clim-defsystem (:scigraph :depends-on (:clim :clim-looks))
  ;; The DWIM part of SCIGRAPH		
  "Apps/Scigraph/dwim/package"
  "Apps/Scigraph/dwim/feature-case"
  "Apps/Scigraph/dwim/macros"
  "Apps/Scigraph/dwim/tv"
  "Apps/Scigraph/dwim/draw"
  "Apps/Scigraph/dwim/present"
  "Apps/Scigraph/dwim/extensions"
  "Apps/Scigraph/dwim/wholine"
  "Apps/Scigraph/dwim/export"
  ;; The Scigraph part
  "Apps/Scigraph/scigraph/package" 
  "Apps/Scigraph/scigraph/copy"
  "Apps/Scigraph/scigraph/dump"
  "Apps/Scigraph/scigraph/duplicate"
  "Apps/Scigraph/scigraph/random"
  "Apps/Scigraph/scigraph/menu-tools"
  "Apps/Scigraph/scigraph/basic-classes"
  "Apps/Scigraph/scigraph/draw"
  "Apps/Scigraph/scigraph/mouse"
  "Apps/Scigraph/scigraph/color"
  "Apps/Scigraph/scigraph/basic-graph"
  "Apps/Scigraph/scigraph/graph-mixins"
  "Apps/Scigraph/scigraph/axis"
  "Apps/Scigraph/scigraph/moving-object"
  "Apps/Scigraph/scigraph/symbol"
  "Apps/Scigraph/scigraph/graph-data"
  "Apps/Scigraph/scigraph/legend"
  "Apps/Scigraph/scigraph/graph-classes"
  "Apps/Scigraph/scigraph/present"
  "Apps/Scigraph/scigraph/annotations"
  "Apps/Scigraph/scigraph/annotated-graph"
  "Apps/Scigraph/scigraph/contour"
  "Apps/Scigraph/scigraph/equation"
  "Apps/Scigraph/scigraph/popup-accept"
  "Apps/Scigraph/scigraph/popup-accept-methods"
  "Apps/Scigraph/scigraph/duplicate-methods"
  "Apps/Scigraph/scigraph/frame"
  "Apps/Scigraph/scigraph/export"
  "Apps/Scigraph/scigraph/demo-frame")

(defsystem :clim-listener
    :depends-on (:clim :clim-looks #+sbcl :sb-posix)
    :components
    ((:file "Experimental/xpm"
            :pathname #.(make-pathname :directory '(:relative "Experimental") :name "xpm" :type "lisp"))
     (:module "Apps/Listener"
              :pathname #.(make-pathname :directory '(:relative "Apps" "Listener"))
              :depends-on ("Experimental/xpm")
              :components
              ((:file "package")
               (:file "util" :depends-on ("package"))
               (:file "icons" :depends-on ("package" "util"))
               (:file "file-types" :depends-on ("package" "icons" "util"))
               (:file "dev-commands" :depends-on ("package" "icons" "file-types" "util"))
               (:file "listener" :depends-on ("package" "file-types" "icons" "dev-commands" "util"))
               #+CMU (:file "cmu-hacks" :depends-on ("package"))))))


;;; The actual McCLIM system that people should to use in their ASDF
;;; package dependency lists.
(defsystem :mcclim
    :depends-on (:clim-looks))

(defmethod perform :after ((op load-op) (c (eql (find-system :clim))))
  (pushnew :clim *features*)
  (pushnew :mcclim *features*))
