home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / swat / scheme / baseobj.scm next >
Text File  |  1995-08-02  |  24KB  |  647 lines

  1. ;;;;; -*- Scheme -*-
  2. ;;;;; Basic objects for the Scheme User Interface Tool Kit
  3. ;;;; MIT Scheme Version derived from Scheme-To-C version 1.2
  4.  
  5. ;;;; $Id: baseobj.scm,v 1.1 1995/08/02 21:26:49 adams Exp $
  6.  
  7. ;;;; Application objects
  8.  
  9. (define (application->TKMainWindow obj) (Application%.TKMainWindow obj))
  10. (define (application->Display obj) (Application%.Xdisplay obj))
  11.  
  12. (define (valid-color-for-application? app color-string)
  13.   ((string->color (application->display app)) color-string))
  14.  
  15. (define (valid-color? color-string)
  16.   ;; For default application
  17.   ((string->color (application->display *the-default-application*))
  18.    color-string))
  19.  
  20. (define (make-top-level-geometry-callback kid)
  21.   ;; Is the TK-TOP-LEVEL-WINDOW required any more? --Jim
  22.   (let ((my-screen-area #f))
  23.     (lambda (configure-event)
  24.       (Decode-Configure-Event
  25.        Configure-Event
  26.        (lambda (type serial send_event display event window x y width
  27.              height border-width above override-redirect)
  28.      type serial send_event display event window x y
  29.      border-width above override-redirect ; Not used
  30.      (let ((new-area (make-UITKRectangle
  31.                     ; (make-point x y)
  32.               (make-point 0 0)
  33.               (make-size width height))))
  34.        (if (not (screen-area= new-area my-screen-area))
  35.            (begin
  36.          (%XClearWindow display window)
  37.          (assign-screen-area! kid #F)
  38.          (assign-screen-area! kid new-area)))
  39.        (set! my-screen-area new-area))
  40.      'DONE)))))
  41.  
  42. (define (valid-child? object)
  43.   (or (interactor%? object)
  44.       (box%? object)
  45.       (arraybox%? object)
  46.       (shape%? object)
  47.       (tkwidget%? object)))
  48.  
  49. (define (application-add-child! application to-be-managed . child-name)
  50.   ;; Name is an optional string that overrides the application's
  51.   ;; name for providing a title to the child window
  52.   (if (not (valid-child? to-be-managed))
  53.       (error "APPLICATION-ADD-CHILD!: Bad UIObj" to-be-managed))
  54.   (one-parent-only! to-be-managed application)
  55.   (let ((really-adding? #F)
  56.     (new-entry (cons to-be-managed 'TK-Top-Level-Window)))
  57.     (update-locked-list!
  58.      (Application%.%child-windows application)
  59.      (lambda (kids)
  60.        (if (assq to-be-managed kids)
  61.        kids
  62.        (begin
  63.          (set! really-adding? #T)
  64.          (cons new-entry kids)))))
  65.     (if really-adding?
  66.     (let ((Xdisplay (Application%.Xdisplay application))
  67.           (context (Application%.context application))
  68.           (top-level-geometry-callback
  69.            (make-top-level-geometry-callback to-be-managed))
  70.           (TKMainW
  71.            (application->TKMainWindow application))
  72.           (TKW (make-ToolKitWindow application #F #F)))
  73.       (let* ((drawing-surface (make-DrawingSurface TKW #F))
  74.          (tlwindow
  75.           (tk-create-top-level-window
  76.            TKMainW
  77.            (hash top-level-geometry-callback *our-hash-table*))))
  78.         (set-cdr! new-entry tlwindow)
  79.         (set-ToolKitWindow.TK-Window! TKW tlwindow)
  80.         (set-ToolKitWindow.Top-Level-Geometry-Callback!
  81.          TKW top-level-geometry-callback)
  82.         (set-context! to-be-managed context)
  83.         (assign-drawing-surface! to-be-managed drawing-surface)
  84.         (let ((desired-size (get-desired-size to-be-managed))
  85.           (window-name (tkwin.pathname tlwindow)))
  86.           (tk-invoke-command
  87.            'WM TKMainW
  88.            (list "title" window-name
  89.              (if (and (pair? child-name)
  90.                   (string? (car child-name)))
  91.              (car child-name)
  92.              (Application%.application-name application))))
  93.           (let ((tlwindow-width
  94.              (number->string (or (size.width desired-size) 0)))
  95.             (tlwindow-height
  96.              (number->string (or (size.height desired-size) 0))))
  97.  
  98.         #|
  99.         (tk-invoke-command
  100.          'WM TKMainW
  101.          (list "minsize" window-name "1" "1"))
  102.         |#
  103.  
  104.         (tk-invoke-command
  105.          'WM TKMainW
  106.          (list "minsize" window-name tlwindow-width tlwindow-height))
  107.         ;;X signals errors if we don't do this, but I'm damned if I know why
  108.         (tk-invoke-command
  109.          'WM TKMainW
  110.          (list "geometry" window-name
  111.                (string-append tlwindow-width "x" tlwindow-height)))
  112.         )
  113.           (let ((kill-me
  114.              (lambda ()
  115.                (application-remove-destroyed-child! application to-be-managed)
  116.                )))
  117.         (tk-invoke-command
  118.          'BIND TKMainW
  119.          (list window-name "<Destroy>"
  120.                (string-append
  121.             "SchemeCallBack "
  122.             (number->string (hash kill-me *our-hash-table*)))))
  123.         (UIObj-protect-from-gc! to-be-managed kill-me))
  124.           ;; Events start being generated and handled in
  125.           ;; the other thread as soon as we map this
  126.           ;; window!  We must map the window before doing
  127.           ;; the MAKE-UITKWINDOW below, because TK
  128.           ;; doesn't create the X window until the widget
  129.           ;; is mapped.
  130.           (our-with-thread-mutex-locked
  131.            'add-child-locks-out-others
  132.            *event-processing-mutex*
  133.            (lambda ()
  134.          (tk-map-window tlwindow)
  135.          (let ((UITKWindow
  136.             (make-uitkwindow
  137.              Xdisplay
  138.              (wrap-window Xdisplay
  139.                       (tkwin.window tlwindow)))))
  140.            (set-DrawingSurface.UITKWindow!
  141.             drawing-surface UITKWindow)
  142.            (assign-drawing-surface!
  143.             to-be-managed drawing-surface))
  144.          ;; UITKWindow changed and some objects will
  145.          ;; need that rather than just the TK top
  146.          ;; level window.
  147.          (assign-screen-area!
  148.           to-be-managed
  149.           (make-UITKRectangle (make-point 0 0)
  150.                       (tkwin->size tlwindow)))
  151.          ))))
  152.       #|
  153.       ;;let window resize when kid requests resize
  154.       ;;but this means that size is determined by kid -- not WM
  155.       ;;do we want both kinds of windows??
  156.       (on-geometry-change!
  157.        to-be-managed 'APPLICATION
  158.        (lambda (old-screen-area new-screen-area)
  159.          old-screen-area        ;not used
  160.          (if (eq? new-screen-area #T) ;instigated by child
  161.          (let* ((desired-size (get-desired-size to-be-managed))
  162.             (tlwindow-width
  163.              (number->string (or (size.width desired-size) 0)))
  164.             (tlwindow-height
  165.              (number->string (or (size.height desired-size) 0)))
  166.             (window-name
  167.              (tkwin.pathname
  168.               (ToolkitWindow.TK-window
  169.                (DrawingSurface.ToolkitWindow
  170.                 (drawing-surface to-be-managed))))))
  171.            (tk-invoke-command
  172.             'WM TKMainW
  173.             (list "minsize" window-name tlwindow-width tlwindow-height))
  174.            (tk-invoke-command
  175.             'WM TKMainW
  176.             (list "geometry" window-name
  177.               (string-append tlwindow-width "x" tlwindow-height)))))))
  178.  
  179.       |#
  180.  
  181.       (on-death! to-be-managed 'APPLICATION
  182.              (lambda ()
  183.                (application-remove-child! application to-be-managed)))))
  184.     'ADDED))
  185. ;;; More methods for Applications below
  186.   
  187. ;;; More methods for Applications objects
  188.  
  189. (define (application-remove-child! Application to-be-unmanaged)
  190.   ;; This is called by the generic REMOVE-CHILD! procedure.
  191.   (let ((entry (with-locked-list
  192.         (application%.%child-windows application)
  193.         (lambda (kids) (assq to-be-unmanaged kids)))))
  194.     (if (not entry)
  195.     'NOT-A-CHILD
  196.     (let ((tlwindow (cdr entry)))
  197.       ;; Just kill the TK Top Level window.  This will cause us to get a
  198.       ;; <Destroy> back from TK, which we process with
  199.       ;; Application-Remove-Destroyed-Child!, below.
  200.       (tk-invoke-command 'DESTROY
  201.                  (Application->TKMainWindow Application)
  202.                  (list (tkwin.pathname tlwindow)))
  203.       'REMOVED))))
  204.  
  205. (define (application-remove-destroyed-child! Application to-be-unmanaged)
  206.   (if (not (valid-child? to-be-unmanaged))
  207.       (error "APPLICATION-REMOVE-DESTROYED-CHILD!: Bad UIObj" to-be-unmanaged))
  208.   (if (let ((OK? #T))
  209.     (update-locked-list! (Application%.%child-windows Application)
  210.                  (lambda (kids)
  211.                    (if (assq to-be-unmanaged kids)
  212.                    (del-assq! to-be-unmanaged kids)
  213.                    (begin (set! OK? #F)
  214.                       kids))))
  215.     OK?)
  216.       (begin
  217.     (assign-drawing-surface! to-be-unmanaged 'RETRACTED)
  218.     (forget! Application to-be-unmanaged)
  219.     'REMOVED)
  220.       'NOT-A-CHILD))
  221.  
  222. (define (make-destroy-<application>-related-objects disp registration mainwindow)
  223.   ;; This code should not have lexical reference to the
  224.   ;; Application, since it will run only after the Application
  225.   ;; has vanished.
  226.   (lambda ()
  227.     (destroy-registration registration)
  228.     (destroy-associated-tk-widgets (->xdisplay disp))
  229.     (destroy-all-sensitive-surfaces-from-display disp)
  230.     (tk-kill-application mainwindow)
  231.     'done))
  232.  
  233. (define (application-maker application-name dsp TKmain context children code)
  234.   ;; Can't be nested in MAKE-APPLICATION because it would lexically
  235.   ;; capture the list of kids!
  236.   (make-application%
  237.    (make-UIObjInternals application-add-child!
  238.             application-remove-child!
  239.             UIObj-set-context!
  240.             'invalid-application-1    ; UIObj-assign-screen-area!
  241.             'invalid-application-2    ; UIObj-assign-drawing-surface!
  242.             'invalid-application-3    ; UIObj-point-within?
  243.             'invalid-application-4    ; UIObj-rectangle-overlaps?
  244.             'invalid-application-5    ; UIObj-handle-event
  245.             'invalid-application-6    ; UIObj-get-desired-size
  246.             'invalid-application-7    ; UIObj-assigned-screen-area
  247.             'invalid-application-8    ; UIObj-used-screen-area
  248.             'invalid-application-9    ; UIObj-set-assigned-screen-area!
  249.             'invalid-application-10    ; UIObj-set-used-screen-area!
  250.             'invalid-application-11); UIObj-assign-glue!
  251.    children
  252.    code
  253.    application-name
  254.    dsp
  255.    TKMain
  256.    context))
  257.  
  258. (define (make-application application-name . kids)
  259.   (let* ((dsp (open-display))
  260.      (context (create-default-context application-name dsp))
  261.      (me 'later)
  262.      (event-string (%XMake-Event)))
  263.     (define (service-display-connection)
  264.       ;; This code is run asynchronously when data arrives from
  265.       ;; the display connection
  266.       (define (process-event event)
  267.     (for-each
  268.      (lambda (kid) (handle-event kid event))
  269.      (with-locked-list (Application%.%child-windows me)
  270.                (lambda (kids)
  271.                  (let loop ((rest kids)
  272.                     (handled-by '()))
  273.                    (cond ((null? rest) (reverse handled-by))
  274.                      ((event-within? (caar rest) event)
  275.                       (loop (cdr rest)
  276.                         (cons (caar rest) handled-by)))
  277.                      (else (loop (cdr rest) handled-by))))))))
  278.       (let loop ((nextevent (get-x-event dsp event-string)))
  279.     (if nextevent
  280.         (begin
  281.           (set! EVENT-COUNTER (+ 1 EVENT-COUNTER))
  282.          
  283.           (our-with-thread-mutex-locked
  284.            'process-event *event-processing-mutex*
  285.            (lambda ()
  286.          (if (not (tk-completely-handles-event? nextevent))
  287.              (process-event (XEvent-><Event> nextevent)))))
  288.           
  289.           (do-tk-callbacks)
  290.  
  291.           (loop (get-x-event dsp event-string)))
  292.         'done))
  293.       )
  294.     (define (idle-work)
  295.                     ; Not actually used by MIT version
  296.       (debug-print 'idle-work 'never called!!!!)
  297.       (flush-queued-output dsp)
  298.       (tk-doevents))
  299.     (let ((TKMainWindow (tk-init dsp)))
  300.       (set! me (application-maker application-name dsp TKMainWindow
  301.                   context (make-locked-list)
  302.                   service-display-connection))
  303.       (add-widget-list-for-display-number! (->xdisplay dsp))
  304.       (for-each (lambda (kid) (add-child! me kid)) kids)
  305.       (when-unreferenced
  306.        me
  307.        (make-destroy-<application>-related-objects
  308.     dsp
  309.     (fork-to-wait-on dsp service-display-connection idle-work)
  310.     TKMainWindow))
  311.       me))
  312.   )
  313.  
  314. ;;;; Interactive Geometry handlers ... low level version
  315.  
  316. (define (interactor-add-child! interact to-be-managed)
  317.   (define (find-handler event-type handlers)
  318.     ;; Returns a list of all handlers for this event-type
  319.     (let loop ((rest handlers))
  320.       (cond ((null? rest) '())
  321.         ((eq? event-type (caar rest))
  322.          (cons (cadr (car rest)) (loop (cdr rest))))
  323.         (else (loop (cdr rest))))))
  324.  
  325.   (if (not (valid-child? to-be-managed))
  326.       (error "INTERACTOR-ADD-CHILD!: Bad UIObj" to-be-managed))
  327.   (let ((sensitive-surfaces (Interactor%.sensitive-surface-map interact)))
  328.     (if (not (assq to-be-managed sensitive-surfaces))
  329.     (let* ((ss (create-sensitive-surface to-be-managed
  330.                          (Interactor%.handlers interact)))
  331.            (entry `(,to-be-managed ,ss)))
  332.       (set-Interactor%.sensitive-surface-map! interact
  333.                           (cons entry sensitive-surfaces))
  334.       (on-event! to-be-managed interact
  335.              (lambda (event)
  336.                (let* ((handlers (Interactor%.handlers interact))
  337.                   (applicable-handlers
  338.                    (find-handler (event.type event) handlers)))
  339.              (cond ((not (null? applicable-handlers))
  340.                 (for-each (lambda (handler) (handler event))
  341.                       applicable-handlers))
  342.                    ((assq #T handlers)
  343.                 => (lambda (entry) ((cadr entry) event)))
  344.                    (else #F)))
  345.                (event! interact event)))
  346.       (on-geometry-change! to-be-managed interact
  347.                    (lambda (old-screen-area new-screen-area)
  348.                  (if (and (not old-screen-area)
  349.                       (not new-screen-area))
  350.                      ;; When a drawing surface is set.
  351.                      (set! ss
  352.                        (change-sensitive-surface!
  353.                         ss
  354.                         to-be-managed))
  355.                      (set-car! (cdr entry) ss))))))))
  356.  
  357. (define (interactor-remove-child! interact was-managed)
  358.   (if (not (valid-child? was-managed))
  359.       (error "INTERACTOR-REMOVE-CHILD!: Bad UIObj" to-be-managed))
  360.   (forget! was-managed interact)
  361.   (let ((ss (assq was-managed (Interactor%.sensitive-surface-map interact))))
  362.     (if ss (destroy-sensitive-surface was-managed (cadr ss)))))
  363.  
  364. ;; Interactor Maker
  365. (define (interactor-maker alist-of-handlers)
  366.   (make-Interactor%
  367.    (make-UIObjInternals interactor-add-child!
  368.             interactor-remove-child!
  369.             UIObj-set-context! ; Defaults
  370.             UIObj-assign-screen-area!
  371.             UIObj-assign-drawing-surface!
  372.             UIObj-point-within?
  373.             UIObj-rectangle-overlaps?
  374.             UIObj-handle-event
  375.             UIObj-get-desired-size
  376.             UIObj-assigned-screen-area
  377.             UIObj-used-screen-area
  378.             UIObj-set-assigned-screen-area!
  379.             UIObj-set-used-screen-area!
  380.             'invalid)
  381.    alist-of-handlers))
  382.  
  383. (define (make-interactor objects alist-of-handlers)
  384.   ;; Constructor for interactors
  385.   (let ((me (interactor-maker alist-of-handlers)))
  386.     (for-each (lambda (object) (add-child! me object)) objects)
  387.     me)
  388.   )
  389.  
  390. ;;;; Higher level interactors
  391.  
  392. (define (handle-exposure object receiver)
  393.   ;; Receiver will be called with the exposed rectangle
  394.   (make-interactor
  395.    (list object)
  396.    `((EXPOSURE
  397.       ,(lambda (event)
  398.      (receiver
  399.       (Make-UITKRectangle (Event.Offset Event)
  400.                   (Make-Size (Event.Width Event)
  401.                      (Event.Height Event))))))))
  402.   'OK)
  403.  
  404. (define (handle-button-grab object which-buttons receiver)
  405.   ;; Receiver is called with the buttons that were actually down and a
  406.   ;; "while-grabbed" procedure which is expected to be tail-called by
  407.   ;; receiver, specifying how to handle subsequent motion events and
  408.   ;; motion termination.
  409.   (make-interactor
  410.    (list object)
  411.    `((BUTTON-PRESS
  412.       ,(lambda (event)
  413.      (decode-button-event
  414.       (Event.OS-Event event)
  415.       (lambda (type serial sent? display window root
  416.             subwindow time x y RootX RootY state
  417.             button SameScreen?)
  418.         type serial sent? display window root
  419.         subwindow time x y RootX RootY state
  420.         button SameScreen?
  421.         (if (or (= which-buttons ANYBUTTON)
  422.             (memv button which-buttons))
  423.         (let* ((should-be-result (list 'foo))
  424.                (result
  425.             (receiver event
  426.                   (lambda (on-motion at-end)
  427.                     (mouse-drag (drawing-surface object)
  428.                         on-motion)
  429.                     (at-end)
  430.                     should-be-result))))
  431.           (if (eq? result should-be-result)
  432.               'OK
  433.               (error "HANDLE-BUTTON-GRAB: Must tail call"))))))))
  434.      (POINTER-MOTION ,(lambda (e) e 'IGNORE))
  435.      (BUTTON-RELEASE ,(lambda (e) e 'IGNORE)))))
  436.  
  437. ;;;; Support code for interaction managers:
  438. ;;;; Maps from DrawingSurface to Interactor to event masks
  439.  
  440. ;; The global map ds->(<interactor>->eventmasks)
  441. (define *all-sensitive-surfaces* '())
  442.  
  443. ;; A Surface-Sensitivity specifies for a given drawing surface the
  444. ;; total event-generation mask for that surface and a list of
  445. ;; Sensitivity data structures. The mask here is the inclusive-OR of
  446. ;; all the masks in the Sensitivity data structures.
  447.  
  448. ;; A Sensitivity maps a single handler to the list of event types it
  449. ;; is intended to handle.  For GC reasons, it only weakly holds the
  450. ;; handler itself, since these are included in the global
  451. ;; *all-sensitive-surfaces* list.
  452.  
  453. (define find-sensitivity
  454.   ;; (find-sensitivity <interactor> list-of-sensitivities) =>
  455.   ;;  sensitivity or #F
  456.   ;; Or, in layman's terms, given a list of handler/description pairs
  457.   ;; and a specific handler, find the description of that handler.
  458.   (make-lookup
  459.    (lambda (obj) (weak-car (Sensitivity.%weak-<interactor> obj)))))
  460.  
  461. (define find-ss
  462.   ;; (find-ss drawing-surface list-of-Surface-Sensitivity)
  463.   ;; returns a specific Surface-Sensitivity or #F
  464.   (make-lookup
  465.    (lambda (x) (weak-car (Surface-Sensitivity.Weak-Surface x)))))
  466.  
  467. (define (record-surface-sensitivity! surface interactor mask)
  468.   (define (record-<interactor>-sensitivity! ss)
  469.     (let* ((sensitivities (surface-sensitivity.sensitivities ss))
  470.        (entry (find-sensitivity interactor sensitivities)))
  471.       (if entry
  472.       (set-sensitivity.masks! entry (cons mask (sensitivity.masks entry)))
  473.       (set-surface-sensitivity.sensitivities! ss
  474.         `(,(make-sensitivity (weak-cons interactor '()) (list mask))
  475.           ,@sensitivities))))
  476.     ;; Now tell the window system to set the event generation for this
  477.     ;; particular drawing surface
  478.     (reset-sensitivity! ss))
  479.   (let ((sensitivity-of-surface
  480.      (or (find-ss surface *all-sensitive-surfaces*)
  481.          (let ((new-entry
  482.             (make-surface-sensitivity (weak-cons surface 'ignore)
  483.                           NoEventMask '())))
  484.            (set! *all-sensitive-surfaces*
  485.              (cons new-entry *all-sensitive-surfaces*))
  486.            new-entry))))
  487.     (record-<interactor>-sensitivity! sensitivity-of-surface)))
  488.  
  489. (define delete-<interactor>!
  490.   (let ((del-sensitivity!
  491.      (del-op! (lambda (obj)
  492.             (weak-car (sensitivity.%weak-<interactor> obj)))))
  493.     (del-ss! (del-op! surface-sensitivity.sensitivities)))
  494.     (lambda (surface interactor)
  495.       (let ((ss (find-ss surface *all-sensitive-surfaces*)))
  496.     (if ss
  497.         (let ((new (del-sensitivity!
  498.             interactor
  499.             (surface-sensitivity.sensitivities ss))))
  500.           (if (null? new)
  501.           (set! *all-sensitive-surfaces*
  502.             (del-ss! surface *all-sensitive-surfaces*))
  503.           (begin
  504.             (set-surface-sensitivity.sensitivities! ss new)
  505.             ;; Now tell the window system to set the event
  506.             ;; generation for this particular drawing surface
  507.             (reset-sensitivity! ss)))))))))
  508.  
  509. ;;;; Continued ...
  510.  
  511. ;;;; Support code for interactive geometry managers, continued
  512.  
  513. ;;; When a surface is asked to generate events, we ask the toolkit to
  514. ;;; generate events if it is a toolkit window.  Otherwise, we ask the
  515. ;;; window system directly.  WE DO NOT DO BOTH.
  516. ;;;
  517. ;;; This lets people create windows from Scheme which don't have
  518. ;;; related toolkit windows, even though we haven't done that yet.
  519.  
  520. (define (reset-sensitivity! surface-sensitivity)
  521.   ;; This tells the window system to actually update the event
  522.   ;; generation mask for a given drawing surface.
  523.   ;; NOTE: Whoever calls this is responsible for guaranteeing that the
  524.   ;;       surface (which is weakly held) still exists.
  525.   (let ((original (surface-sensitivity.mask surface-sensitivity)))
  526.     (let loop ((s 0)
  527.            (rest (surface-sensitivity.sensitivities
  528.               surface-sensitivity)))
  529.       (if (null? rest)
  530.       (begin
  531.         (set-surface-sensitivity.mask! surface-sensitivity s)
  532.         (if (not (= s original))
  533.         (let ((Surface
  534.                (weak-car
  535.             (surface-sensitivity.Weak-Surface
  536.              surface-sensitivity))))
  537.           (if Surface
  538.               (let ((TKWindow (DrawingSurface.ToolKitWindow Surface))
  539.                 (UITKWindow (DrawingSurface.UITKWindow Surface)))
  540.             (if TKWindow
  541.                 (tk-generate-Scheme-event
  542.                  s
  543.                  (ToolKitWindow.TK-Window TKWindow))
  544.                 (Generate-Events! UITKWindow s)))))))
  545.       (loop (apply bit-or s (sensitivity.masks (car rest)))
  546.         (cdr rest))))))
  547.  
  548. (define (create-sensitive-surface UIObject handlers)
  549.   ;; Given an object, return the Sensitive-Surface that will generate
  550.   ;; these events.
  551.   (let ((surface (Drawing-Surface UIObject)))
  552.     (if (DrawingSurface? surface)
  553.     (begin
  554.       (record-surface-sensitivity! surface UIObject
  555.         (if (null? handlers)
  556.         0
  557.         (apply bit-or (map handler->sensitivity handlers))))
  558.       (make-sensitive-surface surface handlers))
  559.     (make-sensitive-surface #F handlers))))
  560.  
  561. (define (change-sensitive-surface! sensitive-surface UIObject)
  562.   ;; If the drawing surface for an object changes, remove the old
  563.   ;; record of handlers for that object (recorded on the old drawing
  564.   ;; surface) and enter a new record on the current drawing surface.
  565.   (let ((surface (Drawing-Surface UIObject))
  566.     (old-surface
  567.      (sensitive-surface.DrawingSurface sensitive-surface)))
  568.     (if (eq? surface old-surface)
  569.     sensitive-surface
  570.     (begin
  571.       (if (DrawingSurface? old-surface)
  572.           (destroy-sensitive-surface UIObject sensitive-surface))
  573.       (create-sensitive-surface
  574.        UIObject (sensitive-surface.handlers sensitive-surface))))))
  575.  
  576. (define (destroy-sensitive-surface interactor sensitive-surface)
  577.   (let ((surface
  578.      (sensitive-surface.DrawingSurface sensitive-surface)))
  579.     (delete-<interactor>! surface interactor)))
  580.  
  581. (define (destroy-all-sensitive-surfaces-from-display display)
  582.   (set! *all-sensitive-surfaces*
  583.     ((list-deletor!
  584.       (lambda (surface-sensitivity)
  585.         (let ((surface
  586.            (weak-car (surface-sensitivity.Weak-Surface
  587.                   surface-sensitivity))))
  588.           (or (not surface)
  589.           (eq? display
  590.                (Application->display
  591.             (ToolKitWindow.Application
  592.              (drawingsurface.ToolKitWindow surface))))))))
  593.      *all-sensitive-surfaces*)))
  594.  
  595. ;;;; Support for simplified user interface building.  We provide a
  596. ;;;; default application, and a procedure for adding new children to
  597. ;;;; it.
  598.  
  599. (define *the-default-application*
  600.   (make-application "SWAT"))
  601.  
  602. ;;; (Swat-Open obj1 ['-title "title1"] obj2 ['-title "title2"] ...)
  603. ;;; adds obj1, obj2, ... to the default application with the window
  604. ;;; titled by the string specified with the -title option.
  605. ;;; If no title option is specified, the window title will be the
  606. ;;; title of the application
  607.  
  608. (define (swat-open . objects-and-title-options)
  609.   (apply swat-open-in-application
  610.      *the-default-application*
  611.      objects-and-title-options))
  612.  
  613. ;;; (SWAT-OPEN-IN-APPLICATION app obj1 ['-title "title1"] obj2 ['-title "title2"] ...)
  614. ;;; is like swat-open, except for the speficifed application.
  615.  
  616. (define (swat-open-in-application app . objects-and-title-options)
  617.   (let loop ((more-to-show objects-and-title-options))
  618.     (if (null? more-to-show)
  619.     'OK
  620.     (let ((next-obj (car more-to-show))
  621.           (after-next (if (null? (cdr more-to-show))
  622.                   #F
  623.                   (cadr more-to-show))))
  624.       ;;look for -title following the object to show
  625.       (if (eq? after-next '-title)
  626.           (let ((specified-title
  627.              (if (null? (cddr more-to-show))
  628.              (error
  629.               "-title option given and no title specified -- SWAT-OPEN"
  630.               objects-and-title-options)
  631.              (caddr more-to-show))))
  632.         ;;if -title is there, next thing must be a string
  633.         (if (string? specified-title)
  634.             (add-child! app
  635.                 next-obj
  636.                 specified-title)
  637.             (error "specified title is not a string -- SWAT-OPEN"
  638.                specified-title))
  639.         (loop (cdddr more-to-show)))
  640.           ;;no -title specified -- use default naming
  641.           (begin (add-child! app next-obj)
  642.              (loop (cdr more-to-show))))))))
  643.  
  644. (define (swat-close . objs)
  645.   (for-each (lambda (obj) (remove-child! *the-default-application* obj))
  646.         objs)
  647.   'closed)