r5152: *** empty log message ***
[hyperobject.git] / views.lisp
index 70819fd276faa89a894cb03156d4e386fd4db58a..6776e39e1bc57a8455aa4a7711f09e7a4de281e4 100644 (file)
@@ -7,15 +7,12 @@
 ;;;; Programmer:    Kevin M. Rosenberg
 ;;;; Date Started:  Apr 2000
 ;;;;
-;;;; $Id: views.lisp,v 1.46 2003/05/22 20:40:03 kevin Exp $
+;;;; $Id: views.lisp,v 1.56 2003/06/17 17:50:45 kevin Exp $
 ;;;;
 ;;;; This file is Copyright (c) 2000-2003 by Kevin M. Rosenberg
 ;;;; *************************************************************************
  
-(in-package :hyperobject)
-
-(eval-when (:compile-toplevel :execute)
-  (declaim (optimize (speed 2) (safety 2) (compilation-speed 0) (debug 2))))
+(in-package #:hyperobject)
 
 
 (defclass object-view ()
                   :accessor obj-end-printer)
    (obj-end-indent :initform nil :initarg :obj-end-indent
                   :accessor obj-end-indent)
+   (subobj-start-printer :type (or string function null) :initform nil :initarg :subobj-start-printer
+                    :accessor subobj-start-printer)
+   (subobj-start-indent :initform nil :initarg :subobj-start-indent
+                    :accessor subobj-start-indent)
+   (subobj-end-printer :type (or string function null) :initform nil :initarg :subobj-end-printer
+                  :accessor subobj-end-printer)
+   (subobj-end-indent :initform nil :initarg :subobj-end-indent
+                  :accessor subobj-end-indent)
    (obj-data-indent :initform nil :initarg :obj-data-indent
                    :accessor obj-data-indent)
    (obj-data-printer :type (or function null) :initform nil
    (obj-data-print-code :type (or function null) :initform nil
                  :initarg :obj-data-print-code
                  :accessor obj-data-print-code)
-   (obj-data-end-str :type (or string null) :initform nil
-                       :initarg :obj-data-end-str
-                       :accessor obj-data-end-str)
+   (obj-data-start-printer :type (or function string null) :initform nil
+                    :initarg :obj-data-start-printer
+                    :accessor obj-data-start-printer)
+   (obj-data-end-printer :type (or string null) :initform nil
+                       :initarg :obj-data-end-printer
+                       :accessor obj-data-end-printer)
+   (indenter :type (or function null) :initform nil
+            :accessor indenter
+            :documentation "Function that performs hierarchical indenting")
    (link-slots :type list :initform nil
               :documentation "List of slot names that have hyperlinks"
               :accessor link-slots)
-   (link-page-name :type (or string null) :initform nil :initarg :link-page-name
-                  :accessor link-page-name)
+   (link-page :type (or string null) :initform nil
+                     :initarg :link-page
+                     :accessor link-page)
    (link-href-start :type (or string null) :initform nil :initarg :link-href-start
                    :accessor link-href-start)
    (link-href-end :type (or string null) :initform nil :initarg :link-href-end
                  :accessor link-href-end)
    (link-ampersand :type (or string null) :initform nil :initarg :link-ampersand
                   :accessor link-ampersand))
-  (:default-initargs :link-page-name "disp-func1")
+  (:default-initargs :link-page "disp-func1")
   (:documentation "View class for a hyperobject"))
 
 
                                 :category :compact-text)))
        view))
     ((consp view-def)
-     (eval `(make-instance ,view-def)))
+     (apply #'make-instance 'object-view view-def))
     (t
      (error "Invalid parameter to make-object-view: ~S" view-def))))
 
   (let* ((slot-data (slot-value obj name))
         (fmt-data (if formatter
                       (funcall formatter slot-data)
-                  slot-data))
-        (data (if cdata
-                  (kmrcl:xml-cdata fmt-data)
-                  fmt-data)))
-    (write-simple data strm)))
-
+                      slot-data)))
+    (if cdata
+       (write-xml-cdata fmt-data strm)
+       (write-simple fmt-data strm))))
 
 (defun ppfc-html (title name type formatter cdata print-func)
   (vector-push-extend '(write-string "<span class=\"" s) print-func)
   (vector-push-extend '(write-char #\> s) print-func))
 
 (defun ppfc-html-link-labels (label name type formatter cdata nlink print-func)
-  (vector-push-extend '(write-string "<label>" s) print-func)
+  (vector-push-extend '(write-string "<span class=\"label\">" s) print-func)
   (vector-push-extend `(write-string ,label s) print-func)
-  (vector-push-extend '(write-string "</label> " s) print-func)
+  (vector-push-extend '(write-string "</span> " s) print-func)
   (ppfc-html-link name type formatter cdata nlink print-func))
 
 (defun push-print-fun-code (category slot nlink print-func)
   (let* ((formatter (esd-print-formatter slot))
         (name (slot-definition-name slot))
-        (namestr-lower (string-downcase (symbol-name name)))
-        (xml-namestr (escape-xml-string namestr-lower))
-        (xml-tag (escape-xml-string namestr-lower))
+        (user-name (esd-user-name slot))
+        (xml-user-name (escape-xml-string user-name))
+        (xml-tag (escape-xml-string user-name))
         (type (slot-value slot 'type))
         (cdata (not (null
                      (and (in category :xml :xhtml :xml-link :xhtml-link
        (vector-push-extend
        `(write-ho-value x ',name ',type ',formatter ,cdata s) print-func))
       (:compact-text-labels
-       (vector-push-extend `(write-string ,namestr-lower s) print-func)
+       (vector-push-extend `(write-string ,user-name s) print-func)
        (vector-push-extend '(write-char #\space s) print-func)
        (vector-push-extend
        `(write-ho-value x ',name ',type ',formatter ,cdata s) print-func))
       ((or :html :xhtml)
-       (ppfc-html namestr-lower name type formatter cdata print-func))
+       (ppfc-html user-name name type formatter cdata print-func))
       (:xml
        (ppfc-xml xml-tag name type formatter cdata print-func))
       (:html-labels
-       (ppfc-html-labels namestr-lower name type formatter cdata print-func))
+       (ppfc-html-labels user-name name type formatter cdata print-func))
       (:xhtml-labels
-       (ppfc-xhtml-labels xml-namestr namestr-lower name type formatter cdata print-func))
+       (ppfc-xhtml-labels xml-user-name user-name name type formatter cdata print-func))
       (:xml-labels
-       (ppfc-xml-labels xml-namestr xml-tag name type formatter cdata print-func))
+       (ppfc-xml-labels xml-user-name xml-tag name type formatter cdata print-func))
       ((or :html-link :xhtml-link)
        (if hyperlink
           (ppfc-html-link name type formatter cdata nlink print-func)
-          (ppfc-html namestr-lower name type formatter cdata print-func)))
+          (ppfc-html user-name name type formatter cdata print-func)))
       ((or :xml-link :ie-xml-link)
        (if hyperlink
           (ppfc-html-link name type formatter cdata nlink print-func)
           (ppfc-xml xml-tag name type formatter cdata print-func)))
       (:html-link-labels
        (if hyperlink
-          (ppfc-html-link-labels namestr-lower name type formatter cdata nlink
+          (ppfc-html-link-labels user-name name type formatter cdata nlink
                                  print-func)
-          (ppfc-html-labels namestr-lower name type formatter cdata print-func)))
+          (ppfc-html-labels user-name name type formatter cdata print-func)))
       (:xhtml-link-labels
        (if hyperlink
-          (ppfc-html-link-labels xml-namestr name type formatter cdata nlink
+          (ppfc-html-link-labels xml-user-name name type formatter cdata nlink
                                  print-func)
-          (ppfc-xhtml-labels xml-tag namestr-lower name type formatter cdata
+          (ppfc-xhtml-labels xml-tag user-name name type formatter cdata
                              print-func)))
       ((or :xml-link-labels :ie-xml-link-labels)
        (if hyperlink
-          (ppfc-html-link-labels xml-namestr name type formatter cdata nlink
+          (ppfc-html-link-labels xml-user-name name type formatter cdata nlink
                                  print-func)
-          (ppfc-xml-labels xml-tag namestr-lower name type formatter cdata
+          (ppfc-xml-labels xml-tag user-name name type formatter cdata
                            print-func))))))
 
 
       (when (and (view-has-links-p view) (esd-hyperlink slot))
        (push (slot-definition-name slot) links)))
 
-    (when (plusp (length print-func))
-      (setf (obj-data-print-code view) `(lambda (x s links)
-                                        (declare (ignorable links))
-                                        ,@(map 'list #'identity print-func)))
-      (setf (obj-data-printer view)
-           (compile nil (eval (obj-data-print-code view)))))
+    (vector-push-extend 'x print-func) ;; return object
+    (setf (obj-data-print-code view) `(lambda (x s links)
+                                      (declare (ignorable s links))
+                                      ,@(map 'list #'identity print-func)))
+    (setf (obj-data-printer view)
+         (compile nil (eval (obj-data-print-code view))))
     
     (setf (link-slots view) (nreverse links)))
 
   (case (category view)
     ((or :compact-text :compact-text-labels)
      (initialize-text-view view))
-    ((or :html :xhtml :html-labels :xhtml-labels)
+    ((or :html :html-labels)
      (initialize-html-view view))
+    ((or :xhtml :xhtml-labels)
+     (initialize-xhtml-view view))
     ((or :xml :xml-labels)
      (initialize-xml-view view))
     ((or :html-link :html-link-labels)
      (setf (link-href-end view) "a")
      (setf (link-ampersand view) "&"))
     ((or :xhtml-link :xhtml-link-labels)
-     (initialize-html-view view)
+     (initialize-xhtml-view view)
      (setf (link-href-start view) "a href=")
      (setf (link-href-end view) "a")
      (setf (link-ampersand view) "&amp;"))
 (defun initialize-text-view (view)
   (setf (list-start-printer view)
        (compile nil
-                (eval '(lambda (obj nitems strm)
+                (eval '(lambda (obj nitems indent strm)
                         (write-user-name-maybe-plural obj nitems strm)
                         (write-char #\: strm)
                         (write-char #\Newline strm)))))
   (setf (list-start-indent view) t)
   (setf (obj-data-indent view) t)
-  (setf (obj-data-end-str view) +newline-string+))
+  (setf (obj-data-end-printer view) +newline-string+)
+  (setf (indenter view) #'indent-spaces))
 
-(defun html-list-start-func (obj nitems strm)
-  (write-string "<p><b>" strm)
+(defun html-list-start-func (obj nitems indent strm)
+  (write-string "<div class=\"ho-username\">" strm)
   (write-user-name-maybe-plural obj nitems strm)
-  (write-string ":</b></p><div class=\"" strm)
-  (write-string (class-name-of obj) strm)
-  (write-string "\"><ul>" strm)
+  (write-string "</div>" strm)
+  (write-char #\newline strm)
+  (write-string "<ul>" strm)
   (write-char #\newline strm))
 
 (defun initialize-html-view (view)
   (initialize-text-view view)
+  (setf (indenter view) #'indent-html-spaces)
   (setf (file-start-str view) (format nil "<html><body>~%"))
   (setf (file-end-str view) (format nil "</body><html>~%"))
   (setf (list-start-indent view) t)
   (setf (list-start-printer view) #'html-list-start-func)
-  (setf (list-end-printer view) (format nil "</ul></div>~%"))
+  (setf (list-end-printer view) (format nil "</ul>~%"))
   (setf (list-end-indent view) t)
-  (setf (obj-start-indent view) t)
+  (setf (obj-start-indent view) nil)
   (setf (obj-start-printer view) "<li>")
-  (setf (obj-end-indent view)  t)
+  (setf (obj-end-indent view)  nil)
   (setf (obj-end-printer view)  (format nil "</li>~%"))
+  (setf (obj-data-end-printer view) nil)
   (setf (obj-data-indent view) nil))
 
+(defun xhtml-list-start-func (obj nitems indent strm)
+  (write-string "<div class=\"ho-username\">" strm)
+  (indent-html-spaces indent strm)
+  (write-user-name-maybe-plural obj nitems strm)
+  (write-string "</div>" strm)
+  (write-char #\newline strm))
+
 (defun initialize-xhtml-view (view)
   (initialize-text-view view)
+  (setf (indenter view) #'indent-html-spaces)
   (setf (file-start-str view) (format nil "<html><body>~%"))
   (setf (file-end-str view) (format nil "</body><html>~%"))
-  (setf (list-start-indent view) t)
-  (setf (list-start-printer view) #'html-list-start-func)
-  (setf (list-end-printer view) (format nil "</ul></div>~%"))
-  (setf (list-end-indent view) t)
-  (setf (obj-start-indent view) t)
-  (setf (obj-start-printer view) "<li>")
-  (setf (obj-end-indent view)  t)
-  (setf (obj-end-printer view) (format nil "</li>~%"))
-  (setf (obj-data-indent view) nil))
+  (setf (list-start-indent view) nil)
+  (setf (list-start-printer view) #'xhtml-list-start-func)
+  (setf (list-end-printer view) (format nil "~%"))
+  (setf (list-end-indent view) nil)
+  (setf (obj-start-indent view) nil)
+  (setf (obj-start-printer view) nil)
+  (setf (obj-end-printer view) (format nil "</div>~%"))
+  (setf (obj-data-start-printer view) "<div>")
+  (setf (obj-data-end-printer view) nil)
+  (setf (obj-end-indent view)  nil)
+  (setf (obj-data-indent view) t))
 
 (defun xmlformat-list-end-func (x strm)
   (write-string "</" strm)
   (write-string ">" strm)
   (write-char #\newline strm))
 
-(defun xmlformat-list-start-func (x nitems strm)
+(defun xmlformat-list-start-func (x nitems indent strm)
   (write-char #\< strm)
   (write-string (class-name-of x) strm)
   (write-string "list><title>" strm)
   (setf (list-end-printer view) #'xmlformat-list-end-func)
   (setf (obj-start-printer view) (format nil "<~(~a~)>" (object-class-name view)))
   (setf (obj-start-indent view) t)
-  (setf (obj-end-printer view) (format nil "</~(~a~)>~%" (object-class-name view)))
-  (setf (obj-end-indent view) nil)
+  (setf (subobj-end-printer view) (format nil "</~(~a~)>~%" (object-class-name view)))
+  (setf (subobj-end-indent view) nil)
   (setf (obj-data-indent view) nil))
 
 
 
 (defun fmt-list-start (obj view strm indent num-items)
   (when (list-start-indent view)
-    (indent-spaces indent strm))
+    (awhen (indenter view)
+          (funcall it indent strm)))
   (awhen (list-start-printer view)
         (if (stringp it)
             (write-string it strm)
-            (funcall it obj num-items strm))))
+            (funcall it obj num-items indent strm))))
 
 (defun fmt-list-end (obj view strm indent num-items)
   (declare (ignore num-items))
   (when (list-end-indent view)
-      (indent-spaces indent strm))
+    (awhen (indenter view)
+          (funcall it indent strm)))
   (awhen (list-end-printer view)
         (if (stringp it)
             (write-string it strm)
 
 ;;; Object Start and Ends
 
+
 (defun fmt-obj-start (obj view strm indent)
   (when (obj-start-indent view)
-    (indent-spaces indent strm))
+    (awhen (indenter view)
+          (funcall it indent strm)))
   (awhen (obj-start-printer view)
         (if (stringp it)
             (write-string it strm)
 
 (defun fmt-obj-end (obj view strm indent)
   (when (obj-end-indent view)
-    (indent-spaces indent strm))
+    (awhen (indenter view)
+          (funcall it indent strm))) 
   (awhen (obj-end-printer view)
         (if (stringp it)
             (write-string it strm)
             (funcall it obj strm))))
+
+(defun fmt-subobj-start (obj view strm indent)
+  (when (subobj-start-indent view)
+    (awhen (indenter view)
+          (funcall it indent strm)))
+  (awhen (subobj-start-printer view)
+        (if (stringp it)
+            (write-string it strm)
+            (funcall it obj strm))))
+
+(defun fmt-subobj-end (obj view strm indent)
+  (when (subobj-end-indent view)
+    (awhen (indenter view)
+          (funcall it indent strm))) 
+  (awhen (subobj-end-printer view)
+        (if (stringp it)
+            (write-string it strm)
+            (funcall it obj strm))))
   
 ;;; Object Data 
 
 
-(defun make-link-start (view fieldfunc fieldvalue refvars)
+(defun make-link-start (view fieldfunc fieldvalue refvars link-printer)
   (with-output-to-string (s)
     (write-string (link-href-start view) s)
     (write-char #\" s)
-    (write-string (make-url (link-page-name view)) s)
-    (write-string "?func=" s)
-    (write-simple fieldfunc s)
-    (write-string (link-ampersand view) s)
-    (write-string "key=" s)
-    (write-simple fieldvalue s)
-    (dolist (var refvars)
-      (write-string (link-ampersand view) s)
-      (write-simple (car var) s)
-      (write-char #\= s)
-      (write-simple (cdr var) s))
+    (let ((link-page (link-page view)))
+      (cond
+       ((null link-printer)
+        (write-string (make-url link-page) s)
+        (write-string "?func=" s)
+        (write-simple fieldfunc s)
+        (write-string (link-ampersand view) s)
+        (write-string "key=" s)
+        (write-simple fieldvalue s)
+        (dolist (var refvars)
+          (write-string (link-ampersand view) s)
+          (write-simple (car var) s)
+          (write-char #\= s)
+          (write-simple (cdr var) s)))
+       (link-printer
+        (funcall link-printer link-page fieldfunc fieldvalue refvars s))))
     (write-char #\" s)))
   
 (defun make-link-end (obj view fieldname)
   (declare (ignore obj fieldname))
   (link-href-end view))
 
-(defun fmt-obj-data (obj view strm indent refvars)
+(defun fmt-obj-data (obj view strm indent refvars link-printer)
+  (awhen (obj-data-start-printer view)
+        (if (stringp it)
+            (write-string it strm)
+            (funcall it obj strm)))
   (when (obj-data-indent view)
-    (indent-spaces indent strm))
+    (awhen (indenter view)
+          (funcall it indent strm)))
   (if (link-slots view)
-      (fmt-obj-data-with-link obj view strm refvars)
+      (fmt-obj-data-with-link obj view strm refvars link-printer)
       (fmt-obj-data-plain obj view strm))
-  (awhen (obj-data-end-str view)
-        (write-string it strm)))
+  (awhen (obj-data-end-printer view)
+        (if (stringp it)
+            (write-string it strm)
+            (funcall it obj strm))))
 
 (defun fmt-obj-data-plain (obj view strm)
   (awhen (obj-data-printer view)
         (funcall it obj strm nil)))
 
-(defun fmt-obj-data-with-link (obj view strm refvars)
+(defun fmt-obj-data-with-link (obj view strm refvars link-printer)
   (let ((refvalues '()))
+    (declare (dynamic-extent refvalues))
     ;; make list of hyperlink link fields for printing to refstr template
     (dolist (name (link-slots view))
       (awhen (find name (hyperobject-class-hyperlinks obj) :key #'name)
             (push (make-link-start view (lookup it) (slot-value obj name)
-                                   (append (link-parameters it) refvars))
+                                   (append (link-parameters it) refvars)
+                                   link-printer)
                   refvalues)
             (push (make-link-end obj view name) refvalues)))
     (funcall (obj-data-printer view) obj strm (nreverse refvalues))))
   objs)
 
 (defun view-hyperobject (objs view category strm &optional (indent 0) filter
-                        subobjects refvars)
+                        subobjects refvars link-printer)
   "Display a single or list of hyperobject-class instances and their subobjects"
-  (declare (fixnum indent))
   (let-when (objlist (mklist objs))
     (let ((nobjs (length objlist))
          (*print-pretty* nil)
       (dolist (obj objlist)
         (unless (and filter (not (funcall filter obj)))
           (fmt-obj-start obj view strm indent)
-          (fmt-obj-data obj view strm (1+ indent) refvars)
+          (fmt-obj-data obj view strm (1+ indent) refvars link-printer)
+          (fmt-obj-end obj view strm indent)
+          (fmt-subobj-start obj view strm indent)
           (when (and subobjects (hyperobject-class-subobjects obj))
            (dolist (subobj (hyperobject-class-subobjects obj))
              (aif (slot-value obj (name-slot subobj))
-                  (view-hyperobject it (get-category-view (car (mklist it)) category)
+                  (view-hyperobject it
+                                    (get-category-view (car (mklist it))
+                                                       category)
                                     category strm (1+ indent) filter
-                                    subobjects refvars))))
-         (fmt-obj-end obj view strm indent)))
+                                    subobjects refvars link-printer))))
+         (fmt-subobj-end obj view strm indent)))
       (fmt-list-end (car objlist) view strm indent nobjs)))
   objs)
 
 
 (defun view (objs &key (stream *standard-output*) category view
-            filter subobjects refvars file-wrapper)
-  "EXPORTED Function: prints hyperobject-class objects. Simplies call to view-hyperobject"
+            filter subobjects refvars file-wrapper link-printer)
+  "EXPORTED Function: prints hyperobject-class objects. Calls view-hyperobject"
   (let-when (objlist (mklist objs))
     (when category
       (setq view (get-category-view (car objlist) category)))
       (setq view (default-view (class-of (car objlist)))))
     (when file-wrapper
       (fmt-file-start view stream))
-    (view-hyperobject objlist view category stream 0 filter subobjects refvars)
+    (view-hyperobject objlist view category stream 0 filter subobjects refvars
+                     link-printer)
     (when file-wrapper
       (fmt-file-end view stream)))
   objs)