home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / utils / dialoglib / listview.c < prev    next >
C/C++ Source or Header  |  1993-03-07  |  8KB  |  299 lines

  1. #include <intuition/gadgetclass.h>
  2. #include <libraries/gadtools.h>
  3. #include <graphics/text.h>
  4. #include <proto/diskfont.h>
  5. #include <proto/gadtools.h>
  6. #include <proto/graphics.h>
  7. #include <proto/utility.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. #include "dialog.h"
  11. #ifdef DEBUG1
  12.     #include <stdio.h>
  13. #endif
  14.  
  15. static LONG countItems( DialogElement *de )
  16. {
  17.     struct List *list;
  18.     struct Node *node;
  19.     ULONG labels;
  20.     LONG count = 0;
  21.  
  22.     if( !de )
  23.         return 0;
  24.  
  25.     labels = GetTagData( GTLV_Labels, 0, de->taglist );
  26.     if( labels == 0 || labels == ~0 )
  27.         goto termination;
  28.  
  29.     list = (struct List *)labels;
  30.     for( node = list->lh_Head; node->ln_Succ; node = node->ln_Succ )
  31.         count++;
  32. termination:
  33.     return count;
  34. }
  35.  
  36. static ULONG getListViewStructure( DialogElement *de )
  37. {
  38.     ULONG place, structure = 0;
  39.  
  40.     if( !de )
  41.         return 0;
  42.  
  43.     if( GetTagData( NGDA_GadgetText, 0, de->taglist ) )
  44.     {
  45.         place = getTextPlacement( GetTagData( NGDA_Flags, 0, de->taglist ), PLACETEXT_ABOVE );
  46.         switch( place )
  47.         {
  48.         case PLACETEXT_ABOVE:
  49.         case PLACETEXT_BELOW:
  50.             structure = DESF_HBaseline;
  51.             break;
  52.         case PLACETEXT_LEFT:
  53.         case PLACETEXT_RIGHT:
  54.             structure = DESF_VBaseline;
  55.             break;
  56.         }
  57.     }
  58.     return structure;
  59. }
  60.  
  61. static VOID setupListView( DialogElement *de )
  62. {
  63.     struct TextAttr *ta;
  64.     struct TextFont *tf;
  65.     struct RastPort rp;
  66.     struct TextExtent te;
  67.     STRPTR text;
  68.     LONG scrollwidth, minwidth, minheight, textwidth, textheight;
  69.     ULONG place;
  70.     LONG *storage;
  71.  
  72.     if( !de )
  73.         return;
  74.  
  75.     de->idcmp_mask |= LISTVIEWIDCMP | IDCMP_REFRESHWINDOW | IDCMP_VANILLAKEY;
  76.  
  77.     storage = (LONG *)GetTagData( DA_Storage, 0, de->taglist );
  78.     if( storage )
  79.         *storage = GetTagData( GTLV_Selected, ~0, de->taglist );
  80.  
  81.     scrollwidth = GetTagData( GTLV_ScrollWidth, 16, de->taglist );
  82.  
  83.     ta = (struct TextAttr *)GetTagData( NGDA_TextAttr, 0, de->taglist );
  84.     if( !ta )
  85.         return;
  86.     tf = OpenDiskFont( ta );
  87.     if( !tf )
  88.         return;
  89.  
  90.     /* minimal dimensions: 3 visible items, 3 visible label characters */
  91.     /* note: the constants "4" and "2" are the thicknesses of the frame */
  92.     minwidth = 4 + 3 * tf->tf_XSize + 4 + scrollwidth;
  93.     minheight = 2 + 3 * tf->tf_YSize + GetTagData( LAYOUTA_Spacing, 0, de->taglist ) + 2;
  94.     if( (struct Gadget *)GetTagData( GTLV_ShowSelected, ~0, de->taglist ) == NULL )
  95.         minheight += 2 + tf->tf_YSize + 2;
  96.  
  97.     text = (STRPTR)GetTagData( NGDA_GadgetText, 0, de->taglist );
  98.     place = getTextPlacement( GetTagData( NGDA_Flags, 0, de->taglist ), PLACETEXT_ABOVE );
  99.  
  100.     if( text )
  101.     {
  102.         InitRastPort( &rp );
  103.         SetFont( &rp, tf );
  104.         TextExtent( &rp, text, strlen( text ), &te );
  105.     }
  106.     else
  107.     {
  108.         te.te_Extent.MinX = te.te_Extent.MinY = 0;
  109.         te.te_Extent.MaxX = te.te_Extent.MaxY = -1;
  110.     }
  111.  
  112.     CloseFont( tf );
  113.  
  114.     textwidth = te.te_Extent.MaxX + 1 - te.te_Extent.MinX;
  115.     textheight = te.te_Extent.MaxY + 1 - te.te_Extent.MinY;
  116.  
  117.     switch( place )
  118.     {
  119.     case PLACETEXT_ABOVE:
  120.         if( minwidth < textwidth )
  121.             minwidth = textwidth;
  122.         setMinWidth( de, minwidth );
  123.         setMaxWidth( de, MAX_SPACE );
  124.         setMinTopExtent( de, textheight + INTERHEIGHT );
  125.         setMaxTopExtent( de, textheight + INTERHEIGHT );
  126.         setMinBottomExtent( de, minheight );
  127.         setMaxBottomExtent( de, MAX_SPACE );
  128.         break;
  129.     case PLACETEXT_BELOW:
  130.         if( minwidth < textwidth )
  131.             minwidth = textwidth;
  132.         setMinWidth( de, minwidth );
  133.         setMaxWidth( de, MAX_SPACE );
  134.         setMinTopExtent( de, minheight );
  135.         setMaxTopExtent( de, MAX_SPACE );
  136.         setMinBottomExtent( de, textheight + INTERHEIGHT );
  137.         setMaxBottomExtent( de, textheight + INTERHEIGHT );
  138.         break;
  139.     case PLACETEXT_LEFT:
  140.         if( minheight < textheight )
  141.             minheight = textheight;
  142.         setMinLeftExtent( de, textwidth + INTERWIDTH  );
  143.         setMaxLeftExtent( de, textwidth + INTERWIDTH  );
  144.         setMinRightExtent( de, minwidth );
  145.         setMaxRightExtent( de, MAX_SPACE );
  146.         setMinHeight( de, minheight );
  147.         setMaxHeight( de, MAX_SPACE );
  148.         break;
  149.     case PLACETEXT_RIGHT:
  150.         if( minheight < textheight )
  151.             minheight = textheight;
  152.         setMinLeftExtent( de, minwidth );
  153.         setMaxLeftExtent( de, MAX_SPACE );
  154.         setMinRightExtent( de, textwidth + INTERWIDTH );
  155.         setMaxRightExtent( de, textwidth + INTERWIDTH );
  156.         setMinHeight( de, minheight );
  157.         setMaxHeight( de, MAX_SPACE );
  158.         break;
  159.     case PLACETEXT_IN:
  160.         setMinWidth( de, minwidth );
  161.         setMaxWidth( de, MAX_SPACE );
  162.         setMinHeight( de, minheight );
  163.         setMaxHeight( de, MAX_SPACE );
  164.     }
  165. }
  166.  
  167. static ULONG layoutListView( DialogElement *de, LayoutMessage *lm )
  168. {
  169.     struct NewGadget ng;
  170.     ULONG place, error = DIALOGERR_OK;
  171.  
  172.     if( !de )
  173.         return DIALOGERR_BAD_ARGS;
  174.     if( !lm )
  175.         return DIALOGERR_BAD_ARGS;
  176.  
  177. #ifdef DEBUG1
  178.     printf(
  179.     "layoutListView : x %d, y %d, width %d, height %d, left %d, right %d, top %d, bottom %d\n",
  180.         lm->lm_X, lm->lm_Y, lm->lm_Width, lm->lm_Height,
  181.         lm->lm_Left, lm->lm_Right, lm->lm_Top, lm->lm_Bottom );
  182. #endif
  183.     ng.ng_GadgetText = (UBYTE *)GetTagData( NGDA_GadgetText, 0, de->taglist );
  184.     ng.ng_TextAttr = (struct TextAttr *)GetTagData( NGDA_TextAttr, 0, de->taglist );
  185.     ng.ng_VisualInfo = (APTR)GetTagData( NGDA_VisualInfo, 0, de->taglist );
  186.     ng.ng_Flags = GetTagData( NGDA_Flags, 0, de->taglist );
  187.     ng.ng_LeftEdge = lm->lm_X;
  188.     ng.ng_TopEdge = lm->lm_Y;
  189.     place = getTextPlacement( ng.ng_Flags, PLACETEXT_ABOVE );
  190.     switch( place )
  191.     {
  192.     case PLACETEXT_LEFT:
  193.         ng.ng_Width = lm->lm_Right;
  194.         ng.ng_Height = lm->lm_Height;
  195.         break;
  196.     case PLACETEXT_RIGHT:
  197.         ng.ng_LeftEdge -= lm->lm_Left;
  198.         ng.ng_Width = lm->lm_Left;
  199.         ng.ng_Height = lm->lm_Height;
  200.         break;
  201.     case PLACETEXT_ABOVE:
  202.         ng.ng_Width = lm->lm_Width;
  203.         ng.ng_Height = lm->lm_Bottom;
  204.         break;
  205.     case PLACETEXT_BELOW:
  206.         ng.ng_TopEdge -= lm->lm_Top;
  207.         ng.ng_Width = lm->lm_Width;
  208.         ng.ng_Height = lm->lm_Top;
  209.         break;
  210.     case PLACETEXT_IN:
  211.         ng.ng_Width = lm->lm_Width;
  212.         ng.ng_Height = lm->lm_Height;
  213.         break;
  214.     }
  215.     de->object = CreateGadgetA( LISTVIEW_KIND, *lm->lm_PreviousPtr, &ng, de->taglist );
  216.     *lm->lm_PreviousPtr = de->object;    /* advance "previous" pointer to new object */
  217.     if( !de->object )
  218.         error = DIALOGERR_NO_MEMORY;
  219.     return error;
  220. }
  221.  
  222. static DialogElement *matchListView( DialogElement *de, MatchMessage *mm )
  223. {
  224.     struct IntuiMessage *imsg;
  225.     DialogElement *match = NULL;
  226.     struct TagItem *tag;
  227.     LONG *storage;
  228.  
  229.     if( !de )
  230.         return NULL;
  231.     if( !mm )
  232.         return NULL;
  233.  
  234.     storage = (LONG *)GetTagData( DA_Storage, 0, de->taglist );
  235.  
  236.     imsg = mm->mm_IntuiMsg;
  237.     switch( imsg->Class )
  238.     {
  239.     case IDCMP_GADGETUP:
  240.         if( de->object == imsg->IAddress )
  241.         {
  242.             if( storage )
  243.                 *storage = (ULONG)imsg->Code;        /* store current level */
  244.             match = de;
  245.         }
  246.         break;
  247.     case IDCMP_VANILLAKEY:
  248.         if( storage )
  249.             if( tag = FindTagItem( DA_EquivalentKey, de->taglist ) )
  250.                 if( imsg->Code == tolower( tag->ti_Data ) )
  251.                 {
  252.                     if( *storage != ~0 )
  253.                         if( *storage < countItems( de ) - 1 )
  254.                             GT_SetGadgetAttrs( de->object, imsg->IDCMPWindow, NULL,
  255.                                 GTLV_Selected, ++(*storage),
  256.                                 TAG_DONE );
  257.                     match = de;
  258.                 }
  259.                 else if( imsg->Code == toupper( tag->ti_Data ) )
  260.                 {
  261.                     if( *storage != ~0 )
  262.                         if( *storage > 0 )
  263.                             GT_SetGadgetAttrs( de->object, imsg->IDCMPWindow, NULL,
  264.                                 GTLV_Selected, --(*storage),
  265.                                 TAG_DONE );
  266.                     match = de;
  267.                 }
  268.         break;
  269.     }
  270.     return match;
  271. }
  272.  
  273. ULONG dispatchListView( struct Hook *hook, DialogElement *de, DialogMessage *dm )
  274. {
  275.     ULONG result;
  276.  
  277.     switch( dm->dm_MethodID )
  278.     {
  279.     case DIALOGM_GETSTRUCT:
  280.         result = getListViewStructure( de );
  281.         break;
  282.     case DIALOGM_SETUP:
  283.         setupListView( de );
  284.         break;
  285.     case DIALOGM_LAYOUT:
  286.         result = layoutListView( de, (LayoutMessage *)dm );
  287.         break;
  288.     case DIALOGM_MATCH:
  289.         result = (ULONG)matchListView( de, (MatchMessage *)dm );
  290.         break;
  291.     case DIALOGM_CLEAR:
  292.         break;
  293.     case DIALOGM_SETATTRS:
  294.         setGTAttrs( de, (SetAttrsMessage *)dm );
  295.         break;
  296.     }
  297.     return result;
  298. }
  299.