text: Module:       scribble
  Author:       Scott McKay
  Synopsis:     Simple scribble application
  Copyright:    Original Code is Copyright (c) 1995-2004 Functional Objects, Inc.
                All rights reserved.
  License:      See License.txt in this distribution for details.
  Warranty:     Distributed WITHOUT WARRANTY OF ANY KIND
  
  /// Simple scribble application
  
  define class <scribble-pane> (<drawing-pane>)
    slot scribble-segment = #f;
    constant slot scribble-segments = make(<stretchy-vector>);
    constant slot scribble-popup-menu-callback = #f,
      init-keyword: popup-menu-callback:;
  end class <scribble-pane>;
  
  define method draw-segment
      (medium :: <medium>, segment :: <sequence>) => ()
    draw-polygon(medium, segment, closed?: #f, filled?: #f)
  end method draw-segment;
  
  // Draw the scribble as several unconnected polylines
  define method handle-repaint
      (sheet :: <scribble-pane>, medium :: <medium>, region :: <region>) => ()
    ignore(region);
    for (segment in sheet.scribble-segments)
      draw-segment(medium, segment)
    end
  end method handle-repaint;
  
  define method handle-button-event
      (sheet :: <scribble-pane>,
       event :: <button-press-event>,
       button == $left-button) => ()
    sheet.scribble-segment := make(<stretchy-vector>);
    add-scribble-segment(sheet, event.event-x, event.event-y)
  end method handle-button-event;
  
  define method handle-button-event
      (sheet :: <scribble-pane>,
       event :: <pointer-drag-event>,
       button == $left-button) => ()
    add-scribble-segment(sheet, event.event-x, event.event-y)
  end method handle-button-event;
  
  define method handle-button-event
      (sheet :: <scribble-pane>,
       event :: <button-release-event>,
       button == $left-button) => ()
    when (add-scribble-segment(sheet, event.event-x, event.event-y))
      add!(sheet.scribble-segments, sheet.scribble-segment)
    end;
    sheet.scribble-segment := #f
  end method handle-button-event;
  
  define method handle-button-event
      (sheet :: <scribble-pane>,
       event :: <button-release-event>,
       button == $right-button) => ()
    let popup-menu-callback = scribble-popup-menu-callback(sheet);
    when (popup-menu-callback)
      popup-menu-callback(sheet, event.event-x, event.event-y)
    end
  end method handle-button-event;
  
  define method add-scribble-segment
      (sheet :: <scribble-pane>, x, y) => (did-it? :: <boolean>)
    let segment = sheet.scribble-segment;
    // The app can generate drag and release events before it has ever
    // seen a press event, so be careful
    when (segment)
      add!(segment, x);
      add!(segment, y);
      draw-segment(sheet-medium(sheet), segment);
      #t
    end
  end method add-scribble-segment;
  
  define method clear-surface (sheet :: <scribble-pane>) => ()
    sheet.scribble-segments.size := 0;
    clear-box*(sheet, sheet-region(sheet))
  end method clear-surface;
  
  
  /// A top-level frame
  define frame <scribble-frame> (<simple-frame>)
    pane surface (frame)
      make(<scribble-pane>,
           popup-menu-callback: method (sheet, x, y)
                                  let frame = sheet-frame(sheet);
                                  popup-scribble-menu(frame, x, y)
                                end,
           width:  300, max-width:  $fill,
           height: 200, max-height: $fill);
    pane file-menu (frame)
      make(<menu>,
           label: "File",
           children: vector(make(<menu-button>,
                                 label: "&Clear",
                                 selection-mode: #"none",
                                 activate-callback: method (button)
                                                      clear-surface(frame.surface)
                                                    end),
                            make(<menu-button>,
                                 label: "E&xit",
                                 selection-mode: #"none",
                                 activate-callback: method (button)
                                                      exit-frame(sheet-frame(button))
                                                    end)));
    pane scribble-popup-menu (frame)
      make(<menu>,
           owner: frame.surface,
           children: vector(make(<menu-button>,
                                 label: "&Clear",
                                 selection-mode: #"none",
                                 activate-callback: method (button)
                                                      ignore(button);
                                                      clear-surface(frame.surface)
                                                    end)));
    layout (frame) frame.surface;
    menu-bar (frame)
      make(<menu-bar>, children: vector(frame.file-menu));
  end frame <scribble-frame>;
  
  define method popup-scribble-menu
      (frame :: <scribble-frame>, x :: <integer>, y :: <integer>) => ()
    let menu = frame.scribble-popup-menu;
    display-menu(menu, x: x, y: y)
  end method popup-scribble-menu;
  