From rjain at common-lisp.net Fri Dec 25 20:57:08 2009 From: rjain at common-lisp.net (rjain) Date: Fri, 25 Dec 2009 15:57:08 -0500 Subject: [rjain-utils-cvs] CVS formulate/src Message-ID: Update of /project/rjain-utils/cvsroot/formulate/src In directory cl-net:/tmp/cvs-serv27653/src Modified Files: formulate.lisp Log Message: define classes using mixins --- /project/rjain-utils/cvsroot/formulate/src/formulate.lisp 2009/11/19 00:44:14 1.5 +++ /project/rjain-utils/cvsroot/formulate/src/formulate.lisp 2009/12/25 20:57:08 1.6 @@ -24,7 +24,7 @@ (error unbound-condition :name cell-name))) ;;; -;;; *** SIMPLE FORMULATOR SOURCE +;;; *** SIMPLE FORMULATOR SOURCE *** ;;; (defclass simple-formulator-source () @@ -59,7 +59,7 @@ result)) ;;; -;;; FORMULA FORMULATOR SINK +;;; *** FORMULA FORMULATOR SINK *** ;;; (defclass formula-formulator-sink () @@ -80,18 +80,18 @@ (slot-boundp formulator 'formula)) ;;; -;;; *** LAZY FORMULATOR SINK +;;; *** LAZY FORMULATOR *** ;;; -(defclass lazy-formula-formulator-sink (formula-formulator-sink) +(defclass lazy-formulator-mixin () ((source :initarg source :initform (make-instance 'simple-formulator-source) :accessor formulator-source :documentation "FORMULATOR-SOURCE that contains the cached value and propagates changes to sinks that refer to this formulator's parent cell.")) - (:documentation "FORMULATOR-SINK implementation that lazily recomputes - and caches the formula's value.")) + (:documentation "Mixin that lazily recomputes and caches the formula's + value.")) (defmethod formulator-dependents ((formulator lazy-formula-formulator-sink)) (formulator-dependents (formulator-source formulator))) @@ -99,8 +99,10 @@ (defmethod (setf formulator-dependents) (new-value (formulator lazy-formula-formulator-sink)) (setf (formulator-dependents (formulator-source formulator)) new-value)) -(defmethod formulator-value ((formulator lazy-formula-formulator-sink) - &optional cond cell) +(defmethod formulator-value :around ((formulator lazy-formula-formulator-sink) + &optional cond cell) + ;; should this be an around method or should I mandate ordering of + ;; mixins? (let ((source (formulator-source formulator))) (if (formulator-value-validp source) (let ((*formulating* nil)) @@ -119,14 +121,23 @@ ((sink lazy-formula-formulator-sink) source new-value old-value) (formulator-invalidate sink)) +(defclass lazy-formula-formulator-sink (lazy-formulator-mixin + formula-formulator-sink) + () + (:documentation "FORMULATOR-SINK implementation that lazily recomputes + and caches the formula's value.")) + ;;; -;;; DYNAMIC-FORMULATOR +;;; *** DYNAMIC FORMULA FORMULATOR *** ;;; -(defclass dynamic-formulator (lazy-formula-formulator-sink) +(defclass dynamic-formula-formulator-mixin (formula-formulator-sink) ()) (defmethod (setf formulator-value) (new-value (formulator dynamic-formulator)) (setf (formulator-formula formulator) new-value (formulator-formula-function formulator) (compile nil `(lambda () ,new-value))) (formulator-invalidate formulator)) + +(defclass dynamic-lazy-formula-formulator (lazy-formula-formulator-sink dynamic-formula-formulator-mixin) + ()) From rjain at common-lisp.net Fri Dec 25 20:59:19 2009 From: rjain at common-lisp.net (rjain) Date: Fri, 25 Dec 2009 15:59:19 -0500 Subject: [rjain-utils-cvs] CVS formulate/src Message-ID: Update of /project/rjain-utils/cvsroot/formulate/src In directory cl-net:/tmp/cvs-serv27785/src Modified Files: metaobjects.lisp Log Message: try to add support for class redefinition... doesn't quite work... --- /project/rjain-utils/cvsroot/formulate/src/metaobjects.lisp 2009/11/19 00:44:14 1.3 +++ /project/rjain-utils/cvsroot/formulate/src/metaobjects.lisp 2009/12/25 20:59:19 1.4 @@ -13,7 +13,8 @@ :initarg formulator-options :accessor formulator-options))) -(defclass formulated-direct-slot-definition (formulated-slot-definition standard-direct-slot-definition) +(defclass formulated-direct-slot-definition (formulated-slot-definition + standard-direct-slot-definition) ()) (defmethod initialize-instance :after ((instance formulated-direct-slot-definition) @@ -36,7 +37,8 @@ ;; a source. 'formulated-direct-slot-definition) -(defclass formulated-effective-slot-definition (formulated-slot-definition standard-effective-slot-definition) +(defclass formulated-effective-slot-definition (formulated-slot-definition + standard-effective-slot-definition) ()) (defmethod effective-slot-definition-class ((class formulated-class) &key &allow-other-keys) @@ -81,4 +83,18 @@ (defun slot-formulator (object slot-name) (let ((*get-formulator* t)) - (slot-value object slot-name))) \ No newline at end of file + (slot-value object slot-name))) + +(defmethod reinitialize-instance :after ((class formulated-class) &key) + ;; TODO: u-i-f-r-c is not being called... find out why + (eval `(defmethod update-instance-for-redefined-class :after + ((instance ,(class-name class)) added discarded plist &rest initargs) + ;; update formulae in slots + ,@(mapcar (lambda (slotd) + `(unless (or (find ,(slot-definition-name slotd) added) + ,(subtypep (formulator-class slotd) 'dynamic-formula-formulator-mixin)) + (setf (formulator-formula (slot-formulator instance ,(slot-definition-name slotd))) + ,(slot-definition-initform slotd)) + (setf (formulator-formula-function (slot-formulator instance ,(slot-definition-name slotd))) + ,(slot-definition-initfunction slotd)))) + (class-slots class))))) From rjain at common-lisp.net Fri Dec 25 21:00:15 2009 From: rjain at common-lisp.net (rjain) Date: Fri, 25 Dec 2009 16:00:15 -0500 Subject: [rjain-utils-cvs] CVS formulate/src Message-ID: Update of /project/rjain-utils/cvsroot/formulate/src In directory cl-net:/tmp/cvs-serv29567/src Modified Files: package.lisp variables.lisp Log Message: add FORMULATED-VARIABLE-P predicate --- /project/rjain-utils/cvsroot/formulate/src/package.lisp 2009/11/19 00:44:14 1.4 +++ /project/rjain-utils/cvsroot/formulate/src/package.lisp 2009/12/25 21:00:15 1.5 @@ -9,7 +9,8 @@ #:formula-p #:formulator-class #:formulator-options - #:define-formulated-variable) + #:define-formulated-variable + #:formulated-variable-p) (:use :cl #.(first '(#+sbcl :sb-mop :mop)))) (defpackage :formulate-user --- /project/rjain-utils/cvsroot/formulate/src/variables.lisp 2009/11/19 00:44:14 1.4 +++ /project/rjain-utils/cvsroot/formulate/src/variables.lisp 2009/12/25 21:00:15 1.5 @@ -17,6 +17,7 @@ 'formula ',formula 'formula-function (lambda () (declare , at declare) ,formula) , at formulator-options)) + (setf (get ',name 'formulated-variable-p) t) ',name)) (defun formulate-variable (name) @@ -26,3 +27,6 @@ (defun (setf formulate-variable) (new-value name) (setf (formulator-value (symbol-value name)) new-value)) + +(defun formulated-variable-p (name) + (get name 'formulated-variable-p nil)) From rjain at common-lisp.net Fri Dec 25 21:01:06 2009 From: rjain at common-lisp.net (rjain) Date: Fri, 25 Dec 2009 16:01:06 -0500 Subject: [rjain-utils-cvs] CVS formulate/src Message-ID: Update of /project/rjain-utils/cvsroot/formulate/src In directory cl-net:/tmp/cvs-serv31027 Modified Files: package.lisp Log Message: add export --- /project/rjain-utils/cvsroot/formulate/src/package.lisp 2009/12/25 21:00:15 1.5 +++ /project/rjain-utils/cvsroot/formulate/src/package.lisp 2009/12/25 21:01:06 1.6 @@ -3,6 +3,7 @@ #:simple-formulator-source #:formula-formulator-sink #:lazy-formula-formulator-sink + #:dynamic-lazy-formula-formulator #:formulated-class #:my #:*me* From rjain at common-lisp.net Fri Dec 25 21:03:22 2009 From: rjain at common-lisp.net (rjain) Date: Fri, 25 Dec 2009 16:03:22 -0500 Subject: [rjain-utils-cvs] CVS formulate/src/clim-ui Message-ID: Update of /project/rjain-utils/cvsroot/formulate/src/clim-ui In directory cl-net:/tmp/cvs-serv31147/src/clim-ui Modified Files: application.lisp formulate.clim-ui.asd objects.lisp variables.lisp Added Files: classes.lisp Log Message: usability enhancements separate class definer into a separate application frame and make it work --- /project/rjain-utils/cvsroot/formulate/src/clim-ui/application.lisp 2009/11/24 10:06:47 1.2 +++ /project/rjain-utils/cvsroot/formulate/src/clim-ui/application.lisp 2009/12/25 21:03:22 1.3 @@ -1,11 +1,18 @@ (in-package :formulate.clim-ui) +(defvar *document-package-counter* 0) + +(defun make-document-package () + (make-package (format nil "Document ~A" (incf *document-package-counter*)) + :use '(common-lisp formulate))) (define-application-frame formulate () - ((monitored-values :initform (make-array 5 :fill-pointer 0 :adjustable t) + ((document-package :initform (make-document-package) :initarg :document-package :accessor document-package) + (monitored-values :initform (make-array 5 :fill-pointer 0 :adjustable t) :accessor monitored-values)) (:panes (interactor :interactor - :scroll-bars t) + :scroll-bars t + :min-width 400) (monitor :application :scroll-bars t :incremental-redisplay t @@ -16,8 +23,26 @@ monitor interactor))) +(defmethod shared-initialize :after ((formulate formulate) slots &key) + (setf (frame-pretty-name formulate) + (format nil "Formulate: ~A" (package-name (document-package formulate))))) + +(defmethod default-frame-top-level ((frame formulate) &key &allow-other-keys) + (let ((*package* (document-package frame)) + (*debugger-hook* (if (find-package :clim-debugger) + (find-symbol "DEBUGGER" :clim-debugger) + *debugger-hook*))) + (call-next-method))) + +(define-formulate-command com-import-library ((name 'string)) + (use-package (string-upcase name))) + +;;;; +;;;; DATA MONITOR +;;;; + (defun display-monitor (*application-frame* *standard-output*) - (updating-output (t :unique-id (monitored-values *application-frame*)) + (updating-output (t) (map nil (lambda (item) (display-monitored-value item)) (monitored-values *application-frame*)))) @@ -28,31 +53,25 @@ (defun remove-from-monitor (value *application-frame*) (delete value (monitored-values *application-frame*))) -(defvar *error-formulator* nil) - (defmacro display-formula-value (location) `(catch 'formula-value-fail (handler-bind ((error #'(lambda (error) (display-formula-error error formulate::*formulating*) (throw 'formula-value-fail nil)))) - (let ((error-source-p (eql *error-formulator* - (let ((formulate::*get-formulator* t)) - ,location))) - (value ,location)) - (when error-source-p - (with-text-face (t :bold) - (with-drawing-options (t :ink +red+) - (write-string ">>>")))) - (present value (presentation-type-of value)) - (when error-source-p - (with-text-face (t :bold) - (with-drawing-options (t :ink +red+) - (write-string "<<<")))))))) + (let* ((value ,location) + (ptype (if (typep (class-of value) 'formulated-class) + 'formulated-object + (presentation-type-of value)))) + (present value ptype))))) (defmethod frame-standard-output ((frame formulate)) (get-frame-pane frame 'interactor)) +;;;; +;;;; FORMULA ERROR HANDLING +;;;; + (define-presentation-type formula-error () :inherit-from t) @@ -65,17 +84,26 @@ (print-unreadable-object ((formula-error-error error) stream :type t))) (defun display-formula-error (error formulator) - (with-output-as-presentation (t - (make-formula-error :error error :formulator formulator) - 'formula-error) + (with-output-as-presentation (t (make-formula-error :error error :formulator formulator) + 'formula-error) (with-text-face (t :italic) (with-drawing-options (t :ink +red+) - (write-char #\!) +2 (write-char #\!) (prin1 (class-name (class-of error))) (write-char #\!))))) (define-formulate-command com-describe-error ((err 'formula-error :gesture :select)) - (setf *error-formulator* (formula-error-formulator err)) (present (formula-error-error err) t) (format t "~&while computing ~A" (formulate::formulator-formula (formula-error-formulator err)))) + +;;;; +;;;; LAUNCHER ENTRY POINT +;;;; + +(defun run () + (clim-sys:make-process + (lambda () + (clim:run-frame-top-level + (clim:make-application-frame "Formulate" + :frame-class 'formulate.clim-ui:formulate))))) \ No newline at end of file --- /project/rjain-utils/cvsroot/formulate/src/clim-ui/formulate.clim-ui.asd 2009/11/19 01:17:18 1.1 +++ /project/rjain-utils/cvsroot/formulate/src/clim-ui/formulate.clim-ui.asd 2009/12/25 21:03:22 1.2 @@ -3,5 +3,6 @@ ((:file "package") (:file "application" :depends-on ("package")) (:file "variables" :depends-on ("package" "application")) - (:file "objects" :depends-on ("package" "application"))) + (:file "objects" :depends-on ("package" "application")) + (:file "classes" :depends-on ("package" "application"))) :depends-on (:formulate :clim)) --- /project/rjain-utils/cvsroot/formulate/src/clim-ui/objects.lisp 2009/11/24 10:06:47 1.2 +++ /project/rjain-utils/cvsroot/formulate/src/clim-ui/objects.lisp 2009/12/25 21:03:22 1.3 @@ -1,40 +1,16 @@ (in-package :formulate.clim-ui) -(define-formulate-command (com-define-formulated-class :name "Define Class") - ((name 'symbol :prompt "Name") - (superclasses '(sequence symbol) :default () :prompt "Superclasses") - (slots '(sequence slot-specification) :prompt "Slots")) - (eval `(defclass ,name ,(coerce superclasses 'list) - (,@(coerce slots 'list)) - (:metaclass formulated-class)))) - -(define-presentation-type slot-specification () - :inherit-from 'expression) - -(define-presentation-method accept ((type slot-specification) stream view - &key default) - (let* ((name (if default - (accept 'symbol :prompt "Name" :default (first default)) - (accept 'symbol :prompt "Name"))) - (formula-p (accept 'boolean - :prompt "Formula?" - :default (getf default 'formula-p t) - :default-type 'boolean)) - (initform (accept 'expression :prompt (if formula-p "Formula" "Initial value")))) - `(,name formula-p ,formula-p :initform ,initform))) - (define-formulate-command (com-create-instance :name "Create Instance") - ((class '(or class symbol) :prompt "Class")) - (vector-push-extend (make-instance class) + ((name 'symbol :prompt "Name") + (class '(or class symbol) :prompt "Class")) + (proclaim `(special ,name)) + (setf (symbol-value name) (make-instance class)) + (vector-push-extend name (monitored-values *application-frame*))) (define-presentation-type formulated-object () :inherit-from t) -(defmethod display-monitored-value ((object standard-object)) - (fresh-line) - (present object 'formulated-object)) - (define-presentation-type formulated-slot () ;; 3 element list: (slot-value ) :inherit-from t) @@ -54,21 +30,22 @@ (define-presentation-method present (object (type formulated-object) stream view &key) - (with-output-as-presentation (stream object 'formulated-object) + (with-output-as-presentation (stream object 'formulated-object :single-box t) (with-output-as-presentation (stream (class-of object) 'class) - (with-text-face (stream :bold) - (prin1 (class-name (class-of object)) stream))) + (with-text-face (stream :bold) + (with-drawing-options (t :ink +blue+) + (prin1 (class-name (class-of object)) stream)))) (fresh-line stream) (formatting-table (stream) (dolist (slot (class-slots (class-of object))) (with-output-as-presentation (stream `(slot-value ,object ',(slot-definition-name slot)) - 'formulated-slot) + 'formulated-slot + :single-box t) (display-slot-as-row object slot stream view)))))) (define-presentation-translator slot-accessor (formulated-slot form formulate) (object) - (format t "translating slot to expression") (values object 'expression t)) (define-formulate-command (com-remove-object :name "Remove Object From Monitor") @@ -77,7 +54,7 @@ (define-formulate-command (com-set-slot-value :name "Set Slot Value") ((expression 'formulated-slot :prompt "Slot" :gesture :select) - (new-value 'form :prompt "New value" :default *unsupplied-argument-marker*)) + (new-value 'form :prompt "New value")) (destructuring-bind (s-v object (q slot)) expression (declare (ignore s-v q)) (setf (slot-value object slot) (eval new-value)))) --- /project/rjain-utils/cvsroot/formulate/src/clim-ui/variables.lisp 2009/11/24 10:06:47 1.2 +++ /project/rjain-utils/cvsroot/formulate/src/clim-ui/variables.lisp 2009/12/25 21:03:22 1.3 @@ -3,10 +3,10 @@ (define-formulate-command (com-define-formulated-variable :name "Define Variable") ((name 'symbol :prompt "Name") (formula-p 'boolean :prompt "Formula?") - (formula 'expression :prompt (if formula-p "Formula" "Initial value")) + (formula 'form :prompt (if formula-p "Formula" "Initial value")) (monitor-p 'boolean :default t :prompt "Show in monitor pane?") - (declarations 'expression :default '() :prompt "Declarations") - (documentation '(or string null) :default nil :prompt "Documentation")) + (declarations 'expression :default '((optimize (speed 1))) :prompt "Declarations") + (documentation '(or string null) :default "" :prompt "Documentation")) (eval `(define-formulated-variable ,name ,formula :formula-p ,formula-p :declare ,declarations :documentation ,documentation)) @@ -15,15 +15,27 @@ (vector-push-extend name (monitored-values *application-frame*))))) (define-presentation-type formulated-variable () - :inherit-from t) + :inherit-from 'symbol) (defmethod display-monitored-value ((name symbol)) (fresh-line) - (with-output-as-presentation (t name 'formulated-variable) - (with-text-face (t :bold) - (present name 'symbol)) - (write-string " = ") - (display-formula-value (eval name)))) + (with-output-as-presentation (t name (if (formulated-variable-p name) 'formulated-variable 'symbol) :single-box t) + (formatting-table () + (formatting-row () + (formatting-cell () + (with-text-face (t :bold) + (present name 'symbol)) + (write-string " = ")) + (formatting-cell () + (display-formula-value (eval name))))) + (when (documentation name 'variable) + (fresh-line) + (with-text-face (t :italic) + (with-drawing-options (t :ink +dark-green+) + (filling-output (t) + (write-string (documentation name 'variable))))))) + (terpri) + (terpri)) (define-formulate-command (com-remove-variable :name "Remove Variable From Monitor") ((name 'formulated-variable :prompt "Variable" :gesture :menu)) @@ -31,7 +43,7 @@ (define-formulate-command (com-set-variable :name "Set Variable") ((name 'formulated-variable :gesture :select) - (new-value 'form)) + (new-value 'expression)) (eval `(setf ,name ',new-value))) (define-formulate-command (com-describe-variable :name "Describe Variable") --- /project/rjain-utils/cvsroot/formulate/src/clim-ui/classes.lisp 2009/12/25 21:03:22 NONE +++ /project/rjain-utils/cvsroot/formulate/src/clim-ui/classes.lisp 2009/12/25 21:03:22 1.1 (in-package :formulate.clim-ui) (define-application-frame class-definer () ((formulate-application :initarg :formulate-application :accessor formulate-application) (class-name :initarg :class-name :accessor name) (direct-superclasses :initarg :direct-superclasses :initform () :accessor direct-superclasses) (slots :initarg :direct-slots :initform () :accessor direct-slots) (options :initarg :options :initform '((:metaclass formulated-class)) :accessor options)) (:pointer-documentation t) (:top-level (class-definer-top-level)) (:geometry :width 500 :height 500) (:panes (class :application :scroll-bars t :display-function 'display-class-definition :display-time :command-loop) (interactor :interactor :scroll-bars t)) (:layouts (initial (:fill class) (horizontally (:x-spacing 10 :max-width 1000) (make-pane 'push-button :label "Define Class" :show-as-default t :activate-callback (lambda (gadget) (declare (ignore gadget)) (eval-define-class *application-frame*) (redisplay-frame-pane (formulate-application *application-frame*) 'monitor) (frame-exit *application-frame*))) (make-pane 'push-button :label "Cancel" :activate-callback (lambda (gadget) (declare (ignore gadget)) (frame-exit *application-frame*))))) (interacting (2/5 class) (3/5 interactor)))) (define-formulate-command (com-define-formulated-class :name "Define Class") ((name 'symbol :prompt "Name")) (let ((package *package*) (formulate-application *application-frame*) (dialog-name (format nil "Define Class: ~A" name))) (clim-sys:make-process (lambda () (let ((*package* package)) (run-frame-top-level (apply #'make-application-frame dialog-name :frame-class 'class-definer :formulate-application formulate-application :class-name name (when (find-class name nil) (let ((class (find-class name))) (list :direct-superclasses (mapcar #'class-name (class-direct-superclasses class)) :direct-slots (mapcar #'make-slot-specification (class-direct-slots class)) :options (list (list :metaclass (class-name (class-of class))))))))))) :name dialog-name))) (defvar *setting-layout* nil) (defmethod layout-frame ((frame class-definer) &optional width height) (if *setting-layout* nil #+nil ;; TODO need to figure out how to get relayout to happen without resizing frame (allocate-space (frame-top-level-sheet frame) (graft-width (frame-top-level-sheet frame)) (graft-height (frame-top-level-sheet frame))) (if (or width height) (call-next-method) (let* ((sr-initial (compose-space (climi::find-pane-for-layout 'initial frame))) (sr-interacting (compose-space (climi::find-pane-for-layout 'interacting frame))) (combined-sr (space-requirement-combine #'max sr-initial sr-interacting))) (call-next-method frame (space-requirement-width combined-sr) (space-requirement-height combined-sr)))))) (defmethod (setf frame-current-layout) :around (name (frame class-definer)) (let ((*setting-layout* t)) (call-next-method))) (defun accept-without-interactor (frame type) (with-input-context (type) (object) (loop (read-gesture :stream (get-frame-pane frame 'class))) (t object))) (defvar *interaction-continuation* nil) (defun do-interaction () (let* ((interactor (get-frame-pane *application-frame* 'interactor)) (*standard-input* interactor) (*standard-output* interactor) (*query-io* interactor)) (window-clear (get-frame-pane *application-frame* 'interactor)) (unwind-protect (funcall *interaction-continuation*) (setf *interaction-continuation* nil) (setf (frame-current-layout *application-frame*) 'initial)))) (defun get-command () (let ((command (accept-without-interactor *application-frame* `(command :command-table ,(frame-command-table *application-frame*))))) (execute-frame-command *application-frame* command))) (defun class-definer-top-level (*application-frame*) (redisplay-frame-panes *application-frame* :force-p t) ;; limit scope of changes to *INTERACTION-CONTINUATION* to this ;; specific invocation (let ((*interaction-continuation* nil)) (loop (restart-case (progn (redisplay-frame-panes *application-frame*) (if (print *interaction-continuation*) (do-interaction) (get-command))) (abort () :report "Return to application command loop" (clim-extensions:frame-display-pointer-documentation-string *application-frame* "Command aborted.")))))) (defmacro with-interaction (() &body body) `(progn (setf *interaction-continuation* (lambda () , at body)) (handler-case ;; the following may exit non-locally back to the top-level loop (setf (frame-current-layout *application-frame*) 'interacting) (climi::frame-layout-changed ())) (do-interaction))) (defun eval-define-class (definer) (eval `(defclass ,(name definer) ,(direct-superclasses definer) ,(mapcar #'slot-specification-form (direct-slots definer)) ,@(options definer)))) (define-presentation-type slot-specification () :inherit-from 't) (defstruct (slot-specification (:constructor %make-slot-specification (name &key formula-p initform accessor options))) name formula-p initform accessor options) (defmethod make-slot-specification ((slotd direct-slot-definition) &rest keys) (declare (ignore keys)) (%make-slot-specification (slot-definition-name slotd) :formula-p (subtypep (formulate::formulator-class slotd) 'formulate::formula-formulator-sink) :initform (slot-definition-initform slotd) :accessor (first (slot-definition-readers slotd)) :options nil)) (defmethod make-slot-specification ((name symbol) &rest keys) (apply #'%make-slot-specification name keys)) (defun slot-specification-form (spec) (list* (slot-specification-name spec) 'formula-p (slot-specification-formula-p spec) :initform (slot-specification-initform spec) :accessor (slot-specification-accessor spec) (slot-specification-options spec))) (define-presentation-method present ((spec slot-specification) (type slot-specification) *standard-output* view &key) (present (slot-specification-name spec)) (with-text-face (t :italic) (prin1 " Formula?: ")) (present (slot-specification-formula-p spec) 'boolean) (with-text-face (t :italic) (if (slot-specification-formula-p spec) (prin1 " Formula: ") (prin1 " Initial Value: "))) (present (slot-specification-initform spec) 'form) (with-text-face (t :italic) (prin1 " Accessor: ")) (present (slot-specification-accessor spec) 'symbol) (with-text-face (t :italic) (prin1 " Options: ")) (present (slot-specification-options spec) 'form)) (define-presentation-translator peer-accessor (slot-specification form class-definer) (object) (values `(my ,(slot-specification-name object)) 'expression t)) (define-presentation-translator peer-accessor (formulated-slot form class-definer) (object) (values `(my ,(second (third object))) 'expression t)) (define-presentation-method accept ((type slot-specification) *standard-output* view &key default) (let (name formula-p initform accessor options) (accepting-values () (fresh-line) (setf name (apply #'accept 'symbol :prompt "Name" (when default (list :default (slot-specification-name default))))) (terpri) (setf formula-p (accept 'boolean :prompt "Formula?" :default (if default (slot-specification-formula-p default) t))) (terpri) (setf initform (apply #'accept 'expression :prompt (if formula-p "Formula" "Initial Value") :query-identifier :initform (when default (list :default (slot-specification-initform default))))) (terpri) (setf accessor (apply #'accept 'symbol :prompt "Accessor" (when default (list :default (slot-specification-accessor default))))) (terpri) (setf options (accept 'expression :prompt "Options" :default (if default (slot-specification-options default) nil)))) (make-slot-specification name :formula-p formula-p :initform initform :accessor accessor :options options))) (define-modify-macro nconcf (place &rest lists) nconc) (defun add-superclass (gadget) (declare (ignore gadget)) (with-interaction () (let ((class (accept 'symbol))) (nconcf (direct-superclasses *application-frame*) (list class))))) (defun add-slot (gadget) (declare (ignore gadget)) (with-interaction () (let ((slot (accept 'slot-specification))) (nconcf (direct-slots *application-frame*) (list slot))))) (defun add-option (gadget) (declare (ignore gadget)) (with-interaction () (let ((option (accept 'form))) (nconcf (options *application-frame*) (list option))))) (define-presentation-type superclass () :inherit-from 'class) (define-class-definer-command (com-remove-superclass) ((superclass 'superclass :gesture :describe)) (setf (direct-superclasses *application-frame*) (remove superclass (direct-superclasses *application-frame*)))) (define-class-definer-command (com-change-superclass) ((superclass 'superclass :gesture :select)) (with-interaction () (setf (direct-superclasses *application-frame*) (substitute (direct-superclasses *application-frame*) (accept 'symbol :default superclass :prompt "New Superclass") superclass)))) (define-class-definer-command (com-remove-slot) ((slot 'slot-specification :gesture :describe)) (setf (direct-slots *application-frame*) (remove slot (direct-slots *application-frame*)))) (define-class-definer-command (com-change-slot) ((slot 'slot-specification :gesture :select)) (with-interaction () (setf (direct-slots *application-frame*) (substitute (accept 'slot-specification :default slot) slot (direct-slots *application-frame*))))) (define-presentation-type class-option () :inherit-from 'expression) (define-presentation-method presentation-typep ((object cons) (type class-option)) (and (symbolp (car object)) (consp (cdr object)))) (define-class-definer-command (com-remove-option) ((option 'class-option :gesture :describe)) (setf (options *application-frame*) (remove option (options *application-frame*)))) (define-class-definer-command (com-change-option) ((option 'class-option :gesture :select)) (with-interaction () (setf (options *application-frame*) (substitute (accept 'class-option :default option) option (options *application-frame*))))) (defun display-class-definition (*application-frame* *standard-output*) (with-look-and-feel-realization (*default-frame-manager* *application-frame*) (let ((interacting (eql (frame-current-layout *application-frame*) 'interacting))) (macrolet ((labelling ((&key label (newline-p t)) &body body) `(surrounding-output-with-border (t) (with-text-face (t :bold) (princ ,label)) (write-char #\:) ,(if newline-p `(terpri) `(write-char #\space)) , at body))) (labelling (:label "Class Name" :newline-p nil) (princ (name *application-frame*))) (terpri) (labelling (:label "Superclasses") (filling-output (t) (dolist (super (direct-superclasses *application-frame*)) (with-output-as-presentation (t super 'superclass) (princ super)) (write-char #\Space))) (fresh-line) (with-output-as-gadget (t) (make-pane 'push-button :label "Add" :id 'add-superclass :activate-callback #'add-superclass :active-p (not interacting)))) (terpri) (labelling (:label "Slots") (dolist (spec (direct-slots *application-frame*)) (present spec 'slot-specification :single-box t) (terpri)) (with-output-as-gadget (t) (make-pane 'push-button :label "Add" :id 'add-slot :activate-callback #'add-slot :active-p (not interacting)))) (terpri) (labelling (:label "Options") (dolist (option (options *application-frame*)) (present option 'class-option) (terpri)) [4 lines skipped]