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 >
Wrap
C/C++ Source or Header
|
1993-03-07
|
8KB
|
299 lines
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <graphics/text.h>
#include <proto/diskfont.h>
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <ctype.h>
#include <string.h>
#include "dialog.h"
#ifdef DEBUG1
#include <stdio.h>
#endif
static LONG countItems( DialogElement *de )
{
struct List *list;
struct Node *node;
ULONG labels;
LONG count = 0;
if( !de )
return 0;
labels = GetTagData( GTLV_Labels, 0, de->taglist );
if( labels == 0 || labels == ~0 )
goto termination;
list = (struct List *)labels;
for( node = list->lh_Head; node->ln_Succ; node = node->ln_Succ )
count++;
termination:
return count;
}
static ULONG getListViewStructure( DialogElement *de )
{
ULONG place, structure = 0;
if( !de )
return 0;
if( GetTagData( NGDA_GadgetText, 0, de->taglist ) )
{
place = getTextPlacement( GetTagData( NGDA_Flags, 0, de->taglist ), PLACETEXT_ABOVE );
switch( place )
{
case PLACETEXT_ABOVE:
case PLACETEXT_BELOW:
structure = DESF_HBaseline;
break;
case PLACETEXT_LEFT:
case PLACETEXT_RIGHT:
structure = DESF_VBaseline;
break;
}
}
return structure;
}
static VOID setupListView( DialogElement *de )
{
struct TextAttr *ta;
struct TextFont *tf;
struct RastPort rp;
struct TextExtent te;
STRPTR text;
LONG scrollwidth, minwidth, minheight, textwidth, textheight;
ULONG place;
LONG *storage;
if( !de )
return;
de->idcmp_mask |= LISTVIEWIDCMP | IDCMP_REFRESHWINDOW | IDCMP_VANILLAKEY;
storage = (LONG *)GetTagData( DA_Storage, 0, de->taglist );
if( storage )
*storage = GetTagData( GTLV_Selected, ~0, de->taglist );
scrollwidth = GetTagData( GTLV_ScrollWidth, 16, de->taglist );
ta = (struct TextAttr *)GetTagData( NGDA_TextAttr, 0, de->taglist );
if( !ta )
return;
tf = OpenDiskFont( ta );
if( !tf )
return;
/* minimal dimensions: 3 visible items, 3 visible label characters */
/* note: the constants "4" and "2" are the thicknesses of the frame */
minwidth = 4 + 3 * tf->tf_XSize + 4 + scrollwidth;
minheight = 2 + 3 * tf->tf_YSize + GetTagData( LAYOUTA_Spacing, 0, de->taglist ) + 2;
if( (struct Gadget *)GetTagData( GTLV_ShowSelected, ~0, de->taglist ) == NULL )
minheight += 2 + tf->tf_YSize + 2;
text = (STRPTR)GetTagData( NGDA_GadgetText, 0, de->taglist );
place = getTextPlacement( GetTagData( NGDA_Flags, 0, de->taglist ), PLACETEXT_ABOVE );
if( text )
{
InitRastPort( &rp );
SetFont( &rp, tf );
TextExtent( &rp, text, strlen( text ), &te );
}
else
{
te.te_Extent.MinX = te.te_Extent.MinY = 0;
te.te_Extent.MaxX = te.te_Extent.MaxY = -1;
}
CloseFont( tf );
textwidth = te.te_Extent.MaxX + 1 - te.te_Extent.MinX;
textheight = te.te_Extent.MaxY + 1 - te.te_Extent.MinY;
switch( place )
{
case PLACETEXT_ABOVE:
if( minwidth < textwidth )
minwidth = textwidth;
setMinWidth( de, minwidth );
setMaxWidth( de, MAX_SPACE );
setMinTopExtent( de, textheight + INTERHEIGHT );
setMaxTopExtent( de, textheight + INTERHEIGHT );
setMinBottomExtent( de, minheight );
setMaxBottomExtent( de, MAX_SPACE );
break;
case PLACETEXT_BELOW:
if( minwidth < textwidth )
minwidth = textwidth;
setMinWidth( de, minwidth );
setMaxWidth( de, MAX_SPACE );
setMinTopExtent( de, minheight );
setMaxTopExtent( de, MAX_SPACE );
setMinBottomExtent( de, textheight + INTERHEIGHT );
setMaxBottomExtent( de, textheight + INTERHEIGHT );
break;
case PLACETEXT_LEFT:
if( minheight < textheight )
minheight = textheight;
setMinLeftExtent( de, textwidth + INTERWIDTH );
setMaxLeftExtent( de, textwidth + INTERWIDTH );
setMinRightExtent( de, minwidth );
setMaxRightExtent( de, MAX_SPACE );
setMinHeight( de, minheight );
setMaxHeight( de, MAX_SPACE );
break;
case PLACETEXT_RIGHT:
if( minheight < textheight )
minheight = textheight;
setMinLeftExtent( de, minwidth );
setMaxLeftExtent( de, MAX_SPACE );
setMinRightExtent( de, textwidth + INTERWIDTH );
setMaxRightExtent( de, textwidth + INTERWIDTH );
setMinHeight( de, minheight );
setMaxHeight( de, MAX_SPACE );
break;
case PLACETEXT_IN:
setMinWidth( de, minwidth );
setMaxWidth( de, MAX_SPACE );
setMinHeight( de, minheight );
setMaxHeight( de, MAX_SPACE );
}
}
static ULONG layoutListView( DialogElement *de, LayoutMessage *lm )
{
struct NewGadget ng;
ULONG place, error = DIALOGERR_OK;
if( !de )
return DIALOGERR_BAD_ARGS;
if( !lm )
return DIALOGERR_BAD_ARGS;
#ifdef DEBUG1
printf(
"layoutListView : x %d, y %d, width %d, height %d, left %d, right %d, top %d, bottom %d\n",
lm->lm_X, lm->lm_Y, lm->lm_Width, lm->lm_Height,
lm->lm_Left, lm->lm_Right, lm->lm_Top, lm->lm_Bottom );
#endif
ng.ng_GadgetText = (UBYTE *)GetTagData( NGDA_GadgetText, 0, de->taglist );
ng.ng_TextAttr = (struct TextAttr *)GetTagData( NGDA_TextAttr, 0, de->taglist );
ng.ng_VisualInfo = (APTR)GetTagData( NGDA_VisualInfo, 0, de->taglist );
ng.ng_Flags = GetTagData( NGDA_Flags, 0, de->taglist );
ng.ng_LeftEdge = lm->lm_X;
ng.ng_TopEdge = lm->lm_Y;
place = getTextPlacement( ng.ng_Flags, PLACETEXT_ABOVE );
switch( place )
{
case PLACETEXT_LEFT:
ng.ng_Width = lm->lm_Right;
ng.ng_Height = lm->lm_Height;
break;
case PLACETEXT_RIGHT:
ng.ng_LeftEdge -= lm->lm_Left;
ng.ng_Width = lm->lm_Left;
ng.ng_Height = lm->lm_Height;
break;
case PLACETEXT_ABOVE:
ng.ng_Width = lm->lm_Width;
ng.ng_Height = lm->lm_Bottom;
break;
case PLACETEXT_BELOW:
ng.ng_TopEdge -= lm->lm_Top;
ng.ng_Width = lm->lm_Width;
ng.ng_Height = lm->lm_Top;
break;
case PLACETEXT_IN:
ng.ng_Width = lm->lm_Width;
ng.ng_Height = lm->lm_Height;
break;
}
de->object = CreateGadgetA( LISTVIEW_KIND, *lm->lm_PreviousPtr, &ng, de->taglist );
*lm->lm_PreviousPtr = de->object; /* advance "previous" pointer to new object */
if( !de->object )
error = DIALOGERR_NO_MEMORY;
return error;
}
static DialogElement *matchListView( DialogElement *de, MatchMessage *mm )
{
struct IntuiMessage *imsg;
DialogElement *match = NULL;
struct TagItem *tag;
LONG *storage;
if( !de )
return NULL;
if( !mm )
return NULL;
storage = (LONG *)GetTagData( DA_Storage, 0, de->taglist );
imsg = mm->mm_IntuiMsg;
switch( imsg->Class )
{
case IDCMP_GADGETUP:
if( de->object == imsg->IAddress )
{
if( storage )
*storage = (ULONG)imsg->Code; /* store current level */
match = de;
}
break;
case IDCMP_VANILLAKEY:
if( storage )
if( tag = FindTagItem( DA_EquivalentKey, de->taglist ) )
if( imsg->Code == tolower( tag->ti_Data ) )
{
if( *storage != ~0 )
if( *storage < countItems( de ) - 1 )
GT_SetGadgetAttrs( de->object, imsg->IDCMPWindow, NULL,
GTLV_Selected, ++(*storage),
TAG_DONE );
match = de;
}
else if( imsg->Code == toupper( tag->ti_Data ) )
{
if( *storage != ~0 )
if( *storage > 0 )
GT_SetGadgetAttrs( de->object, imsg->IDCMPWindow, NULL,
GTLV_Selected, --(*storage),
TAG_DONE );
match = de;
}
break;
}
return match;
}
ULONG dispatchListView( struct Hook *hook, DialogElement *de, DialogMessage *dm )
{
ULONG result;
switch( dm->dm_MethodID )
{
case DIALOGM_GETSTRUCT:
result = getListViewStructure( de );
break;
case DIALOGM_SETUP:
setupListView( de );
break;
case DIALOGM_LAYOUT:
result = layoutListView( de, (LayoutMessage *)dm );
break;
case DIALOGM_MATCH:
result = (ULONG)matchListView( de, (MatchMessage *)dm );
break;
case DIALOGM_CLEAR:
break;
case DIALOGM_SETATTRS:
setGTAttrs( de, (SetAttrsMessage *)dm );
break;
}
return result;
}