r3587: *** empty log message ***
[hyperobject.git] / views.lisp
index cf92ed09dec131e097849e21fc964bb0d53c4ab6..a80c1e9a58051331c17fae8530096be424fd0241 100644 (file)
@@ -7,7 +7,7 @@
 ;;;; Programmer:    Kevin M. Rosenberg
 ;;;; Date Started:  Apr 2000
 ;;;;
-;;;; $Id: views.lisp,v 1.1 2002/11/25 04:47:23 kevin Exp $
+;;;; $Id: views.lisp,v 1.11 2002/12/09 10:39:38 kevin Exp $
 ;;;;
 ;;;; This file is Copyright (c) 2000-2002 by Kevin M. Rosenberg
 ;;;;
 (in-package :hyperobject)
 
 (eval-when (:compile-toplevel :execute)
-  (declaim (optimize (speed 3) (safety 1) (compilation-speed 0) (debug 3))))
+  (declaim (optimize (speed 2) (safety 2) (compilation-speed 0) (debug 2))))
+
+
+;;;; *************************************************************************
+;;;;  Metaclass Intialization
+;;;; *************************************************************************
+
+(defun finalize-hyperlinks (cl)
+  (let ((hyperlinks '()))
+    (dolist (esd (class-slots cl))
+      (awhen (slot-value esd 'hyperlink)
+        (push
+        (make-instance 'hyperlink
+                       :name (slot-definition-name esd)
+                       :lookup it
+                       :link-parameters (slot-value esd 'hyperlink-parameters))
+        hyperlinks)))
+    (setf (slot-value cl 'hyperlinks) hyperlinks)))
+
+
+(defun finalize-views (cl)
+  "Calculate all view slots for a hyperobject class"
+  (let ((fmtstr-text "")
+       (fmtstr-html "")
+       (fmtstr-xml "")
+       (fmtstr-text-labels "")
+       (fmtstr-html-labels "")
+       (fmtstr-xml-labels "")
+       (fmtstr-html-ref "")
+       (fmtstr-xml-ref "")
+       (fmtstr-html-ref-labels "")
+       (fmtstr-xml-ref-labels "")
+       (first-field t)
+       (value-func '())
+       (xmlvalue-func '())
+       (classname (class-name cl))
+       (package (symbol-package (class-name cl)))
+       (hyperlinks nil))
+    (declare (ignore classname))
+    (check-type (slot-value cl 'print-slots) list)
+    (dolist (slot-name (slot-value cl 'print-slots))
+      (let ((slot (find-slot-by-name cl slot-name)))
+       (unless slot
+         (error "Slot ~A is not found in class ~S" slot-name cl))
+       (let ((name (slot-definition-name slot))
+             (namestr (symbol-name (slot-definition-name slot)))
+             (namestr-lower (string-downcase (symbol-name (slot-definition-name slot))))
+             (type (slot-value slot 'ho-type))
+             (print-formatter (slot-value slot 'print-formatter))
+             (value-fmt "~a")
+             (plain-value-func nil)
+             html-str xml-str html-label-str xml-label-str)
+         
+         (when (or (eql type :integer) (eql type :fixnum))
+           (setq value-fmt "~d"))
+         
+         (when (eql type :boolean)
+           (setq value-fmt "~a"))
+         
+         (if first-field
+             (setq first-field nil)
+             (progn
+               (string-append fmtstr-text " ")
+               (string-append fmtstr-html " ")
+               (string-append fmtstr-xml " ")
+               (string-append fmtstr-text-labels " ")
+               (string-append fmtstr-html-labels " ")
+               (string-append fmtstr-xml-labels " ")
+               (string-append fmtstr-html-ref " ")
+               (string-append fmtstr-xml-ref " ")
+               (string-append fmtstr-html-ref-labels " ")
+               (string-append fmtstr-xml-ref-labels " ")))
+         
+         (setq html-str (concatenate 'string "<span class=\"" namestr-lower "\">" value-fmt "</span>"))
+         (setq xml-str (concatenate 'string "<" namestr-lower ">" value-fmt "</" namestr-lower ">"))
+         (setq html-label-str (concatenate 'string "<span class=\"label\">" namestr-lower "</span> <span class=\"" namestr-lower "\">" value-fmt "</span>"))
+         (setq xml-label-str (concatenate 'string "<label>" namestr-lower "</label> <" namestr-lower ">" value-fmt "</" namestr-lower ">"))
+         
+         (string-append fmtstr-text value-fmt)
+         (string-append fmtstr-html html-str)
+         (string-append fmtstr-xml xml-str)
+         (string-append fmtstr-text-labels namestr-lower " " value-fmt)
+         (string-append fmtstr-html-labels html-label-str)
+         (string-append fmtstr-xml-labels xml-label-str)
+         
+         (if (slot-value slot 'hyperlink)
+             (progn
+               (string-append fmtstr-html-ref "<~~a>" value-fmt "</~~a>")
+               (string-append fmtstr-xml-ref "<~~a>" value-fmt "</~~a>")
+               (string-append fmtstr-html-ref-labels "<span class=\"label\">" namestr-lower "</span> <~~a>" value-fmt "</~~a>")
+               (string-append fmtstr-xml-ref-labels "<label>" namestr-lower "</label> <~~a>" value-fmt "</~~a>")
+               (push (make-instance 'hyperlink :name name
+                                    :lookup (slot-value slot 'hyperlink))
+                     hyperlinks))
+             (progn
+               (string-append fmtstr-html-ref html-str)
+               (string-append fmtstr-xml-ref xml-str)
+               (string-append fmtstr-html-ref-labels html-label-str)
+               (string-append fmtstr-xml-ref-labels xml-label-str)))
+         
+         (if print-formatter
+             (setq plain-value-func 
+                   (list `(,print-formatter (slot-value x ',(intern namestr package)))))
+             (setq plain-value-func 
+                   (list `(slot-value x ',(intern namestr package)))))
+         (setq value-func (append value-func plain-value-func))
+         
+         (if (eql type :cdata)
+             (setq xmlvalue-func (append xmlvalue-func (list `(xml-cdata ,@plain-value-func))))
+             (setq xmlvalue-func (append xmlvalue-func plain-value-func)))
+         )))
+    
+    (setf (slot-value cl 'hyperlinks) hyperlinks)
+    
+    (if value-func
+       (setq value-func `(lambda (x) (values ,@value-func)))
+       (setq value-func `(lambda () (values))))
+    (setq value-func (compile nil (eval value-func)))
+    
+    (if xmlvalue-func
+       (setq xmlvalue-func `(lambda (x) (values ,@xmlvalue-func)))
+       (setq xmlvalue-func `(lambda () (values))))
+    (setq xmlvalue-func (compile nil (eval xmlvalue-func)))
+    
+    (setf (slot-value cl 'fmtstr-text) fmtstr-text)
+    (setf (slot-value cl 'fmtstr-html) fmtstr-html)
+    (setf (slot-value cl 'fmtstr-xml) fmtstr-xml)
+    (setf (slot-value cl 'fmtstr-text-labels) fmtstr-text-labels)
+    (setf (slot-value cl 'fmtstr-html-labels) fmtstr-html-labels)
+    (setf (slot-value cl 'fmtstr-xml-labels) fmtstr-xml-labels)
+    (setf (slot-value cl 'fmtstr-html-ref) fmtstr-html-ref)
+    (setf (slot-value cl 'fmtstr-xml-ref) fmtstr-xml-ref)
+    (setf (slot-value cl 'fmtstr-html-ref-labels) fmtstr-html-ref-labels)
+    (setf (slot-value cl 'fmtstr-xml-ref-labels) fmtstr-xml-ref-labels)
+    (setf (slot-value cl 'value-func) value-func)
+    (setf (slot-value cl 'xmlvalue-func) xmlvalue-func))
+  (values))
+
+
+;;;; *************************************************************************
+;;;;  View Data Format Section
+;;;; *************************************************************************
 
 (defparameter *default-textformat* nil)
 (defparameter *default-htmlformat* nil)
    (obj-data-end-fmtstr :initarg :obj-data-end-fmtstr :reader obj-data-end-fmtstr)
    (obj-data-value-func :initarg :obj-data-value-func :reader obj-data-value-func)
    (link-ref :initarg :link-ref :reader link-ref))
-  (:default-initargs :file-start-str nil :file-end-str nil :list-start-fmtstr nil :list-start-value-func nil
-                    :list-start-indent nil :list-end-fmtstr nil :list-end-value-func nil :list-end-indent nil
-                    :obj-start-fmtstr nil :obj-start-value-func nil :obj-start-indent nil
-                    :obj-end-fmtstr nil :obj-end-value-func nil :obj-end-indent nil
-                    :obj-data-indent nil :obj-data-fmtstr nil :obj-data-fmtstr-labels nil :obj-data-end-fmtstr nil
+  (:default-initargs :file-start-str nil :file-end-str nil
+                    :list-start-fmtstr nil :list-start-value-func nil
+                    :list-start-indent nil :list-end-fmtstr nil
+                    :list-end-value-func nil :list-end-indent nil
+                    :obj-start-fmtstr nil :obj-start-value-func nil
+                    :obj-start-indent nil :obj-end-fmtstr nil
+                    :obj-end-value-func nil :obj-end-indent nil
+                    :obj-data-indent nil :obj-data-fmtstr nil
+                    :obj-data-fmtstr-labels nil :obj-data-end-fmtstr nil
                     :obj-data-value-func nil :link-ref nil)
   (:documentation "Parent for all dataformat objects"))
 
   ())
 
 (defun text-list-start-value-func (obj nitems)
-  (values (hyperobject-class-title obj) nitems))
+  (values (hyperobject-class-user-name obj) nitems))
 
 (defclass textformat (dataformat) 
   ()   
   (string-downcase (class-name (class-of obj))))
 
 (defun htmlformat-list-start-value-func (x nitems) 
-  (values (hyperobject-class-title x) nitems (class-name-of x)))
+  (values (hyperobject-class-user-name x) nitems (class-name-of x)))
 
 (defclass htmlformat (textformat) 
   ()
   (format nil "~alist" (class-name-of x)))
 
 (defun xmlformat-list-start-value-func (x nitems) 
-  (values (format nil "~alist" (class-name-of x)) (hyperobject-class-title x) nitems))
+  (values (format nil "~alist" (class-name-of x)) (hyperobject-class-user-name x) nitems))
 
 (defclass xmlformat (textformat) 
   ()
     :fmtstr-labels nil 
     :page-name "disp-func1" 
     :href-head nil :href-end nil :ampersand nil)
-  (:documentation "Formatting for a linked reference"))
+  (:documentation "Formatting for a linked hyperlink"))
 
 (defclass html-link-ref (link-ref)
   ()
 
 (defgeneric fmt-obj-data-with-ref (obj fmt s label refvars))
 (defmethod fmt-obj-data-with-ref (x (fmt textformat) s label refvars)
-  (let ((refstr (make-ref-data-str x fmt label))
-       (refvalues nil)
-       (field-values 
-        (multiple-value-list
-         (funcall (funcall (obj-data-value-func fmt) x) x))))
-    
-    ;; make list of reference link fields for printing to refstr template
-    (dolist (ref (hyperobject-class-references x))
-      (let ((link-start 
-            (make-link-start x (link-ref fmt) (name ref) (lookup ref)
-                             (nth (position (name ref)
-                                            (hyperobject-class-fields x)
-                                            :key #'(lambda (x)
-                                                     (slot-definition-name x)))
-                                  field-values)  
-                             (append (link-parameters ref) refvars)))
-           (link-end (make-link-end x (link-ref fmt) (name ref))))
-       (push link-start refvalues)
-       (push link-end refvalues)))
+  (let ((refvalues '()))
+    ;; make list of hyperlink link fields for printing to refstr template
+    (dolist (name (hyperobject-class-print-slots x))
+      (let-when (hyperlink (find name (hyperobject-class-hyperlinks x) :key #'name))
+       (push  (make-link-start x (link-ref fmt) name (lookup hyperlink)
+                               (slot-value x name)
+                               (append (link-parameters hyperlink) refvars))
+              refvalues)
+       (push (make-link-end x (link-ref fmt) name) refvalues)))
     (setq refvalues (nreverse refvalues))
-    
-    (apply #'format s refstr refvalues)))
+    (apply #'format s (make-ref-data-str x fmt label) refvalues)))
 
 (defgeneric obj-data (obj))
 (defmethod obj-data (x)
 
 (defgeneric make-ref-data-str (obj fmt &optional label))
 (defmethod make-ref-data-str (x (fmt textformat) &optional (label nil))
-  "Return fmt string for that contains ~a slots for reference link start and end"
+  "Return fmt string for that contains ~a slots for hyperlink link start and end"
   (unless (link-ref fmt)
     (error "fmt does not contain a link-ref"))
   (let ((refstr 
       (dolist (obj objlist)
         (awhen (hyperobject-class-subobjects obj)  ;; access list of functions
           (dolist (child-obj it)   ;; for each child function
-            (awhen (funcall (reader child-obj) obj)
+            (awhen (slot-value obj (name-slot child-obj))
               (load-all-subobjects it))))))
     objs))
 
-(defgeneric print-hyperobject-class (objs fmt strm
+(defgeneric view-hyperobject (objs fmt strm
                                  &optional label english-only-function
                                  indent subobjects refvars))
 
-(defmethod print-hyperobject-class (objs (fmt dataformat) (strm stream) 
+(defmethod view-hyperobject (objs (fmt dataformat) (strm stream) 
                                 &optional (label nil) (indent 0)
                                 (english-only-function nil)
                                 (subobjects nil) (refvars nil))
           (if subobjects
               (awhen (hyperobject-class-subobjects obj)  ;; access list of functions
                         (dolist (child-obj it)   ;; for each child function
-                          (awhen (funcall (reader child-obj) obj) ;; access set of child objects
-                                    (print-hyperobject-class it fmt strm label 
-                                                     (1+ indent) english-only-function
-                                                    subobjects refvars)))))
+                          (awhen (slot-value obj (name-slot child-obj)) ;; access set of child objects
+                                (view-hyperobject it fmt strm label 
+                                                  (1+ indent) english-only-function
+                                                  subobjects refvars)))))
           (fmt-obj-end obj fmt strm indent)))
       (fmt-list-end (car objs) fmt strm indent nobjs))
     t))
 
 
-
-(defun print-hyperobject (objs &key (os *standard-output*) (format :text)
+(defun view (objs &key (os *standard-output*) (format :text)
                      (label nil) (english-only-function nil)
                      (subobjects nil) (file-wrapper t) (refvars nil))
-  "EXPORTED Function: prints hyperobject-class objects. Simplies call to print-hyperobject-class"
+  "EXPORTED Function: prints hyperobject-class objects. Simplies call to view-hyperobject"
   (let ((fmt (make-format-instance format)))
     (if file-wrapper
        (fmt-file-start fmt os))
     (when objs
-      (print-hyperobject-class objs fmt os label 0 english-only-function subobjects refvars))
+      (view-hyperobject objs fmt os label 0 english-only-function subobjects refvars))
     (if file-wrapper
        (fmt-file-end fmt os)))
   objs)
 
+
+;;; Misc formatting
+
+(defun fmt-comma-integer (i)
+  (format nil "~:d" i))
+