I'm afraid I'm restarting an old discussion, but I've had it on the backburner, and now that I'm moving forward, I'm not quite sure how to finish out the solution.
"AH" == Andy Hefner ahefner@gmail.com writes:
AH> What I might do is run a separate thread from the GUI that monitors AH> external conditions. It can close over your frame event queue, and AH> communicate changes to the GUI via events as necessary. Just define AH> your own event subclasses and write handle-event methods for them, AH> which will run in the GUI thread and can perform the necessary AH> updates. McCLIM itself already works in this fashion on threaded AH> platforms, events are collected from CLX in a background thread which AH> queues them up for the applications to handle.
I think this is the right solution for control applications. One has a second thread, which gets status updates and latches them into slots in the application frame, and then we queue up an event. Here are a couple of follow-ons, though:
1. Do I just make an event that will translate into setting frame-needs-redisplay?
2. How do I ensure that the slots that I'm latching into are stable over the redisplay? I imagine I make a clim-sys:lock object to make the update process and the redisplay process mutually exclusive, but can anyone give me a little guidance about what to protect in the CLIM code?
I have been thinking that I should make a method for redisplay-frame-pane for my application that will hold the lock and (call-next-method). Is this the right level of granularity?
Thanks! Robert
| I'm afraid I'm restarting an old discussion, but I've had it on the | backburner, and now that I'm moving forward, I'm not quite sure how to | finish out the solution. | | >>>>> "AH" == Andy Hefner ahefner@gmail.com writes: | | AH> What I might do is run a separate thread from the GUI that monitors | AH> external conditions. It can close over your frame event queue, and | AH> communicate changes to the GUI via events as necessary. Just define | AH> your own event subclasses and write handle-event methods for them, | AH> which will run in the GUI thread and can perform the necessary | AH> updates. McCLIM itself already works in this fashion on threaded | AH> platforms, events are collected from CLX in a background thread which | AH> queues them up for the applications to handle. | | I think this is the right solution for control applications. One has | a second thread, which gets status updates and latches them into | slots in the application frame, and then we queue up an event. Here | are a couple of follow-ons, though: | | 1. Do I just make an event that will translate into setting | frame-needs-redisplay? |
I tried this approach in Lispworks CLIM and it seems to work pretty well.
Paul
~~~~~~~~~~~~~~~~~~~~~~~~~~ (in-package :clim-user)
(defclass thing () ((x :initarg :x) (y :initarg :y)) (:default-initargs :x (random 100) :y (random 100)))
(define-application-frame a-test () ((things :initform nil)) (:pointer-documentation nil) (:menu-bar nil) (:panes (p1 :application :width 300 :height 200 :end-of-line-action :allow :display-function 'p1df :incremental-redisplay t :display-time t )) (:layouts (default p1)))
(defun p1df (frame pane) (with-output-recording-options (pane :record t) (with-slots (things) frame (dolist (thing things) (with-slots (x y) thing (updating-output (pane :unique-id thing :cache-value (list x y) :cache-test #'equal) (draw-rectangle* pane x y (+ x 10) (+ y 10) :ink +blue+)))))))
(defvar *frame* nil)
(defun doit () ;; display A-TEST application (setq *frame* (make-application-frame 'a-test)) (run-frame-top-level *frame*))
(defclass my-event (device-event) ;; T-L-S seems to expect only device-event ;; Can't make application-pane see any yet ((pane :initarg :pane)))
(defmethod handle-event (client (event my-event)) (with-application-frame (frame) (with-slots (pane) event (redisplay-frame-pane frame pane))))
(defun stuffit (frame) ;; do something to "update the database" (let ((tls (frame-top-level-sheet frame)) (pane (frame-standard-output frame))) (with-slots (things) frame (with-output-recording-options (pane :record t) (push (make-instance 'thing) things)) (setf (pane-needs-redisplay pane) t)) (queue-event tls (make-instance 'my-event :sheet tls :pane pane :modifier-state 0))))
| | 1. Do I just make an event that will translate into setting | | frame-needs-redisplay? | | | | I tried this approach in Lispworks CLIM and it seems to work pretty well.
It is even easier than I thought. Here is a refinement of yesterdays code.
Paul ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (in-package :clim-user)
(defclass thing () ((x :initarg :x) (y :initarg :y)) (:default-initargs :x (random 100) :y (random 100)))
(define-application-frame a-test () ((things :initform nil)) (:pointer-documentation nil) (:menu-bar nil) (:panes (p1 :application :width 300 :height 200 :end-of-line-action :allow :display-function 'p1df :incremental-redisplay t)) (:layouts (default p1)))
(defun p1df (frame pane) (with-output-recording-options (pane :record t) (with-slots (things) frame (dolist (thing things) (with-slots (x y) thing (updating-output (pane :unique-id thing :cache-value (list x y) :cache-test #'equal) (draw-rectangle* pane x y (+ x 10) (+ y 10) :ink +blue+)))))))
(defvar *frame* nil)
(defun doit () ;; display A-TEST application (setq *frame* (make-application-frame 'a-test)) (run-frame-top-level *frame*))
(defclass my-event (device-event)() (:default-initargs :modifier-state 0))
(defmethod handle-event (client (event my-event)) (with-application-frame (frame) (redisplay-frame-pane frame client))))
(defun stuffit (frame) ;; do something to "update the database" (let ((tls (frame-top-level-sheet frame)) (pane (frame-standard-output frame))) (with-slots (things) frame (push (make-instance 'thing) things)) ;; Inform frame that something has changed (queue-event tls ;; :sheet causes event-handler client to be that (make-instance 'my-event :sheet pane))))
On Jan 7, 2005, at 9:50 PM, Paul Werkowski wrote:
| | 1. Do I just make an event that will translate into setting | | frame-needs-redisplay? | | | | I tried this approach in Lispworks CLIM and it seems to work pretty well.
It is even easier than I thought. Here is a refinement of yesterdays code.
Paul
Very interesting. Does this all "just work" in LispWorks CLIM? Do see any weird artifacts with presentation highlighting?
Tim
(in-package :clim-user) (defclass thing () ((x :initarg :x) (y :initarg :y)) (:default-initargs :x (random 100) :y (random 100))) (define-application-frame a-test () ((things :initform nil)) (:pointer-documentation nil) (:menu-bar nil) (:panes (p1 :application :width 300 :height 200 :end-of-line-action :allow :display-function 'p1df :incremental-redisplay t)) (:layouts (default p1))) (defun p1df (frame pane) (with-output-recording-options (pane :record t) (with-slots (things) frame (dolist (thing things) (with-slots (x y) thing (updating-output (pane :unique-id thing :cache-value (list x y) :cache-test #'equal) (draw-rectangle* pane x y (+ x 10) (+ y 10) :ink +blue+))))))) (defvar *frame* nil) (defun doit () ;; display A-TEST application (setq *frame* (make-application-frame 'a-test)) (run-frame-top-level *frame*)) (defclass my-event (device-event)() (:default-initargs :modifier-state 0)) (defmethod handle-event (client (event my-event)) (with-application-frame (frame) (redisplay-frame-pane frame client)))) (defun stuffit (frame) ;; do something to "update the database" (let ((tls (frame-top-level-sheet frame)) (pane (frame-standard-output frame))) (with-slots (things) frame (push (make-instance 'thing) things)) ;; Inform frame that something has changed (queue-event tls ;; :sheet causes event-handler client to be that (make-instance 'my-event :sheet pane)))) _______________________________________________ mcclim-devel mailing list mcclim-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/mcclim-devel
| Very interesting. Does this all "just work" in LispWorks CLIM? Do see | any weird artifacts with presentation highlighting?
It all seems to just work. I added some simple presentation stuff to the code (see below) and don't see anything unusual as yet. LWW CLIM's presentation highlighting leaves a bit to be desired as the outline seems to be off by 1 pixel (overwriting object on left and top) but that's normal.
I'm going to try this technique on some real code that currently does have some presentation abnormalities to see if this works better. I'll let you know what happens.
Paul
~~~~~~~~~~~~~~~~~~~~~~~ (in-package :clim-user)
(defclass thing () ((x :initarg :x) (y :initarg :y)) (:default-initargs :x (random 100) :y (random 100)))
(define-application-frame a-test () ((things :initform nil)) (:pointer-documentation nil) (:menu-bar nil) (:panes (p1 :application :width 300 :height 200 :end-of-line-action :allow :display-function 'p1df :incremental-redisplay t)) (:layouts (default p1)))
(defun p1df (frame pane) (with-output-recording-options (pane :record t) (with-slots (things) frame (dolist (thing things) (with-slots (x y) thing (updating-output (pane :unique-id thing :cache-value (list x y) :cache-test #'equal) (with-output-as-presentation (pane thing 'thing) (draw-rectangle* pane x y (+ x 10) (+ y 10) :ink +blue+))))))))
(defvar *frame* nil)
(defun doit () ;; display A-TEST application (setq *frame* (make-application-frame 'a-test)) (run-frame-top-level *frame*))
(defclass my-event (device-event)() (:default-initargs :modifier-state 0))
(defmethod handle-event (client (event my-event)) (with-application-frame (frame) (redisplay-frame-pane frame client)))
(defun stuffit (frame) ;; do something to "update the database" (let ((tls (frame-top-level-sheet frame)) (pane (frame-standard-output frame))) (with-slots (things) frame (push (make-instance 'thing) things)) ;; Inform frame that something has changed (queue-event tls ;; :sheet causes event-handler client to be that (make-instance 'my-event :sheet pane))))
(define-presentation-type thing ())
(define-a-test-command (com-noop)((object 'thing)) (print object *trace-output*) )
(define-presentation-to-command-translator x-noop (thing com-noop a-test) (object) (list object))