Update of /project/cells/cvsroot/Celtk
In directory clnet:/tmp/cvs-serv2995
Modified Files:
Celtk.lisp canvas.lisp composites.lisp demos.lisp
ltktest-cells-inside.lisp menu.lisp textual.lisp widgets.lisp
Log Message:
Wow, I changed all these? Only news is light editing of ltk-cells-inside.
--- /project/cells/cvsroot/Celtk/Celtk.lisp 2006/03/26 14:07:15 1.11
+++ /project/cells/cvsroot/Celtk/Celtk.lisp 2006/03/28 04:02:08 1.12
@@ -23,32 +23,33 @@
(defpackage :celtk
(:nicknames "CTK")
(:use :common-lisp :utils-kt :cells)
-
+
(:import-from #:ltk
#:wish-stream #:*wish* #:widget-path
#:read-data #:event-root-x #:event-root-y
#:send-wish #:tkescape #:after #:after-cancel #:bind
#:with-ltk #:do-execute #:add-callback)
-
+
(:export
- #:pop-up #:event-root-x #:event-root-y
+ #:pop-up #:event-root-x #:event-root-y
#:window #:panedwindow #:mk-row #:c?pack-self #:mk-stack #:mk-text-widget
- #:mk-panedwindow
+ #:mk-panedwindow
#:mk-stack #:mk-radiobutton #:mk-radiobutton-ex #:mk-radiobutton #:mk-label #:selection #:selector
- #:mk-checkbutton #:mk-button #:mk-button-ex #:entry #:mk-entry #:text
- #:frame-stack #:mk-frame-stack #:path #:^path
- #:mk-menu-entry-radiobutton #:mk-menu-entry-checkbutton
- #:mk-menu-radio-group #:mk-menu-entry-separator
- #:mk-menu-entry-command #:tk-callback #:menu #:mk-menu #:^menus #:mk-menu-entry-cascade #:mk-menubar
- #:^entry-values #:tk-eval-list #:mk-scale #:mk-popup-menubutton
- #:polygon #:mk-polygon #:oval #:mk-oval #:line #:mk-line #:arc #:mk-arc #:text-item #:mk-text-item
- #:rectangle #:mk-rectangle #:bitmap #:mk-bitmap #:canvas #:mk-canvas #:mk-frame-row
- #:mk-scrolled-list #:listbox-item #:mk-spinbox
- #:mk-scroller #:mk-menu-entry-cascade-ex
- #:with-ltk #:tk-format #:send-wish #:value #:.tkw
- #:tk-user-queue-handler #:user-errors #:^user-errors
+ #:mk-checkbutton #:mk-button #:mk-button-ex #:entry #:mk-entry #:text
+ #:frame-stack #:mk-frame-stack #:path #:^path
+ #:mk-menu-entry-radiobutton #:mk-menu-entry-checkbutton
+ #:mk-menu-radio-group #:mk-menu-entry-separator
+ #:mk-menu-entry-command #:mk-menu-entry-command-ex #:tk-callback
+ #:menu #:mk-menu #:^menus #:mk-menu-entry-cascade #:mk-menubar
+ #:^entry-values #:tk-eval-list #:mk-scale #:mk-popup-menubutton
+ #:polygon #:mk-polygon #:oval #:mk-oval #:line #:mk-line #:arc #:mk-arc #:text-item #:mk-text-item
+ #:rectangle #:mk-rectangle #:bitmap #:mk-bitmap #:canvas #:mk-canvas #:mk-frame-row
+ #:mk-scrolled-list #:listbox-item #:mk-spinbox
+ #:mk-scroller #:mk-menu-entry-cascade-ex
+ #:with-ltk #:tk-format #:send-wish #:value #:.tkw
+ #:tk-user-queue-handler #:user-errors #:^user-errors
#:timer #:timers #:repeat #:executions #:state #:timer-reset #:make-timer-steps
- #:^widget-menu #:widget-menu))
+ #:^widget-menu #:widget-menu #:tk-format-now))
(defpackage :celtk-user
(:use :common-lisp :utils-kt :cells :celtk))
@@ -365,8 +366,7 @@
(tk-format :grouped "senddatastring [set ~a]" var)
(read-data))
-(defun tk-eval-list (self form$)
- (declare (ignore self))
+(defun tk-eval-list (form$)
(tk-format :grouped "senddatastrings [~a]" form$)
(read-data))
--- /project/cells/cvsroot/Celtk/canvas.lisp 2006/03/24 03:46:25 1.2
+++ /project/cells/cvsroot/Celtk/canvas.lisp 2006/03/28 04:02:08 1.3
@@ -33,7 +33,9 @@
-closeenough -confine -height (scroll-region -scrollregion) -width
-xscrollincrement -yscrollincrement)
(:default-initargs
- :id (gentemp "CV")))
+ :xscrollcommand (c-in nil)
+ :yscrollcommand (c-in nil)
+ :id (gentemp "CV")))
(deftk arc (item)
()
--- /project/cells/cvsroot/Celtk/composites.lisp 2006/03/24 03:46:25 1.3
+++ /project/cells/cvsroot/Celtk/composites.lisp 2006/03/28 04:02:08 1.4
@@ -75,7 +75,7 @@
(defmodel window (composite-widget)
((wish :initarg :wish :accessor wish
:initform (wish-stream *wish*)
- #+(or) (c? (do-execute "wish84 -name testwindow"
+ #+(or) (c? (do-execute "wish85 -name testwindow"
nil #+not (list (format nil "-name ~s" (title$ self))))))
(ewish :initarg :ewish :accessor ewish :initform nil :cell nil) ;; vestigial?
(title$ :initarg :title$ :accessor title$
--- /project/cells/cvsroot/Celtk/demos.lisp 2006/03/25 11:32:44 1.5
+++ /project/cells/cvsroot/Celtk/demos.lisp 2006/03/28 04:02:08 1.6
@@ -32,6 +32,7 @@
(cells-reset 'tk-user-queue-handler)
(with-ltk (:debug 0)
(send-wish "proc trc2 {cb n1 n2 op} {puts \"(:callback \\\"$cb\\\" :name1 $n1 :name2 \\\"$n2\\\" :op $op)\"}")
+ #+notyet (send-wish "package require tile")
(setf ltk:*debug-tk* nil)
(with-integrity ()
(make-instance root-class))
@@ -199,7 +200,7 @@
(mk-popup-menubutton
:id :font-face
:initial-value (c? (second (^entry-values)))
- :entry-values (c? (eko ("ff") (tk-eval-list self "font families"))))
+ :entry-values (c? (eko (nil "ff") (tk-eval-list "font families"))))
(mk-scale :id :font-size
:md-value (c-in 14)
@@ -289,7 +290,7 @@
(defmodel font-view (frame-stack)
()
(:default-initargs
- :md-value (c? (tk-eval-list self "font families"))
+ :md-value (c? (tk-eval-list "font families"))
:pady 2 :padx 4
:packing-side 'left
:layout-anchor 'nw
--- /project/cells/cvsroot/Celtk/ltktest-cells-inside.lisp 2006/03/26 14:07:15 1.11
+++ /project/cells/cvsroot/Celtk/ltktest-cells-inside.lisp 2006/03/28 04:02:08 1.12
@@ -40,11 +40,10 @@
Contrast the code below with the excellent ltktest "classic" in ltk.lisp to
see how Celtk programming is different. I won't say better, because some people prefer an
imperative approach where they can have all the bricks laid out in front of them
-and lay them out carefully one by one to get exactly what they want without thinking
+and sequence them manually one by one to get exactly what they want without thinking
very hard. The declarative approach makes one think a little harder but in the end
-do less work. The trade-off becomes a big win for the declarative model as the
-interface gets either bigger or more dynamic, such as widgets that come and go as the
-user specifies different things in other widgets.
+do less work as the responsibility for getting things to work falls on the engine behind
+the declarative interface.
Second topic:
@@ -74,25 +73,27 @@
; Unfortunately, in a declarative paradigm one does not specify in what order different
; things should happen, one just specifies the things we want to have happen. An underlying
; engine then runs around taking care of making that happen, without bothering the developer
- ; about how to do that. Including in what order to make those things happen. That is
- ; a big win when it works. When it did not work for Tk, and I could see the same thing
- ; coming up again in other situations, I added to Cells the concept of a "client queue".
+ ; about how to do that. That includes deciding in what order to make those things happen. That is
+ ; a big win when it works. When it did not work for Tk, and I could imagine the same thing
+ ; coming up again in other situations (Tilton's Law: "The first time you run into something
+ ; is just the first time you will run into it"), I added to Cells the concept of a "client queue".
; Here client-code can store order-sensitive tasks. The client also can specify the handler for
- ; that queue. This handler (or the default FIFO handler) gets called at just the right time
- ; in the larger scheme of state propagation one needs for data integrity. What is that?
+ ; that queue, here 'tk-user-queue-handler. This handler (or the default FIFO handler) gets called
+ ; at just the right time in the larger scheme of state propagation one needs for
+ ; data integrity. What is that?
;
; Data integrity: when the overall Cells data model gets perturbed by imperative code -- typically an
- ; event loop -- executing a SETF of some datapoint X, we want these requirements satisfied:
+ ; event loop -- executing a SETF of some datapoint X, we want these requirements met:
;
; - recompute all and only state computed off X (directly or indirectly through some intermediate datapoint);
;
- ; - recomputations must see only datapoint values current with the new value of X;
+ ; - recomputations, when they read other datapoints, must see only values current with the new value of X;
;
- ; - similarly, client observers ("on change" callbacks) must see only values current with the new value of X
+ ; - similarly, client observers ("on change" callbacks) must see only values current with the new value of X; and
;
; - a corollary: should a client observer SETF a datapoint Y, all the above must
- ; happen with values current not just with X, but also with the value of Y /prior/
- ; to the intended change to Y.
+ ; happen with values current with not just X, but also with the value of Y /prior/
+ ; to the change to Y.
;
; To achieve the above, Cells2 and now Cells3 have taken to using FIFO "unfinished business" queues
; to defer things until The Right Time. Which brings us back to Tk. Inspect the source of
@@ -268,8 +269,7 @@
;
; I added the :user-errors rule above to demonstrate the mechanism in action. Click
; on the entry widget and type "123abc", then delete the alpha characters. The background
- ; color (as well as the File\Save menu item state) tracks the typing. (And an observer
- ; chats away on standard output.)
+ ; color (as well as the File\Save menu item state) tracks the typing.
;
(mk-button-ex ("Print" (format t "~&User wants to see ~A points" (fm^v :point-ct))))
@@ -282,19 +282,19 @@
; keep that information.
;
; Thus each class uses md-value to hold something different, but in all cases it is
- ; the current value of whatever the instance of that class is understood to hold.
+ ; the current value of whatever the instance of that class is understood to hold.
;
(mk-button-ex ("Reset" (setf (fm^v :point-ct) "42")))
;
- ; In Ltk one would SETF (text my-entry) and the
+ ; Driving home this point again, in Ltk one would SETF (text my-entry) and the
; SETF method would communicate with Tk to make the change to the Tk widget -text
; configuration. In Celtk, the md-value slot of the entry gets changed (possibly
; triggering other slots to update, which is why we do not just talk to Tk) and
; then that value gets propagated to Tk via "set <widget path> <value>". Because
; the textVariable for every entry is the entry itself, the text of the entry
; then changes. If that sounds weird, what we are actually doing is tapping into
- ; Tk to a large degree taking the same approach as Cells does with the md-value
- ; slot: in Cells, we think of model instances as wrapping some model-specific
+ ; the fact that Tk to a large degree takes the same approach as Cells does with md-value:
+ ; in Cells, we think of model instances as wrapping some model-specific
; value, which is held in the md-value slot of the model instance. Tk simply
; allows a widget path to be a global variable. Furthermore, as the company name
; ActiveState suggests, Tk also provides automatic propagation: change the
@@ -314,8 +314,9 @@
; the spinning lines. The pop-up is now a radio-group menu that does not know how the
; choice it is maintaining will be used. It simply takes care of its business of allowing
; the user to choose exactly one color. Changes get propagated automatically by the Cells
- ; engine to any slot whose rule happens to read the radio-group selection slot. And that
- ; is all they have to do, read the value. No need to code "subscribe" or "notify" code.
+ ; engine to any slot whose rule happens to read the radio-group selection slot. And the coding
+ ; is transparent: just read the value. No need to write explicit code to subscribe, notify,
+ ; or unsubscribe.
;
:scroll-region '(0 0 500 400)
:gridding "-row 0 -column 0 -sticky news"
@@ -328,25 +329,23 @@
;
; This also simplifies Celtk since it just has to pass the Tk code along with "grid <path> "
; appended.
- ;
- :xscrollcommand (c-in nil) ;; see canvas class for the Tk limitation behind this nonsense
- :yscrollcommand (c-in nil) ;; in brief, Tk lacks the concept of "late binding" on widget names
-
- :bindings (c? (list (list "<1>" (lambda (event)
- ;
- ; Stolen from the original. It means "when the left button is
- ; pressed on this widget, popup this menu where the button was pressed"
- ; The only difference is that here we get to specify this along with
- ; the rest of the configuration of this instance, whereas in the original
- ; the enabling code was just "out there" in a long sequence of other
- ; imperatives setting up this widget and that. ie, It is nice having
- ; everything about X collected in one place. In case you are wondering,
- ; an observer on the bindings slot passes the needed bindings to Tk
- ; via the client queue.
- ;
- (pop-up (^widget-menu :bkg-pop) ;; (^menus) -> (menus self)
- (event-root-x event)
- (event-root-y event))))))
+ ;
+ :bindings (c? (list
+ (list "<1>" (lambda (event)
+ ;
+ ; Stolen from the original. It means "when the left button is
+ ; pressed on this widget, popup this menu where the button was pressed"
+ ; The only difference is that here we get to specify this along with
+ ; the rest of the configuration of this instance, whereas in the original
+ ; the enabling code was just "out there" in a long sequence of other
+ ; imperatives setting up this widget and that. ie, It is nice having
+ ; everything about X collected in one place. In case you are wondering,
+ ; an observer on the bindings slot passes the needed bindings to Tk
+ ; via the client queue.
+ ;
+ (pop-up (^widget-menu :bkg-pop) ;; (^menus) -> (menus self)
+ (event-root-x event)
+ (event-root-y event))))))
:menus (c? (the-kids
;
@@ -356,32 +355,19 @@
; the binding list will run repeatedly) we are not forever regenerating the same pop-up menu.
; premature optimization? well, it also makes the code clearer, and should the list of menus become
; variable over time allows us to GC (via Tk "destroy") menus, so this is not so much about
- ; optimization as it is about the Good Things that happen to well-organized code.
+ ; optimization as it is about Good Things happening to well-organized code.
;
(mk-menu
:id :bkg-pop
:kids (c? (the-kids
(mk-menu-radio-group
:id :bkg
- :selection (c-in nil)
+ :selection (c-in nil) ;; this will start us off with the Tk default
:kids (c? (the-kids
(mk-menu-entry-radiobutton :label "Crimson Tide" :value "red")
(mk-menu-entry-radiobutton :label "Oak Tree Ribbon" :value "yellow")
- (mk-menu-entry-radiobutton :label "Sky" :value "blue")))))))
-
- (mk-menu
- :id :options
- :kids (c? (the-kids
- (mapcar (lambda (spec)
- (destructuring-bind (lbl . out$) spec
- (mk-menu-entry-command
- :label lbl
- :command (c? (tk-callback .tkw (gentemp "MNU")
- (lambda ()
- (format t "~&~a" out$)))))))
- (list (cons "Option 1" "Popup 1")
- (cons "Option 2" "Popup 2")
- (cons "Option 3" "Popup 3"))))))))
+ (mk-menu-entry-radiobutton :label "Sky" :value 'blue)
+ (mk-menu-entry-radiobutton :label "Factory" :value 'SystemButtonFace)))))))))
:kids (c? (the-kids
(mk-text-item
@@ -437,25 +423,14 @@
(mk-menubar
:kids (c? (the-kids
(mk-menu-entry-cascade-ex (:label "File")
- (mk-menu-entry-command :label "Load"
- :command (c? (tk-callback .tkw 'load
- (lambda () (format t "~&Load pressed")))))
-
- (mk-menu-entry-command :label "Save"
- :state (c? (if (user-errors (fm^ :point-ct))
- :disabled :normal))
- :command (c? (tk-callback .tkw 'save
- (lambda () (format t "~&Save pressed")))))
+ (mk-menu-entry-command-ex () "Load" (format t "~&Load pressed"))
+ (mk-menu-entry-command-ex (:state (c? (if (user-errors (fm^ :point-ct))
+ :disabled :normal)))
+ "Save" (format t "~&Save pressed"))
(mk-menu-entry-separator)
(mk-menu-entry-cascade-ex (:id :export :label "Export...")
- (mk-menu-entry-command
- :label "jpeg"
- :command (c? (tk-callback .tkw 'jpeg
- (lambda () (format t "~&Jpeg pressed")))))
- (mk-menu-entry-command
- :label "png"
- :command (c? (tk-callback .tkw 'png
- (lambda () (format t "~&Png pressed"))))))
+ (mk-menu-entry-command-ex () "jpeg" (format t "~&Jpeg pressed"))
+ (mk-menu-entry-command-ex () "png" (format t "~&Png pressed")))
(mk-menu-entry-separator)
(mk-menu-entry-command :label "Quit"
:accelerator "Alt-q"
--- /project/cells/cvsroot/Celtk/menu.lisp 2006/03/24 03:46:25 1.5
+++ /project/cells/cvsroot/Celtk/menu.lisp 2006/03/28 04:02:08 1.6
@@ -171,6 +171,14 @@
()
(:tk-spec command -command))
+(defmacro mk-menu-entry-command-ex ((&rest menu-command-initargs) lbl callback-body)
+ `(mk-menu-entry-command
+ ,@menu-command-initargs
+ :label ,lbl
+ :command (c? (tk-callback .tkw (gentemp "MNU")
+ (lambda ()
+ ,callback-body)))))
+
(deftk menu-entry-button (menu-entry-command)
()
(:tk-spec command
--- /project/cells/cvsroot/Celtk/textual.lisp 2006/03/24 03:46:25 1.4
+++ /project/cells/cvsroot/Celtk/textual.lisp 2006/03/28 04:02:08 1.5
@@ -69,6 +69,7 @@
-validate -validatecommand -width )
(:default-initargs
:id (gentemp "ENT")
+ :xscrollcommand (c-in nil)
:textvariable (c? (^path))
:md-value (c-in "")))
@@ -110,6 +111,8 @@
(:default-initargs
:id (gentemp "TXT")
:md-value (c-in "<your text here>")
+ :xscrollcommand (c-in nil)
+ :yscrollcommand (c-in nil)
:modified (c-in nil)
:bindings (c? (list (list "<<Modified>>"
(format nil "{callback ~~a}" (^path))
--- /project/cells/cvsroot/Celtk/widgets.lisp 2006/03/24 03:46:25 1.3
+++ /project/cells/cvsroot/Celtk/widgets.lisp 2006/03/28 04:02:08 1.4
@@ -120,6 +120,8 @@
:id (gentemp "SCL")
:md-value (c-in nil)
:tk-variable nil ;;(c? (^path))
+ :xscrollcommand (c-in nil)
+ :yscrollcommand (c-in nil)
:command (c? (tk-callbackval self 'scale-set
(lambda (&rest args)
(declare (ignore id))
@@ -143,6 +145,8 @@
-takefocus -width -xscrollcommand -yscrollcommand)
(:default-initargs
:id (gentemp "LBX")
+ :xscrollcommand (c-in nil)
+ :yscrollcommand (c-in nil)
:bindings (c? (when (selector self) ;; if not? Figure out how listbox tracks own selection
(list (list "<<ListboxSelect>>"
(format nil "{callbackval ~~a [~a curselection]}" (^path))
@@ -186,6 +190,7 @@
:md-value (c-in nil)
:id (gentemp "SPN")
:textVariable (c? (^path))
+ :xscrollcommand (c-in nil)
:command (c? (tk-callbackstring-x self 'vmirror "%s"
;;;(tk-callback self 'vcmd
(lambda (text)