gui/list-zipper.scm
#|
A nonempty list of values with a cursor.  We use this for managing
proof checkpoints (forward and back buttons).
|#
(module list-zipper mzscheme
  (require (lib "class.ss"))
  
  (provide make-zipper zipper<%>)
  
  (define (make-zipper lst)
    (if (null? lst)
        #f
        (new list-zipper% [items lst])))
  
  (define zipper<%> (interface () get-current-item has-next? cursor-forward! cursor-backward!))
  
  (define list-zipper%
    (class* object% (zipper<%>)
      (field [left null])
      (init-field items)
      
      ;; Produce the current item.
      (define/public (get-current-item)
        (car items))
      
      (define/public (has-next?)
        (not (null? (cdr items))))
      
      (define/public (has-prior?)
        (not (null? left)))
      
      ;; move the cursor forward if there are any more items,
      ;; otherwise leave state as is.
      (define/public (cursor-forward!)
        (unless (null? (cdr items))
          (set! left (cons (car items) left))
          (set! items (cdr items))))
      
      (define/public (cursor-backward!)
        (unless (null? left)
          (set! items (cons (car left) items))
          (set! left (cdr left))))
      
      (super-new)
      ))
  
  )