;/*
sc DATA=NEAR NMINC STRMERGE NOSTKCHK SAVEDS IGNORE=73 relative
slink FROM LIB:c.o relative.o TO relative LIB LIB:sc.lib LIB:amiga.lib
quit
*/
/* (c) Copyright 1993-1999 Amiga, Inc. All rights reserved. */
/* The information contained herein is subject to change without */
/* notice, and is provided "as is" without warranty of any kind, */
/* either expressed or implied. The entire risk as to the use of */
/* this information is assumed by the user. */
/*
* relative.c - shows custom gadget relativity
*
* custom gadget relativity allows a gadget to arbitrarily resize
* itself whenever the window changes size. This is a complete superset
* of the functionality of the old GRELWIDTH, GRELRIGHT, etc., features.
* This example shows a subclass of gadgetclass whose imagery comes
* from frameiclass. This gadget's property is that it is always half
* the size of its domain, and centered within it. That is, it's always
* half as wide and half as tall as the inner area of its window, and
* centered within that area.
*/
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>
#include <intuition/cghooks.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
struct Library *GfxBase = NULL;
struct Library *IntuitionBase = NULL;
struct Window *win = NULL;
struct Gadget *gad = NULL;
Class *customrelclass = NULL;
Class *initCustomRelClass(void);
ULONG __saveds __asm dispatchCustomRel( register __a0 Class *cl,
register __a2 Object *o,
register __a1 Msg msg );
void renderCustomRel( struct Gadget *gad,
struct RastPort *rp,
struct GadgetInfo *gi );
void layoutCustomRel( struct Gadget *gad,
struct GadgetInfo *gi,
ULONG initial );
LONG handleCustomRel( struct Gadget *gad,
struct gpInput *msg );
void main(void)
{
if ( GfxBase = OpenLibrary("graphics.library",39) )
{
if ( IntuitionBase = OpenLibrary("intuition.library",39) )
{
if ( customrelclass = initCustomRelClass() )
{
if ( gad = NewObject( customrelclass, NULL,
GA_Left, 20,
GA_Top, 20,
GA_Width, 20,
GA_Height, 20,
GA_RelVerify, TRUE,
GA_Immediate, TRUE,
TAG_DONE ) )
{
if ( win = OpenWindowTags( NULL,
WA_Title, "Custom Relativity Demo",
WA_CloseGadget, TRUE,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
WA_SizeGadget, TRUE,
WA_Gadgets, gad,
WA_Activate, TRUE,
WA_IDCMP, IDCMP_GADGETHELP | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW |
IDCMP_GADGETDOWN | IDCMP_GADGETUP,
WA_Width, 150,
WA_Height, 150,
WA_MinWidth, 50,
WA_MinHeight, 50,
WA_MaxWidth, ~0,
WA_MaxHeight, ~0,
WA_NoCareRefresh, TRUE,
TAG_DONE ) )
{
BOOL terminated = FALSE;
struct IntuiMessage *imsg;
/* Turn on Gadget Help */
HelpControl( win, HC_GADGETHELP );
while (!terminated)
{
Wait (1 << win->UserPort->mp_SigBit);
while (imsg = (struct IntuiMessage *) GetMsg(win->UserPort))
{
switch ( imsg->Class )
{
case IDCMP_CLOSEWINDOW:
terminated = TRUE;
break;
case IDCMP_RAWKEY:
printf("RAWKEY %lx\n", imsg->Code);
break;
case IDCMP_GADGETUP:
printf("Gadget Up\n");
break;
case IDCMP_GADGETDOWN:
printf("Gadget Down\n");
break;
case IDCMP_GADGETHELP:
if ( imsg->IAddress == NULL )
{
printf("Gadget Help: Mouse not over window\n");
}
else if ( imsg->IAddress == (APTR) win )
{
printf("Gadget Help: Mouse in window, not over a gadget\n");
}
else
{
/* Detect system gadgets. Figure out by looking at
* system-gadget-type bits in GadgetType field:
*/
LONG sysgtype =
((struct Gadget *)imsg->IAddress)->GadgetType & GTYP_SYSTYPEMASK;
switch ( sysgtype )
{
case GTYP_SIZING:
printf("Gadget Help for window sizing gadget\n");
break;
case GTYP_WDRAGGING:
printf("Gadget Help for window drag-bar\n");
break;
case GTYP_WUPFRONT:
printf("Gadget Help for window depth gadget\n");
break;
case GTYP_WDOWNBACK:
printf("Gadget Help for window zoom gadget\n");
break;
case GTYP_CLOSE:
printf("Gadget Help for window close gadget\n");
break;
case 0:
/* In this example, we only have one gadget,
* so we know which one it is. Normally, you'd
* have to figure that out here, using the
* usual techniques you already use for other
* gadget messages.
*/
printf("Gadget Help for gadget, code 0x%x\n",
imsg->Code);
break;
default:
printf("Gadget Help on some other system gadget\n");
break;
}
}
}
ReplyMsg((struct Message *)imsg);
}
}
CloseWindow( win );
}
DisposeObject( gad );
}
FreeClass( customrelclass );
}
CloseLibrary( IntuitionBase );
}
CloseLibrary( GfxBase );
}
}
/* initCustomRelClass()
*
* Initialize a simple private subclass of gadgetclass that
* knows about GM_LAYOUT.
*
*/
Class *initCustomRelClass( void )
{
Class *cl;
/* Create a private class: */
if ( cl = MakeClass( NULL, "gadgetclass", NULL, 0, 0 ) )
{
cl->cl_Dispatcher.h_SubEntry = NULL;
cl->cl_Dispatcher.h_Entry = dispatchCustomRel;
cl->cl_Dispatcher.h_Data = NULL;
}
return ( cl );
}
/* dispatchCustomRel()
*
* boopsi dispatcher for the custom relativity class.
*
*/
ULONG __saveds __asm
dispatchCustomRel( register __a0 Class *cl,
register __a2 Object *o,
register __a1 Msg msg )
{
ULONG retval = 1;
Object *newobj;
switch ( msg->MethodID )
{
case OM_NEW:
if ( retval = (ULONG)(newobj = (Object *) DoSuperMethodA( cl, o, msg )) )
{
/* Set custom relativity */
((struct Gadget *)newobj)->Flags |= GFLG_RELSPECIAL;
/* Tell Intuition this gadget supports gadget help */
SetAttrs(newobj, GA_GadgetHelp, TRUE, TAG_DONE, NULL);
/* Attempt to allocate a frame. If I can't, then
* delete myself and fail.
*/
if ( ! ( ((struct Gadget *)newobj)->GadgetRender =
NewObject( NULL, "frameiclass",
IA_FrameType, FRAME_BUTTON,
TAG_DONE ) ) )
{
CoerceMethod( cl, o, OM_DISPOSE );
retval = NULL;
}
}
break;
case GM_LAYOUT:
layoutCustomRel( (struct Gadget *)o, ((struct gpLayout *)msg)->gpl_GInfo,
((struct gpLayout *)msg)->gpl_Initial );
break;
case GM_RENDER:
renderCustomRel( (struct Gadget *)o, ((struct gpRender *) msg)->gpr_RPort,
((struct gpRender *) msg)->gpr_GInfo );
break;
case GM_GOACTIVE:
return( GMR_MEACTIVE );
break;
case GM_HELPTEST:
return(GMR_HELPCODE | 0x0000C0DE);
break;
case GM_HANDLEINPUT:
retval = handleCustomRel( (struct Gadget *)o, (struct gpInput *)msg );
break;
case OM_DISPOSE:
DisposeObject( ((struct Gadget *)o)->GadgetRender );
/* fall through to default */
default:
retval = (ULONG) DoSuperMethodA( cl, o, msg );
}
return( retval );
}
/* renderCustomRel()
*
* Simple routine to draw my imagery based on my selected state.
*
*/
void
renderCustomRel( struct Gadget *gad, struct RastPort *rp, struct GadgetInfo *gi )
{
DrawImageState( rp, gad->GadgetRender, gad->LeftEdge, gad->TopEdge,
(gad->Flags & GFLG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
gi ? gi->gi_DrInfo : NULL );
}
/* layoutCustomRel()
*
* Lay myself out based on my domain dimensions. Refigure my own size,
* then inform my image of the size change.
*
*/
void
layoutCustomRel( struct Gadget *gad, struct GadgetInfo *gi, ULONG initial )
{
if ( gi->gi_Requester )
{
/* Center it within the requester */
gad->Width = gi->gi_Domain.Width / 2;
gad->Height = gi->gi_Domain.Height / 2;
gad->LeftEdge = gad->Width / 2;
gad->TopEdge = gad->Height / 2;
}
else
{
/* Center it within the window, after accounting for
* the window borders
*/
gad->Width = ( gi->gi_Domain.Width -
gi->gi_Window->BorderLeft - gi->gi_Window->BorderRight ) / 2;
gad->Height = ( gi->gi_Domain.Height -
gi->gi_Window->BorderTop - gi->gi_Window->BorderBottom ) / 2;
gad->LeftEdge = ( gad->Width / 2 ) + gi->gi_Window->BorderLeft;
gad->TopEdge = ( gad->Height / 2 ) + gi->gi_Window->BorderTop;
}
SetAttrs( gad->GadgetRender,
IA_Width, gad->Width,
IA_Height, gad->Height,
TAG_DONE );
}
/* handleCustomRel()
*
* Routine to handle input to the gadget. Behaves like a basic
* hit-select gadget.
*
*/
LONG
handleCustomRel( struct Gadget *gad, struct gpInput *msg )
{
WORD selected = 0;
struct RastPort *rp;
LONG retval = GMR_MEACTIVE;
/* Could send IM_HITTEST to image instead */
if ( ( msg->gpi_Mouse.X >= 0 ) &&
( msg->gpi_Mouse.X < gad->Width ) &&
( msg->gpi_Mouse.Y >= 0 ) &&
( msg->gpi_Mouse.Y < gad->Height ) )
{
selected = GFLG_SELECTED;
}
if ((msg->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE) &&
(msg->gpi_IEvent->ie_Code == SELECTUP))
{
/* gadgetup, time to go */
if ( selected )
{
retval = GMR_NOREUSE | GMR_VERIFY;
}
else
{
retval = GMR_NOREUSE;
}
/* and unselect the gadget on our way out... */
selected = 0;
}
if ( ( gad->Flags & GFLG_SELECTED ) != selected )
{
gad->Flags ^= GFLG_SELECTED;
if ( rp = ObtainGIRPort( msg->gpi_GInfo ) )
{
DoMethod( (Object *)gad, GM_RENDER, msg->gpi_GInfo, rp, GREDRAW_UPDATE );
ReleaseGIRPort( rp );
}
}
return( retval );
}