fixes, enhancements, and more update-to-latest-ucw stuff. minor, all of it.
authorDrew Crampsie <drewc@tech.coop>
Tue, 13 Dec 2005 09:44:28 +0000 (01:44 -0800)
committerDrew Crampsie <drewc@tech.coop>
Tue, 13 Dec 2005 09:44:28 +0000 (01:44 -0800)
darcs-hash:20051213094428-5417e-eed38060c4605447ce9c2aba300bd48251fddcdc.gz

src/mewa.lisp
src/slot-presentations.lisp
src/slot-presentations/date.lisp
src/static-presentations.lisp

index 203fdf3..1dea1fe 100644 (file)
@@ -57,9 +57,11 @@ Attributes are the metadata used to display, validate, and otherwise manipulate
   (setf (attribute-map occurence) (make-hash-table)))
 
 (defgeneric find-occurence (name)
   (setf (attribute-map occurence) (make-hash-table)))
 
 (defgeneric find-occurence (name)
+  (:method (thing)
+    nil)
   (:method ((name symbol))
     (find-or-create-occurence name))
   (:method ((name symbol))
     (find-or-create-occurence name))
-  (:method (instance)
+  (:method ((instance standard-object))
     (find-or-create-occurence (class-name (class-of instance)))))
 
 
     (find-or-create-occurence (class-name (class-of instance)))))
 
 
index 02fb818..89492aa 100644 (file)
@@ -300,7 +300,8 @@ Calendar.setup({
                       
 
 (defmethod get-foreign-instances ((slot has-many-slot-presentation) instance)
                       
 
 (defmethod get-foreign-instances ((slot has-many-slot-presentation) instance)
-  (slot-value instance (slot-name slot)))
+  (sort (slot-value instance (slot-name slot)) #'<  
+       :key #'(lambda (x) (funcall (car (list-keys instance)) x))))
 
 (defmethod lol::presentation-slot-value ((slot has-many-slot-presentation) instance)
   (get-foreign-instances slot instance))
 
 (defmethod lol::presentation-slot-value ((slot has-many-slot-presentation) instance)
   (get-foreign-instances slot instance))
index 04d93ff..161b31c 100644 (file)
 
 
 
 
 
 
-(defcomponent %integer-range-field (ucw::integer-range-field)
+(defcomponent %integer-range-field (integer-range-field)
   ())
 
 (defmethod (setf lisp-value) :after (value (self %integer-range-field))
   ())
   ())
 
 (defmethod (setf lisp-value) :after (value (self %integer-range-field))
   ())
-  
-  
+(defclass date-field (form-element)
+  ((day :component (integer-range-field :min-value 1 :max-value 31))
+   (month :component (integer-range-field :min-value 1 :max-value 12))
+   (year :component integer-range-field))
+  (:metaclass standard-component-class))
+
+(defmethod shared-initialize :after ((field date-field) slot-names
+                                     &key (year-min 1960) (year-max 2010))
+  (declare (ignore slot-names))
+  (setf (min-value (slot-value field 'year)) year-min
+        (max-value (slot-value field 'year)) year-max
+        (max-value (slot-value field 'day)) 31
+        (max-value (slot-value field 'month)) 12))
+
+(defmethod read-client-value ((date date-field))
+  (with-slots (year month day)
+      date
+    (read-client-value year)
+    (read-client-value month)
+    (read-client-value day)
+    (setf (lisp-value date) (encode-universal-time 0 0 0
+                                                   (lisp-value day)
+                                                   (lisp-value month)
+                                                   (lisp-value year)))))
 
 
-(defclass %date-field (ucw::date-field)
+(defclass %date-field (date-field)
   ((day :component (%integer-range-field :min-value 1 :max-value 31))
    (month :component (%integer-range-field :min-value 1 :max-value 12))
    (year :component (%integer-range-field :min-value 2005 :max-value 2015) ))
   ((day :component (%integer-range-field :min-value 1 :max-value 31))
    (month :component (%integer-range-field :min-value 1 :max-value 12))
    (year :component (%integer-range-field :min-value 2005 :max-value 2015) ))
       "/"
       (<ucw:render-component :component year)))
 
       "/"
       (<ucw:render-component :component year)))
 
+
+
+(defconstant +uninitialized+ '+uninitialized+
+  "The value used in UCW form elements to specify that there is no value.
+
+This obviously implies that you can't have a form element whose
+real value is +uninitialized+, since +uninitialized+ is a ucw
+internal symbol this shouldn't be a problem.")
+
+(defclass form-element (widget-component)
+  ((client-value :accessor client-value :initform ""
+                :initarg :client-value
+                 :documentation "Whetever the client's browse sent for this form element."
+                 :backtrack t)
+   (lisp-value :accessor lisp-value :initform +uninitialized+
+               :initarg :lisp-value
+               :documentation "The current lisp object in this form element."
+               :backtrack t))
+  (:metaclass standard-component-class)
+  (:documentation "A single value in a form.
+
+A form-element is, simply put, a wrapper for a value in an html
+form."))
+
+(defgeneric read-client-value (element)
+  (:method ((element form-element))
+    (setf (lisp-value element) (client-value element))))
+
+(defclass form-component (widget-component)
+  ()
+  (:metaclass standard-component-class))
+
+;; remeber that actions are just methods
+(defgeneric/cc submit (form))
+
+(defaction submit :before ((f form-component))
+  (iterate
+    (with form-element-class = (find-class 'form-element))
+    (for slot in (mopp:class-slots (class-of f)))
+    (for slot-name = (mopp:slot-definition-name slot))
+    (when (and (slot-boundp f slot-name)
+               (subtypep (class-of (slot-value f slot-name)) form-element-class))
+      (read-client-value (slot-value f slot-name)))))
+
+(defaction submit ((f form-component)) t)
+
+
+(defclass select-field (form-element)
+  ((options :accessor options :initform '() :initarg :options)
+   (key :accessor key :initform #'identity :initarg :key)
+   (test :accessor test :initform #'eql :initarg :test)
+   (option-map :accessor option-map :initform (make-array 10 :adjustable t :fill-pointer 0))
+   (option-writer :accessor option-writer :initform #'princ-to-string))
+  (:metaclass standard-component-class))
+
+(defmethod render-option ((select select-field) (object t))
+  (<:as-html (funcall (option-writer select) object)))
+
+(defmethod render ( (select select-field))
+  (setf (fill-pointer (option-map select)) 0)
+  (<:select :name (make-new-callback (context.current-frame *context*)
+                                     (lambda (v) (setf (client-value select) v)))
+    (iterate
+      (for o in (options select))
+      (for index upfrom 0)
+      (vector-push-extend o (option-map select))
+      (<:option :value index
+                :selected (funcall (test select)
+                                   (funcall (key select) o)
+                                   (funcall (key select) (lisp-value select))) 
+        (render-option res select o)))))
+
+(defmethod read-client-value ((select select-field))
+  (with-slots (lisp-value option-map client-value)
+      select
+    (setf lisp-value (aref option-map (parse-integer client-value)))))
+
+;;;; Numbers from text inputs
+
+(defclass number-field (form-element)
+  ((min-value :accessor min-value :initform nil :initarg :min-value)
+   (max-value :accessor max-value :initform nil :initarg :max-value)
+   (size :accessor size :initarg :size :initform 0)
+   (maxlength :accessor maxlength :initarg :maxlength :initform 20))
+  (:metaclass standard-component-class))
+
+(defmethod validate-form-element ((number number-field))
+  (with-slots (min-value max-value lisp-value)
+      number
+    (if (eql +uninitialized+ lisp-value)
+       nil
+       (if (numberp lisp-value)
+           (cond
+             ((and min-value max-value)
+              (< min-value lisp-value max-value))
+             (min-value (< min-value lisp-value))
+             (max-value (< lisp-value max-value))
+             (t lisp-value))
+           nil))))
+
+(defmethod read-client-value :around ((number number-field))
+  (unless (or (null (client-value number))
+              (string= "" (client-value number)))
+    (ignore-errors ; returns NIL in case of SIMPLE-PARSE-ERROR
+      (call-next-method))))
+
+(defmethod render ( (n number-field))
+  (<ucw:input :type "text" :accessor (client-value n)
+              :size (size n)
+             :value (if (eql +uninitialized+ (lisp-value n))
+                        ""
+                        (lisp-value n))
+             :maxlength (maxlength n)))
+
+(defclass decimal-field (number-field)
+  ((precision :accessor precision :initarg :precision :initform nil
+              :documentation "Number of significant digits."))
+  (:metaclass standard-component-class))
+
+(defmethod read-client-value ((decimal number-field))
+  (setf (lisp-value decimal) (parse-float (client-value decimal))))
+
+(defclass integer-field (number-field)
+  ()
+  (:metaclass standard-component-class))
+
+(defmethod read-client-value ((integer integer-field))    
+  (setf (lisp-value integer) (parse-integer (client-value integer))))
+
+(defclass integer-range-field (integer-field)
+  ()
+  (:metaclass standard-component-class)
+  (:default-initargs :min-value 1 :max-value 5))
+
+(defmethod shared-initialize :after ((field integer-range-field) slot-names
+                                     &rest initargs)
+  (declare (ignore slot-names initargs))
+  (setf (lisp-value field) (min-value field)))
+
+(defmethod render ( (range integer-range-field))
+  (<:select :name (ucw::make-new-callback 
+                                     (lambda (v) (setf (client-value range) v)))
+    (iterate
+      (for value from (min-value range) to (max-value range))
+      (<:option :value value :selected (= value (lisp-value range))
+                (<:as-html value)))))
\ No newline at end of file
index bb5cf0d..5958f3b 100644 (file)
@@ -579,7 +579,7 @@ This method is also used by relation-slot-presentations for the same reason."))
 ;;;; Currency (double precision reals)
 
 (defslot-presentation currency-slot-presentation (real-slot-presentation)
 ;;;; Currency (double precision reals)
 
 (defslot-presentation currency-slot-presentation (real-slot-presentation)
-  ()
+  ((as-money-p :accessor as-money-p :initarg :as-money-p :initform nil))
   (:type-name currency))
 
 (defmethod (setf presentation-slot-value) ((value string) (c currency-slot-presentation) instance)
   (:type-name currency))
 
 (defmethod (setf presentation-slot-value) ((value string) (c currency-slot-presentation) instance)
@@ -593,7 +593,10 @@ This method is also used by relation-slot-presentations for the same reason."))
   (if (editablep currency)
       (<ucw:input :type "text" :size 10
                  :accessor (presentation-slot-value currency instance))
   (if (editablep currency)
       (<ucw:input :type "text" :size 10
                  :accessor (presentation-slot-value currency instance))
-      (<:as-html (presentation-slot-value currency instance))))
+      (<:as-html (format nil (if (as-money-p currency)
+                                "$~$"
+                                "~D")
+                        (presentation-slot-value currency instance)) )))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;; dates and times
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;; dates and times