
The _Virtual Playing Cards Library_
-----------------------------------

Load the virtual card library with
   (require (lib "cards.ss" "games" "cards"))

The _cards.ss_ module defines the following procedures:

> (make-table [title-string] [w] [h]) returns a table named by
      `title-string' that is `w' cards wide and `h' cards high. A
      table is an frame% object, with extra methods described
      below. The table is not intially shown; (send table show #t)
      shows it. The arguments are optional, with the default values
      being "Cards", 7, and 3.

> (make-deck) returns a list of 52 cards, one for each suit-value 
      combination. The cards are all face-down, sorted lowest-suit
      then lowest-value. A card is an object, with methods described 
      below. A card can only be on one table at a time.

> (shuffle-list list n) shuffles the given `list' `n' times, returning
      the new list. Shuffling simulates an actual shuffle: the list is
      split into halves which are merged back together by repeatedly
      pulling the top card off one of the halves, randomly selecting
      one half or the other. According to some mathematical theorem, 7
      is a large enough `n' to get a perfect shuffle.

plus a structure:

>  struct:region :: (struct region (x y w h label callback))
      `x', `y', `w', `h' are coordinates on the table,
      `label' is a string to label the region or #f for no label. When the
        region is added to a table, the label is drawn in 12-point (about
        12-pixel) text, centered horizontally and 5 pixels down from the 
        region's top outline. If label is #f, no label or box is drawn 
        for the region.
      `callback' is a procedure that takes a list of cards that were
        dragged to the region; if callback is #f, the region is not
        active (i.e., dragging cards to the region doesn't highlight the
        region box). The region remains hilited until the callback returns.
     The only mutator on the structure that is available is set-region-callback!.
     The structure created by make-region actually has extra hidden fields.

>  (make-button-region x y w h label callback) - returns a region like
     one made by make-region, but the is drawn slightly differently and
     it reacts differently to cards and the mouse. The label is drawn
     in the middle of the box instead of at the top, and the callback is
     called with no arguments when the user clicks the region (instead
     of dragging cards to the region).

>  (make-background-region x y w h paint-callback) - returns a region that
     does not respond to mouse clicks, but which has a general paint
     callback. The `paint-callback' function is called with five
     arguments: a drawing context, x and y offsets, and the width and
     height (which are always `w' and `h'). The x and y offsets can be
     different than the supplied `x' and `y' when part of the table is
     drawn offscreen. Regions are painted in the order that they are
     added to a table, and all regions are painted before any card.
     The `paint-callback' procedure should not assume a particular
     state for the drawing context (i.e.,current brush or pen), and it
     should restore any modified drawing context state before
     returning.

  In additionto the above function, the _region-interactive-callback_
  and _set-region-interactive-callback!_ procedures get and set a
  callback procedure that is invoked when a region is [un]hilited as
  the user drags a set of cards to the region. The callback is
  provided two arguments: a boolean indicating whether the region is
  hilited, and the list of cards being dragged. Like region-callback,
  the default is #f, which indicates that the region has no
  interactive callback (but does not affect whether the region is
  hilited as cards are dragged).


Table methods: [in addition to standard frame% methods]
--------------

> add-card :: (send t add-card card x y) - adds `card' to the table
        with its top-left corner at (`x',`y') in table pixels.

> add-cards :: (send t add-cards cards x y [offset-proc]) - adds list
        of cards at (`x',`y'); the optional `offset-proc' procedure is
        called with an index i (counting from 0) and should return two
        values: `dx' and `dy'; the ith card is the placed at `x'+`dx'
        and `y'+`dy'. The cards are added in order on top of cards
        already one the table such that the first card in `cards' is
        topmost.

> add-cards-to-region :: (send t add-cards-to-region cards r) - adds
        `cards' to fill the region `r', fanning them out bottom-right
        to top-left. The region `r' does not have to be added to the
        table.


> remove-card :: (send t remove-card card) - removes `card' from the
        table

> remove-cards :: (send t remove-cards cards) - removes `cards' from
        the table


> move-card :: (send t move-card card x y)
> move-cards :: (send t move-cards cards x y [offset-proc])
> move-cards-to-region :: (send t move-cards-to-region cards r)
        These are like the `add-card' methods, except that they move
        cards already on the table. The movement of the cards is
        animated. All of the cards are moved at once.


> flip-card :: (send t flip-card card) - flips `card' over with
        animation.

> flip-cards :: (send t flip-cards cards) - flips all `cards' over (at
        once) with animation.

> card-face-up :: (send t card-face-up card)
> cards-face-up :: (send t cards-face-up cards)
> card-face-down :: (send t card-face-down card)
> cards-face-down :: (send t cards-face-down cards)
        These are like `flip-card', but only cards that are not
        already face up/down are flipped.

> card-to-front :: (send t card-to-front card) - moves `card' in front
        of all other cards.

> card-to-back :: (send t card-to-back card) - moves `card' behind all
        other cards.

> stack-cards :: (send t stack-cards cards) - the first card in
        `cards' is not moved; the second card is moved to follow
        immediately behind the first one, then (send t stack-cards
        (cdr cards)) is called. If `cards' is empty or contains only
        one card, no action is taken.


> table-width :: (send t table-width) - returns the width of the table
        in pixels.

> table-height :: (send t table-height) - returns the height of the
        table in pixels.


> begin-card-sequence :: (send t begin-card-sequence) - starts a
        sequence of card or region changes that won't be animated or
        updated until the end of the sequence.

> end-card-sequence :: (send t end-card-sequence) - ends a sequence;
        begin-/end- pairs can be nested.
   

> add-region :: (send t add-region r) - adds the region `r' to the
        table; regions are drawn in the order that they are added to
        the table, and when a region added later is hilighted, it can
        obscure regions added earlier.

> remove-region :: (send t remove-region r) - removes the region `r'
        from the table.

> hilite-region :: (send t hilite-region r) - manual hilite (usually
        for animation)

> unhilite-region :: (send t unhilite-region r) - manual unhilite
        (usually for anaimation)


> set-button-action :: (send t set-button-action which action) - sets
        the way that a mouse click is handled. The which argument must
        be 'left, 'middle, or 'right. The action argument must be one
        of:
           'drag/one - drag only the clicked-on card
           'drag-raise/one - like drag/one, but raise the card to the
                  top on a click
           'drag/above - drag the card along with any card on top of the
                  card (i.e., more towards the front and overlapping with
                  the card). The on-top-of relation is closed transitively.
           'drag-raise/above
           'drag/below - drag the card along with any card underneath the
                  card (i.e., more towards the back and overlapping with
                  the card). The underneath relation is closed transitively.
           'drag-raise/below
        The initial settings are:
           'left - 'drag-raise/above
           'middle - 'drag/one
           'right - 'drag/below

> set-double-click-action :: (send t set-double-click-action) - sets
        the procedure to be called when a card is double-clicked. The
        procedure is called with the double-clicked card. The default
        procedure flips the cards along with its on-top-of cards,
        raises the cards, and reverses the front-to-back order of the
        cards

> set-single-click-action :: (send t set-single-click-action) - sets
        the procedure to be called when a card is single-clicked,
        after the button action is initiated. (If the card is
        double-clicked, this action is inoked for the first click,
        then the double-click action is invoked.) The default action
        does nothing.

> pause :: (send t pause n-secs) - pauses, allowing the table display
        to be updated (unless a sequence is active), but does not let
        the user click on the cards.

> animated :: (send t animated) - returns #t is animation is on.
> animated :: (send t animated on?) - enables/disables animation.


Card methods:
-------------

> card-width :: (send c card-width) - returns the width of the card in
       pixels.

> card-height :: (send c card-height) - returns the height of the card
       in pixels.  All cards have the same width and height.

> flip :: (send c flip) - flips the card without animation. This is
       useful for flipping a card before it is added to a table.

> face-up :: (send c face-up)
> face-down :: (send c face-down)
       Makes the card face up/down without animation.

> face-down? :: (send c face-down?) - #t if the card is currently
       face down.

> get-suit-id :: (send c get-suit-id) - 1, 2, 3, or 4 (see `get-suit'
       for corresponding suit names)

> get-suit :: (send c get-suit) - 'clubs, 'diamonds, 'hearts, or
       'spades

> get-value :: (send c get-value) - 1 (Ace), 2, ... 10, 11 (Jack), 12
       (Queen), or 13 (King)
   
> user-can-flip :: (send c user-can-flip)
> user-can-flip :: (send c user-can-flip can?)
       Determines whether the user can flip the card interactively,
       usually by double-clicking it. Initially #t.

> user-can-move :: (send c user-can-move)
> user-can-move :: (send c user-can-move can?)
       Determines whether the user can move the card interactively,
       usually by dragging it. Disabling moves has the side-effect of
       disabling raises and double-clicks. Initially #t.

> snap-back-after-move :: (send c snap-back-after-move)
> snap-back-after-move :: (send c snap-back-after-move on?)
       Assuming user can move the card interactively, determines
       whether the card stays where the user dragged it or snaps back
       to its original place. Initially #f.

> stay-in-region :: (send c stay-in-region r)
> stay-in-region :: (send c stay-in-region)
       If `r' is a region, the user cannot move the card out of r.
       Initially #f.

> home-region :: (send c home-region r)
> home-region :: (send c home-region)
       If `r' is a region, the user can move the card freely within the
       region, but it snaps back if moved completely out of the
       region. If moved partly out of the region, the card is moved
       enough to get completely back in. Initially #f.

> copy :: (send c copy) - makes a new card with the same suit and
       value.
