--- /dev/null
+(in-package :lisp-on-lines)
+
+(setf (find-class 'simple-attribute nil) nil)
+
+(define-layered-class simple-attribute ()
+ ((%property-access-function
+ :initarg property-access-function)))
+
+(defun ensure-property-access-function (attribute)
+ (if (slot-boundp attribute '%property-access-function)
+ (slot-value attribute '%property-access-function)
+ (let ((fn-name (gensym)))
+ (ensure-layered-function fn-name :lambda-list '() :method-combination '(append))
+ (setf (slot-value attribute '%property-access-function) fn-name))))
+
+(defconstant +property-not-found+ '=lisp-on-lines-property-not-found-indicator=)
+
+(define-layered-method
+ contextl:slot-value-using-layer (class (attribute simple-attribute) slotd reader)
+ (if (or *symbol-access*
+ (eq (slot-definition-name slotd)
+ '%property-access-function)
+ (not (slot-definition-layeredp slotd)))
+ (call-next-method)
+ (let ((value (getf (funcall (ensure-property-access-function attribute))
+ (slot-definition-name slotd)
+ +property-not-found+)))
+ (if (eq value +property-not-found+)
+ (call-next-method)
+ value))))
+
+(defvar *test-attribute-definitions*
+ `((t :label "foo" :value "foo")
+ (simple-test-layer :label "BAZ" :value "BAZ")))
+
+(defmethod initialize-attribute-for-layer (attribute layer-name &rest args)
+ (let* ((class (class-of attribute))
+ (slotds (class-slots class)))
+
+ (ensure-layered-method
+ (ensure-property-access-function attribute)
+ `(lambda ()
+ ',(loop
+ :for (key val) :on args :by #'cddr
+ :nconc (list
+ (loop :for slotd :in slotds
+ :do (when (find key (slot-definition-initargs slotd))
+ (return (slot-definition-name slotd))))
+ val)))
+ :qualifiers '(append)
+ :in-layer layer-name)))
+
+
+
+(define-layered-class simple-standard-attribute (simple-attribute)
+ ((label
+ :layered-accessor attribute-label
+ :initarg :label
+ :initform nil
+ :layered t
+ :special t)
+ (label-formatter
+ :layered-accessor attribute-label-formatter
+ :initarg :label-formatter
+ :initform nil
+ :layered t
+ :special t)
+ (function
+ :initarg :function
+ :layered-accessor attribute-function
+ :layered t
+ :special t)
+ (value
+ :layered-accessor attribute-value
+ :initarg :value
+ :layered t
+ :special t)
+ (value-formatter
+ :layered-accessor attribute-value-formatter
+ :initarg :value-formatter
+ :initform nil
+ :layered t
+ :special t)
+ (activep
+ :layered-accessor attribute-active-p
+ :initarg :active
+ :initform t
+ :layered t
+ :special t
+ :documentation
+ "Can be T, NIL or :WHEN. In the latter case, attribute is only active if the attribute value is non-null.")
+ (active-attributes :layered-accessor attribute-active-attributes
+ :initarg :attributes
+ :layered t
+ :special t)
+ (active-descriptions :layered-accessor attribute-active-descriptions
+ :initarg :activate
+ :initform nil
+ :layered t
+ :special t)
+ (inactive-descriptions :layered-accessor attribute-inactive-descriptions
+ :initarg :deactivate
+ :initform nil
+ :layered t
+ :special t)))
+
+
+(define-layered-class direct-attribute-slot-definition-class
+ (special-layered-direct-slot-definition
+ contextl::singleton-direct-slot-definition)
+ ((attribuite-properties
+ :accessor slot-definition-attribute-properties
+ :documentation "Holds the initargs passed to the slotd")))
+
+(defmethod initialize-instance
+ :after ((slotd direct-attribute-slot-definition-class)
+ &rest initargs)
+ (setf (slot-definition-attribute-properties slotd) initargs))
+
+(defmethod reinitialize-instance
+ :after ((slotd direct-attribute-slot-definition-class)
+ &rest initargs)
+ (setf (slot-definition-attribute-properties slotd) initargs))
+
+(define-layered-class effective-attribute-slot-definition-class
+ (special-layered-effective-slot-definition)
+ ((attribute-object
+ :accessor slot-definition-attribute-object)))
+
+(define-layered-class description-access-class (standard-layer-class contextl::special-layered-access-class)
+ ((defined-in-descriptions :initarg :in-description)
+ (class-active-attributes-definition :initarg :attributes)
+ (mixin-class-p :initarg :mixinp)))
+
+(defmethod direct-slot-definition-class
+ ((class description-access-class) &key &allow-other-keys)
+ (find-class 'direct-attribute-slot-definition-class))
+
+(defmethod effective-slot-definition-class
+ ((class description-access-class) &key &allow-other-keys)
+ (find-class 'effective-attribute-slot-definition-class))
+(fmakunbound 'initialize-slot-definition-attribute)
+(defmethod initialize-slot-definition-attribute ((slotd effective-attribute-slot-definition-class) name direct-slot-definitions)
+ (let ((tbl (make-hash-table))
+ (attribute (make-instance 'simple-standard-attribute :name name)))
+ (loop for ds in direct-slot-definitions
+ :do (setf (gethash (slot-definition-layer ds) tbl)
+ (append (gethash (slot-definition-layer ds) tbl '())
+ (slot-definition-attribute-properties ds))))
+ (maphash (lambda (layer properties)
+ (apply #'initialize-attribute-for-layer attribute layer properties))
+ tbl)
+ (setf (slot-definition-attribute-object slotd) attribute)))
+
+(defmethod compute-effective-slot-definition
+ ((class description-access-class) name direct-slot-definitions)
+ (declare (ignore name))
+ (let ((slotd (call-next-method)))
+ (initialize-slot-definition-attribute slotd)
+ slotd))
+
+(defclass standard-description-class (description-access-class layered-class)
+ ((attributes :accessor description-class-attributes :initform (list)))
+ (:default-initargs :defining-metaclass 'description-access-class))
+
+(defmethod validate-superclass
+ ((class standard-description-class)
+ (superclass standard-class))
+ t)
+
+(define-layered-class standard-description-object (standard-layer-object)
+ ((described-object :accessor described-object
+ :special t)))
+
+(defun initialize-description-class-attribute (description attribute initargs)
+ )
+
+(defmethod initialize-instance :around ((class standard-description-class) &rest initargs &key (direct-superclasses '()))
+ (declare (dynamic-extent initargs))
+ (prog1
+ (if (loop for direct-superclass in direct-superclasses
+ thereis (ignore-errors (subtypep direct-superclass 'standard-description-object)))
+ (call-next-method)
+ (apply #'call-next-method
+ class
+ :direct-superclasses
+ (append direct-superclasses
+ (list (find-class 'standard-description-object)))
+ initargs))
+ (break "initializing ~A ~A" class initargs)))
+
+
+(defmethod reinitialize-instance :around ((class standard-description-class) &rest initargs &key (direct-superclasses '() direct-superclasses-p))
+ (declare (dynamic-extent initargs))
+; (warn "CLASS ~A ARGS ~A:" class initargs)
+ (prog1
+ (if (or (not direct-superclasses-p)
+ (loop for direct-superclass in direct-superclasses
+ thereis (ignore-errors (subtypep direct-superclass 'standard-description-object))))
+ (call-next-method)
+ (apply #'call-next-method
+ class
+ :direct-superclasses
+ (append direct-superclasses
+ (list (find-class 'standard-description-object)))
+ initargs))
+ (break "RE-initializing ~A ~A" class initargs)))
+
+(defmethod finalize-inheritance :after ((class standard-description-class))
+ (break "Finalizing ~S" (class-name class)))
+
+;;;; A simpler implementation of descriptions based on plists
+
+
+
(in-package :lol-test)
-(defclass lol-test-server (standard-server)
+(defclass lol-test-server (ucw-core:standard-server)
())
-(defclass lol-test-application (standard-application)
+(defclass lol-test-application (ucw:standard-application)
()
(:default-initargs
:url-prefix "/lisp-on-lines.test/"
(defparameter *lol-test-ucw-server* (make-server))
-(register-application *lol-test-ucw-server* *lol-test-ucw-application*)
+(ucw-core:register-application *lol-test-ucw-server* *lol-test-ucw-application*)
-(defentry-point "index.ucw" (:application *lol-test-ucw-application*) ()
+(ucw-core:defentry-point "index.ucw" (:application *lol-test-ucw-application*) ()
(call 'lol-test-window))
(defun startup-lol-ucw-test ()
- (startup-server *lol-test-ucw-server*))
+ (ucw-core:startup-server *lol-test-ucw-server*))
(defun shutdown-lol-ucw-test ()
- (shutdown-server *lol-test-ucw-server*))
+ (ucw-core:shutdown-server *lol-test-ucw-server*))
-(defcomponent lol-test-window (standard-window-component)
+(ucw-core:defcomponent lol-test-window (standard-window-component)
()
(:default-initargs
:body (make-instance 'lol-test-suite-component)))
-(define-symbol-macro $window (lol-ucw:context.window-component *context*))
+(define-symbol-macro $window (ucw-core:context.window-component *context*))
(define-symbol-macro $body (window-body $window))
-(defcomponent lol-test-suite-component ()
+(ucw-core:defcomponent lol-test-suite-component ()
((test :component lol-test-simple-action :accessor test)
(component :component lol-test-render :accessor component)))
(define-symbol-macro $component (component $body))
-(defmethod render ((self lol-test-suite-component))
+(defmethod ucw-core:render ((self lol-test-suite-component))
(<:H1 "Lisp On Lines Web test suite")
(render (slot-value self 'test))
(<:div
:style "border:1px solid black;"
(render (slot-value self 'component))))
-(defcomponent lol-test-render ()
+(ucw-core:defcomponent lol-test-render ()
((message :initform "test" :accessor message :initarg :message)))
-(defmethod render ((self lol-test-render))
+(defmethod ucw-core:render ((self lol-test-render))
(<:h3 :id "test-render"
(<:as-html (format nil "Hello ~A." (message self)))))
-(defcomponent lol-test-simple-action ()
+(ucw-core:defcomponent lol-test-simple-action ()
())
-(defmethod render ((self lol-test-simple-action))
+(defmethod ucw-core:render ((self lol-test-simple-action))
(<:ul
- (<:li (<lol:a
+ (<:li (<ucw:a
:function
(lambda ()
(setf (message $component)
(format nil "~A : ~A" (message $component) "FUNCTION")))
"Test <:A :FUNCTION type actions"))
(<:li
- (<lol:a
+ (<ucw:a
:action (setf (message $component)
(format nil "~A : ~A" (message $component) "ACTION"))
"Test <:A :ACTION type actions"))
(<:li
- (<lol:a
+ (<ucw:a
:action* (make-action
(lambda ()
(setf (message $component)
(format nil "~A : ~A" (message $component) "ACTION*"))))
"Test <:A :ACTION* type actions"))
(<:li
- (<lol:a
+ (<ucw:a
:action (call-component $component (make-instance 'lol-test-answer))
"Test CALL-COMPONENT/ANSWER-COMPONENT"))
(<:li
- (<lol:a
+ (<ucw:a
:action (call-component $component (make-instance 'lol-test-call-magic))
"Test CALL/ANSWER MAGIC"))
(<:li
- (<lol:a
+ (<ucw:a
:action (call-component $component (make-instance 'lol-test-call-answer-action-magic))
"Test CALL/ANSWER ACTION MAGIC"))
(<:li
- (<lol:a
+ (<ucw:a
:action (call-component $component (make-instance 'lol-test-simple-form))
"Test Simple Form"))
(<:li
- (<lol:a
+ (<ucw:a
:action (call-component $component (make-instance 'lol-test-multi-submit-form))
"Test Multi Form"))
(<:li
- (<lol:a
+ (<ucw:a
:action (call-component $component (make-instance 'lol-test-input))
"Test Form input"))
))
-(defcomponent lol-test-answer (lol-test-render) ()
+(ucw-core:defcomponent lol-test-answer (lol-test-render) ()
(:default-initargs :message "CALL was ok. Go Back will answer"))
-(defmethod render :wrapping ((self lol-test-answer))
+(defmethod ucw-core:render :wrapping ((self lol-test-answer))
(call-next-method)
- (<lol:a :action (answer-component self nil) "Go Back."))
+ (<ucw:a :action (answer-component self nil) "Go Back."))
-(defcomponent lol-test-simple-form (lol-test-render) ()
+(ucw-core:defcomponent lol-test-simple-form (lol-test-render) ()
(:default-initargs :message "Testing Simple Form:"))
-(defmethod render :wrapping ((self lol-test-simple-form))
+(defmethod ucw-core:render :wrapping ((self lol-test-simple-form))
(call-next-method)
- (<lol:form
+ (<ucw:form
:action (setf (message self) "Form Submitted")
(<:submit))
- (<lol:a :action (answer-component self nil) "Go Back."))
+ (<ucw:a :action (answer-component self nil) "Go Back."))
-(defcomponent lol-test-multi-submit-form (lol-test-render) ()
+(ucw-core:defcomponent lol-test-multi-submit-form (lol-test-render) ()
(:default-initargs :message "Testing Simple Form:"))
-(defmethod render :wrapping ((self lol-test-multi-submit-form))
+(defmethod ucw-core:render :wrapping ((self lol-test-multi-submit-form))
(call-next-method)
- (<lol:form
+ (<ucw:form
:action (setf (message self) "Form Submitted")
(<:submit)
- (<lol:submit :action (setf (message self) "Submit 2" )
+ (<ucw:submit :action (setf (message self) "Submit 2" )
:value "2")
- (<lol:submit :action (setf (message self) "Submit 3")
+ (<ucw:submit :action (setf (message self) "Submit 3")
3))
- (<lol:a :action (answer-component self nil) "Go Back."))
+ (<ucw:a :action (answer-component self nil) "Go Back."))
-(defcomponent lol-test-input (lol-test-render)
+(ucw-core:defcomponent lol-test-input (lol-test-render)
()
(:default-initargs :message "Testing INPUTS"))
-(defmethod render :wrapping ((self lol-test-input))
+(defmethod ucw-core:render :wrapping ((self lol-test-input))
(call-next-method)
- (<lol:form
+ (<ucw:form
:function (constantly t)
- (<lol:input :type "text" :accessor (message self))
+ (<ucw:input :type "text" :accessor (message self))
(<:submit)
)
- (<lol:a :action (answer-component self nil) "Go Back."))
+ (<ucw:a :action (answer-component self nil) "Go Back."))
-(defcomponent lol-test-call-magic (lol-test-render)
+(ucw-core:defcomponent lol-test-call-magic (lol-test-render)
()
(:default-initargs :message "Testing CALL magic."))
-(defmethod render :wrapping ((self lol-test-call-magic))
+(defmethod ucw-core:render :wrapping ((self lol-test-call-magic))
(call-next-method)
- (<lol:a :action (setf (message self) (call 'lol-test-answer-magic)) "Test CALL")
+ (<ucw:a :action (setf (message self) (call 'lol-test-answer-magic)) "Test CALL")
(<:br)
- (<lol:a :action (answer-component self nil) "Go Back."))
+ (<ucw:a :action (answer-component self nil) "Go Back."))
-(defcomponent lol-test-answer-magic (lol-test-render)
+(ucw-core:defcomponent lol-test-answer-magic (lol-test-render)
()
(:default-initargs :message "Hit it to answer"))
-(defmethod render :wrapping ((self lol-test-answer-magic))
+(defmethod ucw-core:render :wrapping ((self lol-test-answer-magic))
(call-next-method)
- (<lol:a :action (answer "Ja, dat is vut ve answer" ) "IT! (hit here)"))
+ (<ucw:a :action (answer "Ja, dat is vut ve answer" ) "IT! (hit here)"))
-(defcomponent lol-test-call-answer-action-magic (lol-test-render)
+(ucw-core:defcomponent lol-test-call-answer-action-magic (lol-test-render)
()
(:default-initargs :message "Hit it to answer"))
-(defaction test-call-component ()
+(ucw:defaction test-call-component ()
(call 'lol-test-call-answer-action-magic :message "We made it"))
-(defaction test-answer-component ()
+(ucw:defaction test-answer-component ()
(answer "We Made IT BACK!!!"))
-(defmethod render :wrapping ((self lol-test-call-answer-action-magic))
+(defmethod ucw-core:render :wrapping ((self lol-test-call-answer-action-magic))
(call-next-method)
- (<lol:a :action (test-call-component) "Test CALL from ACTION")
+ (<ucw:a :action (test-call-component) "Test CALL from ACTION")
(<:br)
- (<lol:a :action (test-answer-component) "Test ANSWER from ACTION"))
+ (<ucw:a :action (test-answer-component) "Test ANSWER from ACTION"))