home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Programmation / e / Exemples / BoopsiExamples.lha / BoopsiExamples / ScrollerWindow_feck.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  14.1 KB  |  589 lines

  1. /*
  2. ****************************************************************************
  3. **
  4. **  $VER: scrollerwindow.c 0.2 (5.6.94)
  5. **
  6. **  Example code which shows how to correctly create a screen resolution
  7. **  sensitive window with scrollbars and arrows.
  8. **
  9. **  Write *ADPAPTIVE* software!  Get *RID* of hard coded values!
  10. **
  11. ****************************************************************************
  12. **
  13. **  Copyright ⌐ 1994 Christoph Feck, TowerSystems.  You may use methods
  14. **  and code provided in this example in executables for Commodore-Amiga
  15. **  computers.  All other rights reserved.
  16. **
  17. **  For questions and suggestions contact me via email at:
  18. **  feck@informatik.uni-kl.de
  19. **
  20. **  NOTE:  This file is provided "AS-IS" and subject to change without
  21. **  prior notice; no warranties are made.  All use is at your own risk.
  22. **  No liability or responsibility is assumed.
  23. **
  24. ****************************************************************************
  25. **
  26. **  Compilation notes:
  27. **
  28. **  - Needs V39 or newer includes and amiga.lib (Fred Fish CD or CATS NDK).
  29. **
  30. ****************************************************************************
  31. **
  32. **  Changes:
  33. **  - oops!  forgot ReplyMsg()
  34. **  - added input processing
  35. **  - visible based on window size
  36. **  - scrolls the screen in the window :)
  37. **
  38. **  Todo:
  39. **  - drag scrolling
  40. **  - keyboard control
  41. **  - GM_LAYOUT for scrollbars (V39)
  42. **  - make it a model
  43. **  - your suggestions/questions
  44. **
  45. ****************************************************************************
  46. */
  47.  
  48. #include <exec/types.h>
  49. #include <exec/memory.h>
  50. #include <exec/libraries.h>
  51. #include <intuition/intuition.h>
  52. #include <intuition/imageclass.h>
  53. #include <intuition/icclass.h>
  54. #include <intuition/gadgetclass.h>
  55.  
  56. #include <proto/exec.h>
  57. #include <proto/intuition.h>
  58. #include <proto/graphics.h>
  59. #include <proto/utility.h>
  60.  
  61.  
  62. /***************************************************************************
  63.  *
  64.  *  Pepo's peculiarities.
  65.  *
  66.  ***************************************************************************
  67.  */
  68.  
  69. #define NEW(type) ((type *) AllocMem(sizeof(type), MEMF_CLEAR | MEMF_PUBLIC))
  70. #define DISPOSE(stuff) (FreeMem(stuff, sizeof(*stuff)))
  71.  
  72. #ifndef IM
  73. #define IM(o) ((struct Image *) o)
  74. #endif
  75.  
  76. #ifndef MAX
  77. #define MAX(x,y) ((x) > (y) ? (x) : (y))
  78. #endif
  79. #ifndef MIN
  80. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  81. #endif
  82.  
  83.  
  84. /***************************************************************************
  85.  *
  86.  *  Global variables.
  87.  *
  88.  ***************************************************************************
  89.  */
  90.  
  91. struct IntuitionBase *IntuitionBase;
  92. struct GfxBase *GfxBase;
  93. struct Library *UtilityBase;
  94. struct Screen *screen;
  95. struct DrawInfo *dri;
  96. BOOL V39;
  97.  
  98. /* The bitmap we want to display */
  99. struct BitMap *bitmap;
  100.  
  101.  
  102. /***************************************************************************
  103.  *
  104.  *  V37 compatible BitMap functions.
  105.  *
  106.  ***************************************************************************
  107.  */
  108.  
  109. struct BitMap *CreateBitMap(LONG width, LONG height, LONG depth, ULONG flags, struct BitMap *friend)
  110. {
  111.     struct BitMap *bm;
  112.  
  113.     if (V39)
  114.     {
  115.         bm = AllocBitMap(width, height, depth, flags, friend);
  116.     }
  117.     else
  118.     {
  119.         LONG memflags = MEMF_CHIP;
  120.  
  121.         if (bm = NEW(struct BitMap))
  122.         {
  123.             InitBitMap(bm, depth, width, height);
  124.             if (flags & BMF_CLEAR) memflags |= MEMF_CLEAR;
  125.             /* For simplicity, we allocate all planes in one big chunk */
  126.             if (bm->Planes[0] = (PLANEPTR) AllocVec(depth * RASSIZE(width, height), memflags))
  127.             {
  128.                 LONG i;
  129.  
  130.                 for (i = 1; i < depth; i++)
  131.                 {
  132.                     bm->Planes[i] = bm->Planes[i - 1] + RASSIZE(width, height);
  133.                 }
  134.             }
  135.             else
  136.             {
  137.                 DISPOSE(bm);
  138.                 bm = NULL;
  139.             }
  140.         }
  141.     }
  142.     return (bm);
  143. }
  144.  
  145.  
  146. VOID DeleteBitMap(struct BitMap *bm)
  147. {
  148.     if (bm)
  149.     {
  150.         if (V39)
  151.         {
  152.             FreeBitMap(bm);
  153.         }
  154.         else
  155.         {
  156.             FreeVec(bm->Planes[0]);
  157.             DISPOSE(bm);
  158.         }
  159.     }
  160. }
  161.  
  162.  
  163. ULONG BitMapDepth(struct BitMap *bm)
  164. {
  165.     if (V39)
  166.     {
  167.         return (GetBitMapAttr(bm, BMA_DEPTH));
  168.     }
  169.     else
  170.     {
  171.         return (bm->Depth);
  172.     }
  173. }
  174.  
  175.  
  176. /***************************************************************************
  177.  *
  178.  *  Calculates the basic size of the resolution.
  179.  *
  180.  ***************************************************************************
  181.  */
  182.  
  183. int SysISize(VOID)
  184. {
  185.     return (screen->Flags & SCREENHIRES ? SYSISIZE_MEDRES : SYSISIZE_LOWRES);
  186. /* NB: SYSISIZE_HIRES not yet supported. */
  187. }
  188.  
  189.  
  190. /***************************************************************************
  191.  *
  192.  *  Object creation stubs.
  193.  *
  194.  ***************************************************************************
  195.  */
  196.  
  197. /* Creates a sysiclass object. */
  198. Object *NewImageObject(ULONG which)
  199. {
  200.     return (NewObject(NULL, SYSICLASS,
  201.      SYSIA_DrawInfo, dri,
  202.      SYSIA_Which, which,
  203.      SYSIA_Size, SysISize(),
  204.     TAG_DONE));
  205. }
  206.  
  207.  
  208. /* Creates a propgclass object. */
  209. Object *NewPropObject(ULONG freedom, Tag tag1, ...)
  210. {
  211.     return (NewObject(NULL, PROPGCLASS,
  212.     /* Send update to IDCMP.  If we make it a model, we would send the
  213.      * notification to our model object. */
  214.      ICA_TARGET, ICTARGET_IDCMP,
  215.      PGA_Freedom, freedom,
  216.      PGA_NewLook, TRUE,
  217.     /* Borderless does only look right with newlook screens */
  218.      PGA_Borderless, ((dri->dri_Flags & DRIF_NEWLOOK) && dri->dri_Depth != 1),
  219.     TAG_MORE, &tag1));
  220. }
  221.  
  222.  
  223. /* Creates a buttongclass object. */
  224. Object *NewButtonObject(Object *image, Tag tag1, ...)
  225. {
  226.     return (NewObject(NULL, BUTTONGCLASS,
  227.      ICA_TARGET, ICTARGET_IDCMP,
  228.      GA_Image, image,
  229.     /* No need for GA_Width/Height.  buttongclass is smart :) */
  230.     TAG_MORE, &tag1));
  231. }
  232.  
  233.  
  234. /***************************************************************************
  235.  *
  236.  *  Our scroller window.  This is not a boopsi object (yet?).
  237.  *
  238.  ***************************************************************************
  239.  */
  240.  
  241. /* All gadgets and their IDs. */
  242. Object *horizgadget, *vertgadget;
  243. Object *leftgadget, *rightgadget, *upgadget, *downgadget;
  244.  
  245. #define HORIZ_GID    1
  246. #define VERT_GID    2
  247. #define LEFT_GID    3
  248. #define RIGHT_GID    4
  249. #define UP_GID        5
  250. #define DOWN_GID    6
  251.  
  252. struct Window *window;
  253.  
  254. /* These are the images we adapt our layout to. */
  255. Object *sizeimage, *leftimage, *rightimage, *upimage, *downimage;
  256.  
  257. /* Cached model info */
  258. LONG htotal;
  259. LONG vtotal;
  260. LONG hvisible;
  261. LONG vvisible;
  262.  
  263. VOID OpenScrollerWindow(Tag tag1, ...)
  264. {
  265.     int resolution = SysISize();
  266.     WORD topborder = screen->WBorTop + screen->Font->ta_YSize + 1;
  267.     WORD w = IM(sizeimage)->Width;
  268.     WORD h = IM(sizeimage)->Height;
  269.     WORD bw = (resolution == SYSISIZE_LOWRES) ? 1 : 2;
  270.     WORD bh = (resolution == SYSISIZE_HIRES) ? 2 : 1;
  271.     WORD rw = (resolution == SYSISIZE_HIRES) ? 3 : 2;
  272.     WORD rh = (resolution == SYSISIZE_HIRES) ? 2 : 1;
  273.     WORD gw;
  274.     WORD gh;
  275.     WORD gap;
  276.  
  277.     gh = MAX(IM(leftimage)->Height, h);
  278.     gh = MAX(IM(rightimage)->Height, gh);
  279.     gw = MAX(IM(upimage)->Width, w);
  280.     gw = MAX(IM(downimage)->Width, gw);
  281.  
  282.     /* If you have gadgets in the left window border, set 'gap' to the
  283.      * width of these gadgets. */
  284.     gap = 1;
  285.  
  286.     horizgadget = NewPropObject(FREEHORIZ,
  287.      GA_Left, rw + gap,
  288.      GA_RelBottom, bh - gh + 2,
  289.      GA_RelWidth, -gw - gap - IM(leftimage)->Width - IM(rightimage)->Width - rw - rw,
  290.      GA_Height, gh - bh - bh - 2,
  291.      GA_BottomBorder, TRUE,
  292.      GA_ID, HORIZ_GID,
  293.      PGA_Total, htotal,
  294.      PGA_Visible, hvisible,
  295.     TAG_DONE);
  296.  
  297.     vertgadget = NewPropObject(FREEVERT,
  298.      GA_RelRight, bw - gw + 3,
  299.      GA_Top, topborder + rh,
  300.      GA_Width, gw - bw - bw - 4,
  301.      GA_RelHeight, -topborder - h - IM(upimage)->Height - IM(downimage)->Height - rh - rh,
  302.      GA_RightBorder, TRUE,
  303.      GA_Previous, horizgadget,
  304.      GA_ID, VERT_GID,
  305.      PGA_Total, vtotal,
  306.      PGA_Visible, vvisible,
  307.     TAG_DONE);
  308.  
  309.     leftgadget = NewButtonObject(leftimage,
  310.      GA_RelRight, 1 - IM(leftimage)->Width - IM(rightimage)->Width - gw,
  311.      GA_RelBottom, 1 - IM(leftimage)->Height,
  312.      GA_BottomBorder, TRUE,
  313.      GA_Previous, vertgadget,
  314.      GA_ID, LEFT_GID,
  315.     TAG_DONE);
  316.  
  317.     rightgadget = NewButtonObject(rightimage,
  318.      GA_RelRight, 1 - IM(rightimage)->Width - gw,
  319.      GA_RelBottom, 1 - IM(rightimage)->Height,
  320.      GA_BottomBorder, TRUE,
  321.      GA_Previous, leftgadget,
  322.      GA_ID, RIGHT_GID,
  323.     TAG_DONE);
  324.  
  325.     upgadget = NewButtonObject(upimage,
  326.      GA_RelRight, 1 - IM(upimage)->Width,
  327.      GA_RelBottom, 1 - IM(upimage)->Height - IM(downimage)->Height - h,
  328.      GA_RightBorder, TRUE,
  329.      GA_Previous, rightgadget,
  330.      GA_ID, UP_GID,
  331.     TAG_DONE);
  332.  
  333.     downgadget = NewButtonObject(downimage,
  334.      GA_RelRight, 1 - IM(downimage)->Width,
  335.      GA_RelBottom, 1 - IM(downimage)->Height - h,
  336.      GA_RightBorder, TRUE,
  337.      GA_Previous, upgadget,
  338.      GA_ID, DOWN_GID,
  339.     TAG_DONE);
  340.  
  341.     /* if downgadget is non-NULL, all gadgets were created OK. */
  342.     if (downgadget)
  343.     {
  344.         window = OpenWindowTags(NULL,
  345.          WA_Gadgets, horizgadget,
  346.          WA_MinWidth, MAX(80, gw + gap + IM(leftimage)->Width + IM(rightimage)->Width + rw + rw + KNOBHMIN),
  347.          WA_MinHeight, MAX(50, topborder + h + IM(upimage)->Height + IM(downimage)->Height + rh + rh + KNOBVMIN),
  348.         TAG_MORE, &tag1);
  349.     }
  350. }
  351.  
  352.  
  353. VOID CloseScrollerWindow(VOID)
  354. {
  355.     if (window) CloseWindow(window);
  356.     DisposeObject(horizgadget);
  357.     DisposeObject(vertgadget);
  358.     DisposeObject(leftgadget);
  359.     DisposeObject(rightgadget);
  360.     DisposeObject(upgadget);
  361.     DisposeObject(downgadget);
  362. }
  363.  
  364.  
  365. /***************************************************************************
  366.  *
  367.  *  Here we do all the stuff necessary to make it work properly.
  368.  *
  369.  ***************************************************************************
  370.  */
  371.  
  372. /* Calculate visible region based on window size. */
  373.  
  374. STATIC LONG RecalcHVisible(VOID)
  375. {
  376.     return (window->Width - window->BorderLeft - window->BorderRight);
  377. }
  378.  
  379. STATIC LONG RecalcVVisible(VOID)
  380. {
  381.     return (window->Height - window->BorderTop - window->BorderBottom);
  382. }
  383.  
  384.  
  385. VOID UpdateProp(Object *gadget, ULONG attr, LONG value)
  386. {
  387.     SetGadgetAttrs((struct Gadget *) gadget, window, NULL, attr, value, TAG_DONE);
  388. }
  389.  
  390.  
  391. /* Copy our BitMap into the window */
  392. VOID CopyBitMap(VOID)
  393. {
  394.     ULONG srcx, srcy;
  395.  
  396.     /* Get right place */
  397.     GetAttr(PGA_Top, horizgadget, &srcx);
  398.     GetAttr(PGA_Top, vertgadget, &srcy);
  399.     BltBitMapRastPort(bitmap, srcx, srcy, window->RPort, window->BorderLeft, window->BorderTop, MIN(htotal, hvisible), MIN(vtotal, vvisible), 0xC0);
  400. }
  401.  
  402.  
  403. VOID UpdateScrollerWindow(VOID)
  404. {
  405.     hvisible = RecalcHVisible();
  406.     UpdateProp(horizgadget, PGA_Visible, hvisible);
  407.     vvisible = RecalcVVisible();
  408.     UpdateProp(vertgadget, PGA_Visible, vvisible);
  409.     CopyBitMap();
  410. }
  411.  
  412.  
  413. /***************************************************************************
  414.  *
  415.  *  Main program.
  416.  *
  417.  ***************************************************************************
  418.  */
  419.  
  420.  
  421. VOID HandleScrollerWindow(VOID)
  422. {
  423.     struct IntuiMessage *imsg;
  424.     BOOL quit = FALSE;
  425.     LONG oldtop;
  426.  
  427.     while (!quit)
  428.     {
  429.         while (!quit && (imsg = (struct IntuiMessage *) GetMsg(window->UserPort)))
  430.         {
  431.             switch (imsg->Class)
  432.             {
  433.             case IDCMP_CLOSEWINDOW:
  434.                 quit = TRUE;
  435.                 break;
  436.             case IDCMP_NEWSIZE:
  437.                 UpdateScrollerWindow();
  438.                 break;
  439.             case IDCMP_REFRESHWINDOW:
  440.                 BeginRefresh(window);
  441.                 CopyBitMap();
  442.                 EndRefresh(window, TRUE);
  443.                 break;
  444.             case IDCMP_IDCMPUPDATE:
  445.                 /* IAddress is a pointer to a taglist with new attributes.
  446.                  * We are only interested in the ID of the involved gadget.
  447.                  */
  448.                 switch (GetTagData(GA_ID, 0, (struct TagItem *) imsg->IAddress))
  449.                 {
  450.                 case HORIZ_GID:
  451.                 case VERT_GID:
  452.                     CopyBitMap();
  453.                     break;
  454.                 case LEFT_GID:
  455.                     GetAttr(PGA_Top, horizgadget, (ULONG *) &oldtop);
  456.                     if (oldtop > 0)
  457.                     {
  458.                         UpdateProp(horizgadget, PGA_Top, oldtop - 1);
  459.                         CopyBitMap();
  460.                     }
  461.                     break;
  462.                 case RIGHT_GID:
  463.                     GetAttr(PGA_Top, horizgadget, (ULONG *) &oldtop);
  464.                     if (oldtop < htotal - hvisible)
  465.                     {
  466.                         UpdateProp(horizgadget, PGA_Top, oldtop + 1);
  467.                         CopyBitMap();
  468.                     }
  469.                     break;
  470.                 case UP_GID:
  471.                     GetAttr(PGA_Top, vertgadget, (ULONG *) &oldtop);
  472.                     if (oldtop > 0)
  473.                     {
  474.                         UpdateProp(vertgadget, PGA_Top, oldtop - 1);
  475.                         CopyBitMap();
  476.                     }
  477.                     break;
  478.                 case DOWN_GID:
  479.                     GetAttr(PGA_Top, vertgadget, (ULONG *) &oldtop);
  480.                     if (oldtop < vtotal - vvisible)
  481.                     {
  482.                         UpdateProp(vertgadget, PGA_Top, oldtop + 1);
  483.                         CopyBitMap();
  484.                     }
  485.                     break;
  486.                 default:
  487.                     break;
  488.                 }
  489.                 break;
  490.             default:
  491.                 break;
  492.             }
  493.             ReplyMsg((struct Message *) imsg);
  494.         }
  495.         if (!quit) WaitPort(window->UserPort);
  496.     }
  497. }
  498.  
  499.  
  500. VOID DoScrollerWindow(VOID)
  501. {
  502.     if (screen = LockPubScreen(NULL))
  503.     {
  504.         /* We clone the screen bitmap */
  505.         hvisible = htotal = screen->Width;
  506.         vvisible = vtotal = screen->Height;
  507.         if (bitmap = CreateBitMap(htotal, vtotal, BitMapDepth(screen->RastPort.BitMap), 0, screen->RastPort.BitMap))
  508.         {
  509.             /* Copy it over */
  510.             BltBitMap(screen->RastPort.BitMap, 0, 0, bitmap, 0, 0, htotal, vtotal, 0xC0, ~0, NULL);
  511.             if (dri = GetScreenDrawInfo(screen))
  512.             {
  513.                 sizeimage = NewImageObject(SIZEIMAGE);
  514.                 leftimage = NewImageObject(LEFTIMAGE);
  515.                 rightimage = NewImageObject(RIGHTIMAGE);
  516.                 upimage = NewImageObject(UPIMAGE);
  517.                 downimage = NewImageObject(DOWNIMAGE);
  518.                 if (sizeimage && leftimage && rightimage && upimage && downimage)
  519.                 {
  520.                     OpenScrollerWindow(WA_PubScreen, screen,
  521.                      WA_Title, "$VER: ScrollerWindow 0.2 (5.6.94)",
  522.                      WA_Flags,
  523.                          WFLG_CLOSEGADGET |
  524.                          WFLG_SIZEGADGET |
  525.                          WFLG_DRAGBAR |
  526.                          WFLG_DEPTHGADGET |
  527.                          WFLG_SIMPLE_REFRESH |
  528.                          WFLG_ACTIVATE |
  529.                          WFLG_NEWLOOKMENUS,
  530.                      WA_IDCMP,
  531.                          IDCMP_CLOSEWINDOW |
  532.                          IDCMP_NEWSIZE |
  533.                          IDCMP_REFRESHWINDOW |
  534.                          IDCMP_IDCMPUPDATE,
  535.                      WA_InnerWidth, htotal,
  536.                      WA_InnerHeight, vtotal,
  537.                      WA_MaxWidth, -1,
  538.                      WA_MaxHeight, -1,
  539.                     TAG_DONE);
  540.                     if (window)
  541.                     {
  542.                         UpdateScrollerWindow();
  543.                         HandleScrollerWindow();
  544.                     }
  545.                     CloseScrollerWindow();
  546.                 }
  547.                 DisposeObject(sizeimage);
  548.                 DisposeObject(leftimage);
  549.                 DisposeObject(rightimage);
  550.                 DisposeObject(upimage);
  551.                 DisposeObject(downimage);
  552.                 FreeScreenDrawInfo(screen, dri);
  553.             }
  554.             WaitBlit();
  555.             DeleteBitMap(bitmap);
  556.         }
  557.         UnlockPubScreen(NULL, screen);
  558.     }
  559. }
  560.  
  561.  
  562. /***************************************************************************
  563.  *
  564.  *  Startup.
  565.  *
  566.  ***************************************************************************
  567.  */
  568.  
  569. VOID main(int argc, char *argv[])
  570. {
  571.     if (IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 36))
  572.     {
  573.         /* Do we run V39? */
  574.         V39 = ((struct Library *) IntuitionBase)->lib_Version >= 39;
  575.         if (GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 36))
  576.         {
  577.             if (UtilityBase = OpenLibrary("utility.library", 36))
  578.             {
  579.                 DoScrollerWindow();
  580.                 CloseLibrary(UtilityBase);
  581.             }
  582.             CloseLibrary((struct Library *) IntuitionBase);
  583.         }
  584.         CloseLibrary((struct Library *) GfxBase);
  585.     }
  586. }
  587.  
  588.  
  589.