[plt-scheme] Re: on-event on snips seems a little weird

From: Danny Yoo (dyoo at cs.wpi.edu)
Date: Thu Jun 19 03:04:39 EDT 2008

On Thu, Jun 19, 2008 at 1:55 AM, Danny Yoo <dyoo at cs.wpi.edu> wrote:
> I'm trying to get a snip to do something when I hover my mouse over
> it; I suspect I need to have the snip somehow have keyboard focus.  Is
> there a way to get a snip to get events even if it doesn't have
> keyboard focus?


Ah, ok.  I see how syncheck is doing it now.  Ok, that works well
enough.  I end up firing off the events manually from the enclosing
editor, so that I get to control when the snip gets the event,
regardless of focus.


Here's my example, just in case it comes in handy to others.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#lang scheme/gui


;; event-in-snip? mouse-event snip -> void
;; Returns true if the mouse event is hovering over the snip.
;; If the snip isn't attached to an admin, or isn't visible, returns #f.
(define (event-hovering-over-snip? an-event a-snip)
  (cond
    [(and (send a-snip get-admin)
          (send (send a-snip get-admin) get-dc))
     (let ([dc (send (send a-snip get-admin) get-dc)]
           [editor (send (send a-snip get-admin) get-editor)])
       (let-values ([(x-box y-box) (values (box 0) (box 0))]
                    [(w-box h-box) (values (box 0) (box 0))])
         (send editor get-snip-location a-snip x-box y-box)
         (send a-snip get-extent dc
               (unbox x-box) (unbox y-box) w-box h-box #f #f #f #f)

         (and (<= (unbox x-box) (send an-event get-x)
                  (+ (unbox x-box) (unbox w-box)))
              (<= (unbox y-box) (send an-event get-y)
                  (+ (unbox y-box) (unbox h-box))))))]
    [else
     #f]))


;; event-editor-mixin: editor<%> -> editor<%>
;; Adds an interface for doing event listening to an editor.
(define (event-editor-mixin super%)
  (class super%
    (define listeners (make-weak-hasheq))

    (define/public (add-event-listener a-listener)
      (hash-set! listeners a-listener #t))

    (define/override (on-event event)
      (for ([listener (in-hash-keys listeners)])
        (with-handlers ([exn:fail? (lambda (exn) (void))])
          (listener event)))
      (super on-event event))

    (super-new)))


;; exercising code, not really a test case.
(define (test)
  (define my-editor-snip%
    (class editor-snip%
      (define over? #f)

      (define/public (handle-event an-event)
        (cond [(and (not over?) (event-hovering-over-snip? an-event this))
               (printf "over~n")
               (set! over? #t)]
              [(and over? (not (event-hovering-over-snip? an-event this)))
               (printf "not over~n")
               (set! over? #f)]))

      (super-new)))

  (define f (new frame% [label ""]))
  (define e (new (event-editor-mixin text%)))
  (define c (new editor-canvas% [parent f] [editor e]))

  (define snip (make-object my-editor-snip%))
  (send e add-event-listener
        (lambda (evt)
          (send snip handle-event evt)))

  (send (send snip get-editor)
        insert "hi")

  (send e insert snip)

  (send f show #t))


Posted on the users mailing list.