398 lines
10 KiB
C
398 lines
10 KiB
C
/*************************************************************************
|
|
* ClassAct Comprehensive Demo Program
|
|
* Copyright © 1995 Osma Ahvenlampi
|
|
*
|
|
*/
|
|
|
|
#include <exec/types.h>
|
|
#include <exec/memory.h>
|
|
#include <intuition/intuition.h>
|
|
#include <intuition/gadgetclass.h>
|
|
#include <intuition/icclass.h>
|
|
#include <libraries/gadtools.h>
|
|
#include <graphics/gfxbase.h>
|
|
#include <graphics/text.h>
|
|
#include <graphics/gfxmacros.h>
|
|
#include <utility/tagitem.h>
|
|
#include <workbench/startup.h>
|
|
#include <workbench/workbench.h>
|
|
#include <datatypes/datatypes.h>
|
|
#include <datatypes/datatypesclass.h>
|
|
|
|
#include <proto/datatypes.h>
|
|
#include <proto/intuition.h>
|
|
#include <proto/graphics.h>
|
|
#include <proto/exec.h>
|
|
#include <proto/dos.h>
|
|
#include <proto/diskfont.h>
|
|
#include <proto/utility.h>
|
|
#include <proto/wb.h>
|
|
#include <proto/icon.h>
|
|
|
|
#include <classact.h>
|
|
#include <classact_lib.h>
|
|
#include <clib/classact_lib_protos.h>
|
|
|
|
/* get LayerHook.lha from Aminet for this */
|
|
#include <imagebackfill.h>
|
|
|
|
/*************************************************************************
|
|
* Backfill options
|
|
* We're using the public domain LayerHook here.
|
|
*/
|
|
struct BackFillOptions Options =
|
|
{
|
|
256,256,
|
|
// !!! 0,0,
|
|
TRUE,FALSE,
|
|
0,0,
|
|
TRUE
|
|
};
|
|
|
|
struct BackFillInfo BF1, BF2, *Backfill;
|
|
|
|
UBYTE name[256];
|
|
|
|
/*************************************************************************
|
|
* Gadget list
|
|
* This wouldn't be strictly necessary, but it's an easy way of keeping
|
|
* the gadget pointers for when we need to access the gadgets.
|
|
*/
|
|
typedef enum { G_Backfill = 1, G_Datatype, G_MAX } GadgetIDs;
|
|
|
|
struct Gadget *GL[G_MAX+1];
|
|
|
|
/*************************************************************************
|
|
* App message hook.
|
|
* Workbench App messages can be caught with a callback hook such as this.
|
|
* We'll not worry about the app message type in this hook. Objects dropped
|
|
* on the window or on the icon (while iconified) will be added to the
|
|
* listview.
|
|
*/
|
|
|
|
void __asm __saveds AppMsgFunc( register __a0 struct Hook *Hook,
|
|
register __a2 Object *Window,
|
|
register __a1 struct AppMessage *Msg )
|
|
{
|
|
struct Window *Win;
|
|
struct WBArg *arg = Msg->am_ArgList;
|
|
Object *dt;
|
|
|
|
GetAttr( WINDOW_Window, Window, (ULONG *)&Win );
|
|
|
|
NameFromLock( arg->wa_Lock, name, sizeof(name) );
|
|
AddPart( name, arg->wa_Name, sizeof(name) );
|
|
|
|
dt = NewDTObject( name,
|
|
DTA_GroupID, GID_PICTURE,
|
|
ICA_TARGET, ICTARGET_IDCMP,
|
|
TAG_END );
|
|
|
|
if (dt)
|
|
{
|
|
SetGadgetAttrs( (struct Gadget *)Hook->h_Data, Win, NULL,
|
|
LAYOUT_ModifyChild, GL[G_Datatype],
|
|
CHILD_ReplaceObject, dt,
|
|
TAG_END );
|
|
GL[G_Datatype] = (struct Gadget *)dt;
|
|
RethinkLayout( (struct Gadget *)Hook->h_Data, Win, NULL, FALSE );
|
|
}
|
|
}
|
|
|
|
struct Hook apphook;
|
|
|
|
/*************************************************************************
|
|
* IDCMP hook
|
|
*/
|
|
|
|
void __asm __saveds IDCMPFunc( register __a0 struct Hook *Hook,
|
|
register __a2 Object *Window,
|
|
register __a1 struct IntuiMessage *Msg )
|
|
{
|
|
struct Window *Win;
|
|
|
|
GetAttr( WINDOW_Window, Window, (ULONG *)&Win );
|
|
|
|
if (Msg->Class == IDCMP_IDCMPUPDATE)
|
|
{
|
|
if ( GetTagData( DTA_Sync, FALSE, Msg->IAddress ) )
|
|
{
|
|
RefreshGList( (struct Gadget *)Hook->h_Data, Win, NULL, 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Hook idcmphook;
|
|
|
|
/*************************************************************************
|
|
* This function creates our gadgets for the window.
|
|
*/
|
|
Object *CreateLayout(void)
|
|
{
|
|
return VGroupObject, Offset(32,32,32,32),
|
|
LAYOUT_BevelStyle, BVS_THIN,
|
|
|
|
/* this tag instructs layout.gadget to defer GM_LAYOUT and GM_RENDER and ask
|
|
* the windowclass to do them. This lessens the load on input.device
|
|
*/
|
|
LAYOUT_DeferLayout, TRUE,
|
|
|
|
/* this gives us a backfill
|
|
*/
|
|
CLASSACT_BackFill, Backfill,
|
|
|
|
/* this dummy object will be replaced with a datatype when we have a picture
|
|
*/
|
|
StartMember, apphook.h_Data = idcmphook.h_Data = LayoutObject, VCentered, HCentered,
|
|
LAYOUT_BevelStyle, BVS_THIN,
|
|
LAYOUT_BevelState, IDS_SELECTED,
|
|
LAYOUT_SpaceOuter, TRUE,
|
|
|
|
/* We need to install this clearing backfill hook because
|
|
* most of the datatypes really screw up rendering if the
|
|
* background isn't color 0.
|
|
*/
|
|
LAYOUT_BackFill, LAYERS_BACKFILL,
|
|
StartImage, GL[G_Datatype] = LabelObject,
|
|
LABEL_Text, "Please drop picture icons on this window",
|
|
EndImage,
|
|
CHILD_MinHeight, 128,
|
|
EndMember,
|
|
|
|
StartMember, GL[G_Backfill] = ButtonObject,
|
|
GA_Text, "Use as a backfill",
|
|
GA_ID, G_Backfill,
|
|
GA_RelVerify, TRUE,
|
|
EndMember,
|
|
CHILD_WeightedHeight, 0,
|
|
EndGroup;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* Main Program
|
|
*/
|
|
int
|
|
main(void)
|
|
{
|
|
struct MsgPort *appport;
|
|
struct Screen *Scr;
|
|
|
|
if (!ButtonBase) /* force it open */
|
|
return 30;
|
|
|
|
/* By providing a message port you enable windowclass to handle iconification
|
|
* and appwindows. This port can shared by all the windows of your application.
|
|
*/
|
|
appport = CreateMsgPort();
|
|
Scr = LockPubScreen(NULL);
|
|
|
|
if (appport && Scr)
|
|
{
|
|
Object *Window;
|
|
|
|
apphook.h_Entry = (ULONG (* )())AppMsgFunc;
|
|
apphook.h_SubEntry = NULL;
|
|
|
|
idcmphook.h_Entry = (ULONG (* )())IDCMPFunc;
|
|
idcmphook.h_SubEntry = NULL;
|
|
|
|
/* Create a Window object with a Layout. When Window is asked to open itself,
|
|
* it will calculate how much space the Layout needs and size itself accordingly.
|
|
*/
|
|
|
|
Window = WindowObject,
|
|
|
|
/* these tags describe the window
|
|
*/
|
|
|
|
WA_IDCMP, IDCMP_RAWKEY,
|
|
WA_Top, 20,
|
|
WA_Left, 20,
|
|
WA_SizeGadget, TRUE,
|
|
WA_DepthGadget, TRUE,
|
|
WA_DragBar, TRUE,
|
|
WA_CloseGadget, TRUE,
|
|
WA_Activate, TRUE,
|
|
|
|
WA_Title, "ClassAct backfill/datatype example",
|
|
WA_ScreenTitle, "ClassAct Copyright 1995 Phantom Development LLC.",
|
|
|
|
/* Add an iconification gadget. If you have this, you must listen to
|
|
* WMHI_ICONIFY.
|
|
*/
|
|
|
|
WINDOW_IconifyGadget, TRUE,
|
|
|
|
/* This message port lets windowclass handle the icon and appwindow.
|
|
*/
|
|
|
|
WINDOW_AppPort, appport,
|
|
WINDOW_AppWindow, TRUE,
|
|
WINDOW_AppMsgHook, &apphook,
|
|
|
|
/* This sets up windowclass to relay IDCMPUPDATE messages to the
|
|
* application's hook.
|
|
*/
|
|
|
|
WINDOW_IDCMPHook, &idcmphook,
|
|
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE,
|
|
|
|
/* The windowclass will automatically free the DiskObject used when
|
|
* iconifying the window. If you do not provide a valid DiskObject,
|
|
* windowclass will try to use env:sys/def_window.info or the default
|
|
* project icon.
|
|
*/
|
|
|
|
WINDOW_Icon, GetDiskObject( "BackfillExample" ),
|
|
WINDOW_IconTitle, "ClassAct Example",
|
|
|
|
/* Below is the layout of the window
|
|
*/
|
|
|
|
WINDOW_Layout, CreateLayout(),
|
|
EndWindow;
|
|
|
|
if (Window)
|
|
{
|
|
/* Window pointer cache.
|
|
*/
|
|
|
|
struct Window *Win;
|
|
BOOL changebackfill = FALSE;
|
|
|
|
if (Win = CA_OpenWindow( Window ))
|
|
{
|
|
ULONG wsig, asig = 1L << appport->mp_SigBit;
|
|
BOOL done = FALSE;
|
|
|
|
/* Now that the window has been opened, we can get the signal mask
|
|
* of its user port. If the program supported iconification and didn't
|
|
* use a shared IDCMP port between all windows, this signal bit
|
|
* would have to be re-queried before each Wait().
|
|
*/
|
|
|
|
GetAttr( WINDOW_SigMask, Window, &wsig );
|
|
|
|
while (done == FALSE)
|
|
{
|
|
ULONG sig = Wait(wsig | asig | SIGBREAKF_CTRL_C);
|
|
ULONG result;
|
|
UWORD code;
|
|
|
|
if (sig & (wsig | asig))
|
|
{
|
|
/* Messages waiting at the window's IDCMP port. Loop at WM_HANDLEINPUT
|
|
* until all have been processed.
|
|
*/
|
|
|
|
while ((result = CA_HandleInput(Window,&code)) != WMHI_LASTMSG)
|
|
{
|
|
/* The return code of this method is two-part. The upper word describes the
|
|
* class of the message (gadgetup, menupick, closewindow, iconify, etc),
|
|
* and the lower word is a class-defined ID, currently in use in the
|
|
* gadgetup and menupick return codes.
|
|
* Switch on the class, then on the ID.
|
|
*/
|
|
|
|
switch(result & WMHI_CLASSMASK)
|
|
{
|
|
case WMHI_GADGETUP:
|
|
|
|
/* OK, got a gadgetup from something. Lets find out what the something is.
|
|
* The code WORD to which a pointer was passed to WM_HANDLEINPUT has been
|
|
* set to the Code value from the IDCMP_GADGETUP, in case we need it.
|
|
*/
|
|
|
|
switch(result & WMHI_GADGETMASK)
|
|
{
|
|
case G_Backfill:
|
|
changebackfill = TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WMHI_CLOSEWINDOW:
|
|
/* The window close gadget was hit. Time to die...
|
|
*/
|
|
done = TRUE;
|
|
break;
|
|
|
|
case WMHI_ICONIFY:
|
|
/* Window requests that it be iconified. Handle this event as
|
|
* soon as possible. The window is not iconified automatically to
|
|
* give you a chance to make note that the window pointer will be
|
|
* invalid before the window closes. It also allows you to free
|
|
* resources only needed when the window is open, if you wish to.
|
|
*/
|
|
if (CA_Iconify( Window ))
|
|
Win = NULL;
|
|
break;
|
|
|
|
case WMHI_UNICONIFY:
|
|
/* The window should be reopened. If you had free'd something
|
|
* on iconify, now is the time to re-allocate it, before calling
|
|
* CA_OpenWindow.
|
|
*/
|
|
Win = CA_OpenWindow( Window );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (sig & SIGBREAKF_CTRL_C)
|
|
{
|
|
done = TRUE;
|
|
}
|
|
|
|
if (changebackfill)
|
|
{
|
|
Object *layout;
|
|
|
|
/* This is a quick&dirty demo using an unmodified LayerHook (on Aminet).
|
|
* This hook can not change its source bitmap on the fly.
|
|
* Becaue of this, we have to do a bit of a juggling act to
|
|
* replace the current backfill.
|
|
*/
|
|
if (Backfill == &BF1)
|
|
{
|
|
Backfill = NULL;
|
|
if (LoadBackgroundImage( &BF2, name, Scr, &Options ))
|
|
{
|
|
Backfill = &BF2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Backfill = NULL;
|
|
if (LoadBackgroundImage( &BF1, name, Scr, &Options ))
|
|
{
|
|
Backfill = &BF1;
|
|
}
|
|
}
|
|
if (layout = CreateLayout())
|
|
{
|
|
SetAttrs(Window, WINDOW_Layout, layout, TAG_END);
|
|
/* backfill changed, it's not safe to dispose the old
|
|
* one. */
|
|
UnloadBackgroundImage((Backfill == &BF1) ? &BF2 : &BF1);
|
|
}
|
|
else
|
|
{
|
|
/* layout failed */
|
|
UnloadBackgroundImage(Backfill);
|
|
}
|
|
changebackfill = FALSE;
|
|
}
|
|
}
|
|
/* Close the window and dispose of all attached gadgets
|
|
*/
|
|
DisposeObject( Window );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (appport)
|
|
DeleteMsgPort(appport);
|
|
if (Scr)
|
|
UnlockPubScreen(NULL,Scr);
|
|
}
|