#lang racket/gui ;;; animated-canvas.rkt ;;; Copyright (c) 2007-2010 M. Douglas Williams ;;; ;;; This program is free software: you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation, either version 3 of the License, or ;;; (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program. If not, see <http://www.gnu.org/licenses/>. ;;; ;; ------------------------------------------------------------------------------ ;;; ;;; Version Date Description ;;; 1.0.0 12/28/07 Initial release. (MDW) ;;; 1.2.0 09/02/08 Updated for PLT Scheme 4.0. (MDW) ;;; 1.2.1 09/25/08 Added no-autoclear and transparent processing. (MDW) ;;; 1.2.2 09/25/08 Added resizing. (MDW) ;;; 2.0.0 06/01/10 Updated for Racket. (MDW) ;;; class animated-canvas% ;;; Implements a canvas that supports offscreen bitmaps for animation. Works ;;; like a standard canvas% object, but the device context points to the ;;; appropriate bitmap-dc% for drawing. A call to swap-bitmaps swaps the ;;; bitmaps and paits the old one. [The device context is not valid across ;;; calls to swap-bitmap.] (define animated-canvas% (class canvas% ;; Init parameters (shadows those from csnvas%) ;; so we can manipulate no-autoclear (init parent) (init (style '())) ;; Save animated-canvas no-autoclear and transparent style (define no-autoclear? (if (memq 'no-autoclear style) #t #f)) (define transparent? (if (memq 'transparent style) #t #f)) ;; Instantiate superclass with updated no-autoclear and transparent ;; arguments (set! style (if no-autoclear? style (cons 'no-autoclear style))) (set! style (remq 'transparent style)) (super-instantiate (parent) (style style)) ;; Inherit superclass methods (inherit get-client-size) (inherit refresh) ;; Create bitmaps (define bitmap-vector (let-values (((w h) (get-client-size))) (build-vector 2 (lambda (i) (make-object bitmap% w h))))) ;; Create from and to bitmap indices (define from-bitmap 0) (define to-bitmap 1) ;; Create from and to device contexts (define from-bitmap-dc (make-object bitmap-dc%)) (define to-bitmap-dc (make-object bitmap-dc%)) ;; Initialize from and to indices (send from-bitmap-dc set-bitmap (vector-ref bitmap-vector from-bitmap)) (send to-bitmap-dc set-bitmap (vector-ref bitmap-vector to-bitmap)) ;; Clear the from bitmap so the canvas initially is white. (send from-bitmap-dc clear) (send to-bitmap-dc clear) ;; Swap the bitmaps (define/public (swap-bitmaps) ;; Reset bitmap-dc instances (send from-bitmap-dc set-bitmap #f) (send to-bitmap-dc set-bitmap #f) ;; Swap bitmap indices (set! from-bitmap (modulo (+ from-bitmap 1) 2)) (set! to-bitmap (modulo (+ to-bitmap 1) 2)) ;; Set bitmap-dc instances (send from-bitmap-dc set-bitmap (vector-ref bitmap-vector from-bitmap)) (send to-bitmap-dc set-bitmap (vector-ref bitmap-vector to-bitmap)) ;; Check for client resize and make new bitmap if necessary (let-values (((w h) (get-client-size))) (let ((bitmap (send to-bitmap-dc get-bitmap))) (unless (and (= w (send bitmap get-width)) (= h (send bitmap get-height))) (vector-set! bitmap-vector to-bitmap (make-object bitmap% w h)) (send to-bitmap-dc set-bitmap (vector-ref bitmap-vector to-bitmap)) ))) ;; Clear the to-bitmap (unless no-autoclear? (send to-bitmap-dc clear)) ;; Refresh the canvas (refresh) (yield)) ;; Override the superclass get-dc method to return the bitmap-dc of the ;; to bitmap. (define/override-final (get-dc) to-bitmap-dc) ;; Override the superclass on-paint method to move the from-bitmap to the ;; canvas. (define/override-final (on-paint) (let ((canvas-dc (super get-dc))) (send canvas-dc draw-bitmap (vector-ref bitmap-vector from-bitmap) 0 0))))) ;;; Module Contracts (provide (all-defined-out))