home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d502 / cells.lha / CELLS / CELLSSource.lzh / cView.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  11KB  |  470 lines

  1. /*
  2.  *  CELLS       An Implementation of the WireWorld cellular automata
  3.  *              as described in Scientific American, Jan 1990.
  4.  *
  5.  *              Copyright 1990 by Davide P. Cervone.
  6.  *  You may use this code, provided this copyright notice is kept intact.
  7.  *  See the CELLS.HELP file for complete information on distribution conditions.
  8.  */
  9.  
  10. /*
  11.  *  File:  cView.c          Handles the VIEW mode of the Load PArt requester.
  12.  */
  13.  
  14.  
  15. #include "cGadget.h"
  16. #include "cRequest.h"
  17. #include "cReqLP.h" 
  18. #include "cParts.h"
  19.  
  20. #define IMAGEW          (LP_PNAMEW-2)
  21. #define IMAGEH          (LP_PNAMEH-2)
  22. #define BOXSIZE         4
  23. #define BOXW            ((IMAGEW-3)/BOXSIZE)
  24. #define BOXH            ((IMAGEH-3)/BOXSIZE)
  25.  
  26. #define SCROLLDELAY     6
  27.  
  28. #define SLIDERINFO      ((struct PropInfo *)(theList->Slider->SpecialInfo))
  29.  
  30. /*
  31.  *  Image structure used to draw the small picture of the parts
  32.  */
  33.  
  34. static struct Image ViewImage =
  35.    {1,1, IMAGEW,IMAGEH,SCREEND, NULL, 0xFF, 0x00, NULL};
  36.  
  37. int Viewing;                    /* TRUE if in VIEW mode */
  38. static LISTINFO *ActiveList;    /* which list's slider is active */
  39.  
  40.  
  41. extern void LPGadgetUp(),LPGadgetDown(),DoListMouse();
  42.  
  43.  
  44. /*
  45.  *  PartToImage()
  46.  *
  47.  *  Clear the image to the background color
  48.  *  If the part fits within the image, center it, otherwise, clip it
  49.  *  Set the drawing mode
  50.  *  for each cell in the part
  51.  *    if the cell is within the visible area of the part within the image
  52.  *      if the cell is non-zero
  53.  *        fill in the cell in the image
  54.  */
  55.  
  56. static void PartToImage(rp,thePart)
  57. struct RastPort *rp;
  58. PART *thePart;
  59. {
  60.    register short X,Y;
  61.    register UBYTE *theByte = thePart->Data;
  62.    short x,y,w,h;
  63.    short dx,dy;
  64.    short Bx,By;
  65.  
  66.    SetRast(rp,BACKGROUND);
  67.    if (thePart->w > BOXW)
  68.    {
  69.       x = (thePart->w - BOXW) / 2;
  70.       w = BOXW + x;
  71.       dx = 2;
  72.    } else {
  73.       x = 0;
  74.       w = thePart->w;
  75.       dx = (BOXW - w) / 2 * BOXSIZE + 2;
  76.    }
  77.    if (thePart->h > BOXH)
  78.    {
  79.       y = (thePart->h - BOXH) / 2;
  80.       h = BOXH + y;
  81.       dy = 2;
  82.    } else {
  83.       y = 0;
  84.       h = thePart->h;
  85.       dy = (BOXH - h) / 2 * BOXSIZE + 2;
  86.    }
  87.    
  88.    SetDrMd(rp,JAM1);
  89.    for (Y=0; Y<thePart->h; Y++)
  90.    {
  91.       for (X=0; X<thePart->w; X++,theByte++)
  92.       {
  93.          if (X >= x && X < w && Y >= y && Y < h)
  94.          {
  95.             if (*theByte)
  96.             {
  97.                Bx = dx + BOXSIZE * (X - x);
  98.                By = dy + BOXSIZE * (Y - y);
  99.                SetAPen(rp,(int)(*theByte));
  100.                RectFill(rp,Bx,By,Bx+BOXSIZE-2,By+BOXSIZE-2);
  101.             }
  102.          }
  103.       }
  104.    }
  105. }
  106.  
  107.  
  108. /*
  109.  *  SetViewImage()
  110.  *
  111.  *  Set up the list to point to this item
  112.  *  If the item exists
  113.  *    set the list to select this item
  114.  *    get the part's image
  115.  *    show the part's name
  116.  *  otherwise
  117.  *    clear the image area and name
  118.  *  If the Load Part requester is up, refresh the gadgets
  119.  */
  120.  
  121. static void SetViewImage(theList,theItem)
  122. LISTINFO *theList;
  123. LISTITEM *theItem;
  124. {
  125.    theList->ItemTop = theItem;
  126.    if (theItem)
  127.    {
  128.       theList->ItemSelect = theItem;
  129.       theList->SelectedItem = theList->TopItem;
  130.       PartToImage(irp,theItem);
  131.       SetStringInfo(theList->Name,theItem->Name);
  132.    } else {
  133.       SetRast(irp,FOREGROUND);
  134.       SetStringInfo(theList->Name,"");
  135.    }
  136.    if (ActiveRequest)
  137.    {
  138.       RefreshGList(theList->Gadget,myWindow,theList->Request,1);
  139.       RefreshGList(theList->Name,myWindow,theList->Request,1);
  140.    }
  141. }
  142.  
  143.  
  144. /*
  145.  *  UpdateViewSlider()
  146.  *
  147.  *  Calculate the new body and pot values for the current list position
  148.  *  If the Load Part requester is up,
  149.  *    if the values are not the current ones, update the slider gadget
  150.  *  otherwise
  151.  *   set the slider values to the new values
  152.  */
  153.  
  154. void UpdateViewSlider(theList)
  155. LISTINFO *theList;
  156. {
  157.    int Pot,Body;
  158.  
  159.    if (theList->ListLen > 1)
  160.    {
  161.       Body = 0xFFFF / theList->ListLen;
  162.       Pot  = 0xFFFF * theList->TopItem / (theList->ListLen - 1);
  163.    } else {
  164.       Body = 0xFFFF;
  165.       Pot = 0;
  166.    }
  167.  
  168.    if (ActiveRequest)
  169.    {
  170.       if (Body != SLIDERINFO->VertBody || Pot != SLIDERINFO->VertPot)
  171.           NewModifyProp(theList->Slider,myWindow,theList->Request,
  172.              SLIDERINFO->Flags,0,Pot,0,Body,1);
  173.    } else {
  174.       SLIDERINFO->VertBody = Body;
  175.       SLIDERINFO->VertPot  = Pot;
  176.    }
  177. }
  178.  
  179.  
  180. /*
  181.  *  RemoveViewItem()
  182.  *
  183.  *  Decrease the list length
  184.  *  If the deleted item is the head of the list, set the head to the next one
  185.  *  if the deleted item is the displayed item,
  186.  *    select the next item in the list, if possible, and the previous
  187.  *    item if not, and NULL, if no previous or next item.
  188.  *  otherwise, if the deleted item is before the top item in the list,
  189.  *    decrement the top item counter to reflect the deletion
  190.  *  Unselect the item, if it was selected
  191.  *  Show the new selected item
  192.  *  Update the sliders to the new position and length
  193.  */
  194.  
  195. void RemoveViewItem(theList,theItem)
  196. LISTINFO *theList;
  197. LISTITEM *theItem;
  198. {
  199.    LISTITEM *ItemTop = theList->ItemTop;
  200.  
  201.    theList->ListLen--;
  202.    if (theItem == theList->Item) theList->Item = theItem->Prev;
  203.    if (theItem == ItemTop)
  204.    {
  205.       if (ItemTop->Prev)
  206.       {
  207.          ItemTop = ItemTop->Prev;
  208.       } else {
  209.          ItemTop = ItemTop->Next;
  210.          if (theList->TopItem) theList->TopItem--;
  211.       }
  212.    } else if (ItemBeforeTop(theItem,ItemTop)) {
  213.       theList->TopItem--;
  214.    }
  215.  
  216.    if (theList->ItemSelect) theList->ItemSelect->Flags &= ~LI_SELECTED;
  217.    theList->ItemSelect = NULL;
  218.    SetViewImage(theList,ItemTop);
  219.    UpdateViewSlider(theList);
  220. }
  221.  
  222.  
  223. /*
  224.  *  SetView()
  225.  *
  226.  *  Initialise the list manager to use the given list
  227.  *  setup the image of the current item
  228.  *  update the sliders to their new position and size
  229.  */
  230.  
  231. void SetView(theGadget,theItem,SelectItem)
  232. struct Gadget *theGadget;
  233. LISTITEM *theItem,*SelectItem;
  234. {
  235.    LISTINFO *theList = (LISTINFO *)theGadget->UserData;
  236.  
  237.    theItem = InitList(theList,theItem,SelectItem);
  238.    SetViewImage(theList,theItem);
  239.    UpdateViewSlider(theList);
  240. }
  241.  
  242.  
  243. /*
  244.  *  DoScrollUp()
  245.  *
  246.  *  while the arrow is being held down
  247.  *    if there are more parts to scroll
  248.  *      move to the next part and display it
  249.  *      update the sliders
  250.  *      delay (if necessary)
  251.  */
  252.  
  253. void DoViewScrollUp(theList,theGadget,theMessage)
  254. LISTINFO *theList;
  255. struct Gadget *theGadget;
  256. struct IntuiMessage *theMessage;
  257. {
  258.    while (theGadget->Flags & SELECTED)
  259.    {
  260.       if (theList->TopItem)
  261.       {
  262.          theList->TopItem--;
  263.          SetViewImage(theList,theList->ItemTop->Next);
  264.          RefreshGList(theList->Gadget,myWindow,theList->Request,1);
  265.          UpdateViewSlider(theList);
  266.          #if SCROLLDELAY > 0
  267.             Delay(SCROLLDELAY);
  268.          #endif
  269.       }
  270.    }
  271. }
  272.  
  273. /*
  274.  *  DoScrollDown()
  275.  *
  276.  *  while the arrow is being held down
  277.  *    if there are more parts to scroll
  278.  *      move to the next part and display it
  279.  *      update the sliders
  280.  *      delay (if necessary)
  281.  */
  282.  
  283. void DoViewScrollDown(theList,theGadget,theMessage)
  284. LISTINFO *theList;
  285. struct Gadget *theGadget;
  286. struct IntuiMessage *theMessage;
  287. {
  288.    while (theGadget->Flags & SELECTED)
  289.    {
  290.       if (theList->TopItem + 1 < theList->ListLen)
  291.       {
  292.          theList->TopItem++;
  293.          SetViewImage(theList,theList->ItemTop->Prev);
  294.          RefreshGList(theList->Gadget,myWindow,theList->Request,1);
  295.          UpdateViewSlider(theList);
  296.          #if SCROLLDELAY > 0
  297.             Delay(SCROLLDELAY);
  298.          #endif
  299.       }
  300.    }
  301. }
  302.  
  303.  
  304. /*
  305.  *  DoViewSlider()
  306.  *
  307.  *  Find the position in the list of the new slider location
  308.  *  If the position has changed
  309.  *    Look through the list until we get to the specified position
  310.  *    display the proper part image
  311.  */
  312.  
  313. void DoViewSlider(theList)
  314. LISTINFO *theList;
  315. {
  316.    LISTITEM *theItem = theList->Item;
  317.    short Top;
  318.    short Size = theList->ListLen - 1;
  319.    
  320.    if (Size < 0) Size = 0; 
  321.    Top = Size * SLIDERINFO->VertPot / 0xFFFF;
  322.    if (Top > Size) Top = Size; else if (Top < 0) Top = 0;
  323.  
  324.    if (Top != theList->TopItem)
  325.    {
  326.       theList->TopItem = Top;
  327.       while (Top-- && theItem) theItem = theItem->Prev;
  328.       SetViewImage(theList,theItem);
  329.    }
  330. }
  331.  
  332.  
  333. /*
  334.  *  ViewGadgetUp()
  335.  *
  336.  *  Do the right thing for gadget up events in VIEW mode:
  337.  *
  338.  *  Parts slider:
  339.  *    stop getting mouse moves and make no slider as active
  340.  *    update the slider position
  341.  *
  342.  *  Everything else:
  343.  *    do the regular gadget up routine
  344.  */
  345.  
  346. void ViewGadgetUp(theGadget,theMessage)
  347. struct Gadget *theGadget;
  348. struct IntuiMessage *theMessage;
  349. {
  350.    switch(theGadget->GadgetID)
  351.    {
  352.       case LP_PSLIDE:
  353.          StopMouseMoves(); ActiveList = NULL;
  354.          DoViewSlider(theGadget->UserData);
  355.          break;
  356.  
  357.       default:
  358.          LPGadgetUp(theGadget,theMessage);
  359.          break;
  360.    }
  361. }
  362.  
  363.  
  364. /*
  365.  * ViewGadgetDown()
  366.  *
  367.  *  Do the right thing for gadget down events in VIEW mode:
  368.  *
  369.  *  Ignore hits in the name and parts list gadgets
  370.  *  Arrows:  scroll the parts list in VIEW mode
  371.  *  Slider:  if the knob is hit, start dragging poperations
  372.  *  Everything else:  do the regular gadget down routine
  373.  */
  374.  
  375. void ViewGadgetDown(theGadget,theMessage)
  376. struct Gadget *theGadget;
  377. struct IntuiMessage *theMessage;
  378. {
  379.    LISTINFO *theList;
  380.  
  381.    switch(theGadget->GadgetID)
  382.    {
  383.       case LP_PNAMES:
  384.       case LP_NAME:
  385.          break;
  386.  
  387.       case LP_PUARROW:
  388.          DoViewScrollUp(theGadget->UserData,theGadget,theMessage);
  389.          break;
  390.  
  391.       case LP_PDARROW:
  392.          DoViewScrollDown(theGadget->UserData,theGadget,theMessage);
  393.          break;
  394.  
  395.       case LP_PSLIDE:
  396.          theList = (LISTINFO *)theGadget->UserData;
  397.          if (SLIDERINFO->Flags & KNOBHIT)
  398.          {
  399.             DoViewSlider(theList);
  400.             StartMouseMoves();
  401.             ActiveList = theList;
  402.          }
  403.          break;
  404.  
  405.       default:
  406.          LPGadgetDown(theGadget,theMessage);
  407.          break;
  408.    }
  409. }
  410.  
  411.  
  412. /*
  413.  *  DoViewMouse()
  414.  *
  415.  *  if a list is active, do the slider operation in VIEW mode
  416.  */
  417.  
  418. void DoViewMouse(MouseX,MouseY,theMessage)
  419. short MouseX,MouseY;
  420. struct IntuiMessage *theMessage;
  421. {
  422.    if (ActiveList) DoViewSlider(ActiveList);
  423. }
  424.  
  425.  
  426. /*
  427.  *  SetViewMode()
  428.  *
  429.  *  If already in VIEW mode
  430.  *    clear the image bitmap
  431.  *    set things up for a text list again
  432.  *    call the list manager to initialize the list
  433.  *    change the gadget routines back to normal
  434.  *    cancel VIEW mode
  435.  *  Otherwise
  436.  *    set up the image to use the bitmap data area
  437.  *    set up the list gadget to use the image
  438.  *    display the selected part
  439.  *    set the gadget routines to the VIEW mode routines
  440.  *    set VIEW mode to TRUE
  441.  */
  442.  
  443. void SetViewMode(theList,theItem,SelectItem)
  444. LISTINFO *theList;
  445. LISTITEM *theItem;
  446. LISTITEM *SelectItem;
  447. {
  448.    if (Viewing)
  449.    {
  450.       SetRast(irp,FOREGROUND);
  451.       RefreshGList(theList->Gadget,myWindow,theList->Request,1);
  452.       theList->Gadget->GadgetText = theList->IText;
  453.       theList->Gadget->GadgetRender = (APTR)theList->Image;
  454.       SetList(theList->Gadget,theItem,SelectItem);
  455.       theList->Request->er_GadgetDown = &LPGadgetDown;
  456.       theList->Request->er_GadgetUp   = &LPGadgetUp;
  457.       theList->Request->er_MouseMove  = &DoListMouse;
  458.       Viewing = FALSE;
  459.    } else {
  460.       ViewImage.ImageData = (USHORT *)irp->BitMap->Planes[0];
  461.       theList->Gadget->GadgetText = NULL;
  462.       theList->Gadget->GadgetRender = (APTR)&ViewImage;
  463.       SetView(theList->Gadget,theItem,SelectItem);
  464.       theList->Request->er_GadgetDown = &ViewGadgetDown;
  465.       theList->Request->er_GadgetUp   = &ViewGadgetUp;
  466.       theList->Request->er_MouseMove  = &DoViewMouse;
  467.       Viewing = TRUE;
  468.    }
  469. }
  470.