(in-package :ucw-standard)
(defmethod render :wrap-around (component)
(let ((*source-component* component))
(call-next-method)))
(defclass standard-application (basic-application)
((action-class :accessor application.action-class
:initform 'standard-action
:initarg :action-class)))
(defmethod service :around ((app standard-application) context)
(let ((*default-action-class* (application.action-class app)))
(call-next-method)))
;;;; ** Simple Window
(defcomponent basic-window-features-mixin ()
((title :accessor window-component.title
:initarg :title
:initform nil)
(stylesheet :accessor window-component.stylesheet
:initarg :stylesheet
:initform nil
:documentation "The URL of the css file to use as a stylesheet for this window.")
(icon :accessor window-component.icon
:initarg :icon
:initform nil
:documentation "Optional URL for an icon.")
(doctype :accessor window-component.doctype
:initarg :doctype
:initform (load-time-value +xhtml-transitional-doctype+)
:documentation "Doctype for this window.")
(content-prologue :accessor window-component.content-prologue
:initarg :content-prologue
:initform nil
:documentation "Unless nil it's printed <:as-is before any other output. Suitable for lines.")
(html-tag-attributes :accessor window-component.html-tag-attributes
:initarg :html-tag-attributes
:initform (list "xmlns" #.+xhtml-namespace-uri+)
:documentation "A yaclml attribute list that'll be rendered into the <:html tag's attributes.")
(javascript :accessor window-component.javascript
:initarg :javascript
:initform nil
:documentation "List of javascript includes.
Each element must be a list whose first value is either the
symbol :SRC or :JS.
(:SRC url) - writes tag.
(:JS form) - equivalent to (:SCRIPT (js:js* form))
(:SCRIPT string) - write .
The elements will be rendered in order."))
(:documentation "A mixin that renders basic html toplevel tags."))
(defgeneric effective-window-stylesheets (window)
(:documentation "This method is used to collect the effective stylesheet list for a window; available for customizations.")
(:method-combination nconc)
(:method nconc ((thing t))
(list))
(:method nconc ((window basic-window-features-mixin))
(copy-list (window-component.stylesheet window))))
(defmethod render ((window basic-window-features-mixin))
"This convience method assumes: 1) the stylesheet is
external (as opposed to inlined) or is not used; 2) the script
file is javascript and is external or is no script is used and 3)
the title is either a literal or a lambda with one argument (the
window)."
(awhen (window-component.content-prologue window)
(<:as-is it ~%))
(<:html :doctype (window-component.doctype window)
(@ (window-component.html-tag-attributes window))
(render-html-head window)
(render-html-body window)))
(defgeneric render-html-head (window)
(:method :around ((window basic-window-features-mixin))
(<:head (call-next-method)))
(:method ((window basic-window-features-mixin))
(<:meta :http-equiv "Content-Type" :content (window-component.content-type window))
(awhen (window-component.title window)
(<:title (if (functionp it)
(funcall it window)
(<:as-html it))))
(awhen (window-component.icon window)
(<:link :rel "icon"
:type "image/x-icon"
:href it))
(dolist (stylesheet (effective-window-stylesheets window))
(<:link :rel "stylesheet"
:href stylesheet
:type "text/css"))))
(defgeneric render-html-body (window)
(:method :around ((window basic-window-features-mixin))
(<:body
(render-window-scripts window)
(call-next-method))))
(defgeneric render-window-scripts (window)
(:method ((window basic-window-features-mixin))
(dolist* ((type value) (window-component.javascript window))
(ecase type
(:src
(<:script :type "text/javascript"
:src value
;; most browsers (firefox, safari and ie at least) really,
;; really, really don't like empty script tags. The "" forces
;; yaclml to generate a seperate closing tag.
""))
;; TODO clean up these names
#+nil(:js
(" ~%)))))))
(defcomponent basic-window-component (basic-window-features-mixin window-component)
()
(:documentation "A convenience class for writing window components."))
(defcomponent standard-window-component
(basic-window-component)
((body
:initform nil
:accessor window-body
:component t
:initarg :body)))
(defmethod render-html-head ((window standard-window-component))
(<:meta :http-equiv "Content-Type" :content (window-component.content-type window))
(awhen (window-component.title window)
(<:title (if (functionp it)
(funcall it window)
(<:as-html it))))
(awhen (window-component.icon window)
(<:link :rel "icon"
:type "image/x-icon"
:href it))
(dolist (stylesheet (effective-window-stylesheets window))
(<:link :rel "stylesheet"
:href stylesheet
:type "text/css")))
(defmethod render-html-body ((window standard-window-component))
(render (window-body window)))
(defcomponent info-message ()
((message :accessor message :initarg :message)))
(defmethod render ((m info-message))
(<:div
:class "info-mssage"
(<:as-html (message m)))
(