r5152: *** empty log message ***
[hyperobject.git] / views.lisp
index 0aeafe1bda4b2401a7d617dcea6c321a66bb246d..6776e39e1bc57a8455aa4a7711f09e7a4de281e4 100644 (file)
@@ -7,15 +7,12 @@
 ;;;; Programmer:    Kevin M. Rosenberg
 ;;;; Date Started:  Apr 2000
 ;;;;
-;;;; $Id: views.lisp,v 1.48 2003/05/26 21:43:05 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"))
 
 
   (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)
 
     (vector-push-extend 'x print-func) ;; return object
     (setf (obj-data-print-code view) `(lambda (x s links)
-                                      (declare (ignorable links))
+                                      (declare (ignorable links))
                                       ,@(map 'list #'identity print-func)))
     (setf (obj-data-printer view)
          (compile nil (eval (obj-data-print-code view))))
   (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)