home *** CD-ROM | disk | FTP | other *** search
- /*
- ** File: paletteclass.c
- ** Description: BOOPSI (BGUI) palette selector gadget class.
- ** Copyright: (C) Copyright 1995 Jaba Development.
- ** (C) Copyright 1995 Jan van den Baard.
- ** All Rights Reserved.
- **/
-
- #include <exec/types.h>
- #include <intuition/intuition.h>
- #include <graphics/gfxmacros.h>
- #include <libraries/bgui.h>
-
- #include <clib/alib_protos.h>
-
- #include <proto/exec.h>
- #include <proto/intuition.h>
- #include <proto/graphics.h>
- #include <proto/bgui.h>
- #include <proto/utility.h>
-
- #include <string.h>
-
- #include "paletteclass.h"
-
- /*
- ** Compiler stuff.
- **/
- #ifdef _DCC
- #define SAVEDS __geta4
- #define ASM
- #define REG(x) __ ## x
- #else
- #define SAVEDS __saveds
- #define ASM __asm
- #define REG(x) register __ ## x
- #endif
-
- /*
- ** Clamp a value in a range.
- **/
- #define CLAMP(v,i,a) if ( v < i ) v = i; else if ( v > a ) v = a;
-
- /*
- ** Simple type-cast.
- **/
- #define GAD(x) (( struct Gadget * )x)
-
- /*
- ** PaletteClass object instance data.
- **/
- typedef struct {
- UWORD pd_ColorOffset; /* Offset in palette/table. */
- UWORD pd_Depth; /* Palette depth. */
- UWORD pd_NumColors; /* Number of colors. */
- UWORD *pd_PenTable; /* Table of pens. */
- UWORD pd_CurrentColor; /* Currently selected color. */
- Object *pd_Frame; /* Frame for selected color. */
- UWORD pd_Columns; /* Number of columns. */
- struct IBox pd_ColorBox; /* Bounds of real color box. */
- UWORD pd_RectWidth; /* Width of color rectangle. */
- UWORD pd_RectHeight; /* Height of color rectangle. */
- UWORD pd_InitialColor; /* Color selected when going active. */
- BOOL pd_ResetInitial; /* Reset initial color? */
- } PD;
-
- /*
- ** Make sure that "CurrentColor" is a valid
- ** pen number in the colors which are displayed
- ** in the palette object.
- **/
- STATIC ASM UWORD ValidateColor( REG(a0) PD *pd, REG(d0) ULONG pen )
- {
- UWORD *tab = pd->pd_PenTable, i;
-
- /*
- ** Do we have a pen table?
- **/
- if ( tab ) {
- /*
- ** Check the pens in the table.
- **/
- for ( i = 0; i < pd->pd_NumColors; i++ ) {
- /*
- ** Does the pen exist in the
- ** pen table?
- **/
- if ( pen == tab[ i + pd->pd_ColorOffset ] )
- return( pen );
- }
- /*
- ** The pen does not exist in the table.
- ** Make it the first pen in the table.
- **/
- i = tab[ pd->pd_ColorOffset ];
- } else {
- /*
- ** Check if the pen number is
- ** in range.
- **/
- if ( pen >= pd->pd_ColorOffset && pen <= ( pd->pd_ColorOffset + pd->pd_NumColors - 1 ))
- return( pen );
- /*
- ** No. Default to the first pen.
- **/
- i = pd->pd_ColorOffset;
- }
-
- return( i );
- }
-
- /*
- ** Create a new palette object.
- **/
- STATIC ASM ULONG PaletteClassNew( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct opSet *ops )
- {
- PD *pd;
- struct TagItem *tstate = ops->ops_AttrList, *tag;
- Object *label;
- ULONG rc, place;
-
- /*
- ** Let the superclass make the object.
- **/
- if ( rc = DoSuperMethodA( cl, obj, ( Msg )ops )) {
- /*
- ** Get a pointer to the object
- ** it's instance data.
- **/
- pd = ( PD * )INST_DATA( cl, rc );
-
- /*
- ** Preset the data to 0. Don't
- ** know if this is necessary.
- **/
- bzero(( char * )pd, sizeof( PD ));
-
- /*
- ** Setup the default settings.
- **/
- pd->pd_Depth = 1;
- pd->pd_NumColors = 2;
-
- /*
- ** Setup the instance data.
- **/
- while ( tag = NextTagItem( &tstate )) {
- switch ( tag->ti_Tag ) {
-
- case PALETTE_Depth:
- pd->pd_Depth = tag->ti_Data;
- CLAMP( pd->pd_Depth, 1, 8 );
- pd->pd_NumColors = ( 1L << pd->pd_Depth );
- break;
-
- case PALETTE_ColorOffset:
- pd->pd_ColorOffset = tag->ti_Data;
- break;
-
- case PALETTE_PenTable:
- pd->pd_PenTable = ( UWORD * )tag->ti_Data;
- break;
-
- case PALETTE_CurrentColor:
- pd->pd_CurrentColor = tag->ti_Data;
- break;
- }
- }
-
- /*
- ** Make sure the offset stays in range.
- **/
- CLAMP( pd->pd_ColorOffset, 0, 256 - pd->pd_NumColors );
-
- /*
- ** The color must remain OK.
- **/
- pd->pd_CurrentColor = ValidateColor( pd, pd->pd_CurrentColor );
-
- /*
- ** See if the object has a label
- ** attached to it.
- **/
- DoMethod(( Object * )rc, OM_GET, BT_LabelObject, &label );
- if ( label ) {
- /*
- ** Yes. Query the place because it may
- ** not be PLACE_IN for obvious reasons.
- **/
- DoMethod( label, OM_GET, LAB_Place, &place );
- if ( place == PLACE_IN )
- SetAttrs( label, LAB_Place, PLACE_LEFT, TAG_END );
- }
-
- /*
- ** Create a frame for the
- ** currently selected pen.
- **/
- if ( pd->pd_Frame = BGUI_NewObject( BGUI_FRAME_IMAGE, FRM_Type, FRTYPE_BUTTON, FRM_Flags, FRF_RECESSED, TAG_END ))
- return( rc );
-
- /*
- ** No frame means no object.
- **/
- CoerceMethod( cl, ( Object * )rc, OM_DISPOSE );
- }
- return( 0L);
- }
-
- /*
- ** Dispose of the object.
- **/
- STATIC ASM ULONG PaletteClassDispose( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
-
- /*
- ** Dispose of the frame.
- **/
- if ( pd->pd_Frame ) DoMethod( pd->pd_Frame, OM_DISPOSE );
-
- /*
- ** The superclass handles
- ** the rest.
- **/
- return( DoSuperMethodA( cl, obj, msg ));
- }
-
- /*
- ** Get an attribute.
- **/
- STATIC ASM ULONG PaletteClassGet( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct opGet *opg )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
- ULONG rc = 1L;
-
- /*
- ** We only know one attribute.
- **/
- if ( opg->opg_AttrID == PALETTE_CurrentColor )
- /*
- ** Pass on the currently
- ** selected color.
- **/
- *( opg->opg_Storage ) = pd->pd_CurrentColor;
- else
- /*
- ** Everything else goes
- ** to the superclass.
- **/
- rc = DoSuperMethodA( cl, obj, ( Msg )opg );
-
- return( rc );
- }
-
- /*
- ** Render the color rectangles
- ** inside the palette object it's
- ** color box.
- **/
- STATIC ASM VOID RenderColorRects( REG(a0) PD *pd, REG(a1) struct RastPort *rp, REG(a2) struct IBox *area, REG(a3) struct DrawInfo *dri )
- {
- UWORD colorwidth, colorheight, columns = 1, rows = 1, depth = pd->pd_Depth;
- UWORD hadjust = 0, vadjust = 0, left, top, colsize, rowsize, c, r, color;
- UWORD offset = pd->pd_ColorOffset;
-
- /*
- ** Get the first color of the
- ** displayed palette.
- **/
- if ( pd->pd_PenTable ) color = pd->pd_PenTable[ offset ];
- else color = offset;
-
- /*
- ** Get the Width and height of the
- ** area in which we layout the
- ** color rectangles.
- **/
- colorwidth = area->Width;
- colorheight = area->Height;
-
- /*
- ** Layout the color
- ** rectangles.
- **/
- while ( depth ) {
- if (( colorheight << 1 ) > colorwidth ) {
- colorheight >>= 1;
- rows <<= 1;
- } else {
- colorwidth >>= 1;
- columns <<= 1;
- }
- depth--;
- }
-
- /*
- ** Compute the pixel width and
- ** height of the color rectangles.
- **/
- colsize = area->Width / columns;
- rowsize = area->Height / rows;
-
- /*
- ** Since this is not precise
- ** we compute the space left
- ** over to adjust the left
- ** and top offset at which we
- ** begin.
- **
- ** Also we re-compute the color
- ** box dimensions.
- **/
- hadjust = ( area->Width - ( area->Width = colsize * columns )) >> 1;
- vadjust = ( area->Height - ( area->Height = rowsize * rows )) >> 1;
-
- /*
- ** Adjust the colorbox position.
- **/
- area->Left += hadjust;
- area->Top += vadjust;
-
- /*
- ** Get initial left and top offset.
- **/
- left = area->Left + 1;
- top = area->Top + 1;
-
- /*
- ** No patterns!
- **/
- SetAfPt( rp, NULL, 0 );
-
- /*
- ** Set these up. We need this information to
- ** compute the color the mouse is over.
- **/
- pd->pd_Columns = columns;
- pd->pd_RectWidth = colsize;
- pd->pd_RectHeight = rowsize;
-
- /*
- ** Now render the rectangles.
- **/
- for ( r = 0; r < rows; r++ ) {
- for ( c = 0; c < columns; c++ ) {
- /*
- ** The currently selected color
- ** is done with a frameclass object.
- **/
- if ( color == pd->pd_CurrentColor ) {
- /*
- ** Setup the object.
- **/
- SetAttrs( pd->pd_Frame, IA_Left, left,
- IA_Top, top,
- IA_Width, colsize - 1,
- IA_Height, rowsize - 1,
- FRM_BackPen, color,
- TAG_END );
- /*
- ** Render it.
- **/
- DrawImageState( rp, ( struct Image * )pd->pd_Frame, 0, 0, IDS_NORMAL, dri );
- } else {
- /*
- ** Other colors we do ourselves.
- **/
- SetAPen( rp, color );
- RectFill( rp, left, top, left + colsize - 2, top + rowsize - 2 );
- }
- left += colsize;
- /*
- ** Get the next color from the
- ** displayed palette.
- **/
- if ( pd->pd_PenTable ) color = pd->pd_PenTable[ ++offset ];
- else color++;
- }
- left = area->Left + 1;
- top += rowsize;
- }
- }
-
- /*
- ** Render the palette object.
- **/
- STATIC ASM ULONG PaletteClassRender( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct gpRender *gpr )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
- struct RastPort rp = *gpr->gpr_RPort;
- struct DrawInfo *dri = gpr->gpr_GInfo->gi_DrInfo;
- struct IBox *bounds;
- Object *frame;
- ULONG fw = 0, fh = 0;
- static UWORD dispat[ 2 ] = { 0x2222, 0x8888 };
- ULONG rc;
-
- /*
- ** First we let the superclass
- ** render. If it returns 0 we
- ** do not render!
- **/
- if ( rc = DoSuperMethodA( cl, obj, ( Msg )gpr )) {
- /*
- ** Get the hitbox bounds of the object
- ** and copy it's contents. We need to
- ** copy the data because we must adjust
- ** it's contents.
- **/
- DoMethod( obj, OM_GET, BT_HitBox, &bounds );
- pd->pd_ColorBox = *bounds;
-
- /*
- ** Do we have a frame?
- **/
- DoMethod( obj, OM_GET, BT_FrameObject, &frame );
- if ( frame ) {
- /*
- ** Find out the frame thickness.
- **/
- DoMethod( frame, OM_GET, FRM_FrameWidth, &fw );
- DoMethod( frame, OM_GET, FRM_FrameHeight, &fh );
- fw++;
- fh++;
-
- /*
- ** Adjust bounds accoordingly.
- **/
- pd->pd_ColorBox.Left += fw;
- pd->pd_ColorBox.Top += fh;
- pd->pd_ColorBox.Width -= fw << 1;
- pd->pd_ColorBox.Height -= fh << 1;
- }
-
- /*
- ** Render the color rectangles.
- **/
- RenderColorRects( pd, &rp, &pd->pd_ColorBox, dri );
-
- /*
- ** Disabled?
- **/
- if ( GAD( obj )->Flags & GFLG_DISABLED ) {
- SetAPen( &rp, dri ? dri->dri_Pens[ SHADOWPEN ] : 2 );
- SetDrMd( &rp, JAM1 );
- SetAfPt( &rp, dispat, 1 );
- RectFill( &rp, bounds->Left,
- bounds->Top,
- bounds->Left + bounds->Width - 1,
- bounds->Top + bounds->Height - 1 );
- }
-
- }
- return( rc );
- }
-
- /*
- ** Get the pen number of
- ** ordinal color number "num".
- **/
- STATIC ASM ULONG GetPenNumber( REG(a0) PD *pd, REG(d0) ULONG num )
- {
- /*
- ** Return the pen number
- ** from the pen table or...
- **/
- if ( pd->pd_PenTable ) return( pd->pd_PenTable[ pd->pd_ColorOffset + num ] );
-
- /*
- ** From the screen palette.
- **/
- return( num + pd->pd_ColorOffset );
- }
-
- /*
- ** Determine the ordinal number
- ** of the pen in the object.
- **/
- STATIC ASM ULONG GetOrdinalNumber( REG(a0) PD *pd, REG(d0) ULONG pen )
- {
- UWORD *tab = pd->pd_PenTable, i;
-
- /*
- ** Do we have a pen table?
- **/
- if ( tab ) {
- /*
- ** Look up the pen in the table.
- **/
- for ( i = 0; i < pd->pd_NumColors; i++ ) {
- /*
- ** Is this the one?
- **/
- if ( tab[ i + pd->pd_ColorOffset ] == pen )
- return( i );
- }
- }
-
- /*
- ** Return the ordinal palette pen.
- **/
- return( pen - pd->pd_ColorOffset );
- }
-
- /*
- ** Determine which color rectangle
- ** the coordinates are in.
- **/
- STATIC ASM UWORD GetColor( REG(a0) PD *pd, REG(d0) ULONG x, REG(d1) ULONG y )
- {
- UWORD col, row;
-
- /*
- ** Compute the row and column
- ** we clicked on.
- **/
- row = y / pd->pd_RectHeight;
- col = x / pd->pd_RectWidth;
-
- /*
- ** With this information we can simple
- ** compute and return the color under
- ** these coordinates.
- **/
- return( GetPenNumber( pd, ( row * pd->pd_Columns ) + col ));
- }
-
- /*
- ** Get the top-left position of
- ** a color in the color box.
- **/
- STATIC ASM GetTopLeft( REG(a0) PD *pd, REG(d0) UWORD color, REG(a1) UWORD *x, REG(a2) UWORD *y )
- {
- UWORD row, col;
-
- /*
- ** First compute the row and column
- ** of the color.
- **/
- row = color / pd->pd_Columns;
- col = color - ( row * pd->pd_Columns );
-
- /*
- ** Now we can simply get the
- ** x/y position of the color
- ** box.
- **/
- *x = pd->pd_ColorBox.Left + ( col * pd->pd_RectWidth );
- *y = pd->pd_ColorBox.Top + ( row * pd->pd_RectHeight );
- }
-
- /*
- ** Notify about an attribute change.
- **/
- STATIC ULONG NotifyAttrChange( Object *obj, struct GadgetInfo *gi, ULONG flags, Tag tag1, ... )
- {
- return( DoMethod( obj, OM_NOTIFY, &tag1, gi, flags ));
- }
-
- /*
- ** Change the currently selected color.
- **/
- STATIC ASM VOID ChangeSelectedColor( REG(a0) PD *pd, REG(a1) struct GadgetInfo *gi, REG(d0) ULONG newcolor )
- {
- struct RastPort *rp;
- UWORD l, t;
-
- /*
- ** Allocate a rastport.
- **/
- if ( gi && ( rp = ObtainGIRPort( gi ))) {
- /*
- ** First pickup the coordinates
- ** of the currently selected
- ** color.
- **/
- GetTopLeft( pd, GetOrdinalNumber( pd, pd->pd_CurrentColor ), &l, &t );
-
- /*
- ** Render this color rectangle
- ** as not-selected.
- **/
- SetAPen( rp, pd->pd_CurrentColor );
- RectFill( rp, l + 1,
- t + 1,
- l + pd->pd_RectWidth - 1,
- t + pd->pd_RectHeight - 1 );
-
- /*
- ** Now pickup the coordinates
- ** of the new selected color.
- **/
- GetTopLeft( pd, GetOrdinalNumber( pd, newcolor ), &l, &t );
-
- /*
- ** Setup and render the frame to
- ** reflect the new data.
- **/
- SetAttrs( pd->pd_Frame, IA_Left, l + 1,
- IA_Top, t + 1,
- IA_Width, pd->pd_RectWidth - 1,
- IA_Height, pd->pd_RectHeight - 1,
- FRM_BackPen, newcolor,
- TAG_END );
-
- DrawImageState( rp, ( struct Image * )pd->pd_Frame, 0, 0, IDS_NORMAL, gi->gi_DrInfo );
-
- /*
- ** Free up the rastport.
- **/
- ReleaseGIRPort( rp );
- }
- /*
- ** Setup the new color.
- **/
- pd->pd_CurrentColor = newcolor;
- }
-
- /*
- ** Set attributes.
- **/
- STATIC ASM ULONG PaletteClassSet( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct opUpdate *opu )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
- struct TagItem *tag;
- ULONG rc, new;
-
- /*
- ** First the superclass.
- **/
- rc = DoSuperMethodA( cl, obj, ( Msg )opu );
-
- /*
- ** Frame thickness change? When the window in which
- ** we are located has WINDOW_AutoAspect set to TRUE
- ** the windowclass distributes the FRM_ThinFrame
- ** attribute to the objects in the window. Here we
- ** simply intercept it to set the selected color
- ** frame thickness.
- **/
- if ( tag = FindTagItem( FRM_ThinFrame, opu->opu_AttrList ))
- /*
- ** Set it to the frame.
- **/
- SetAttrs( pd->pd_Frame, FRM_ThinFrame, tag->ti_Data, TAG_END );
-
- /*
- ** Color change?
- **/
- if ( tag = FindTagItem( PALETTE_CurrentColor, opu->opu_AttrList )) {
- /*
- ** Make sure it's valid.
- **/
- new = ValidateColor( pd, tag->ti_Data );
- /*
- ** Did it really change?
- **/
- if ( new != pd->pd_CurrentColor ) {
- /*
- ** Yes. Show it and notify
- ** the change.
- **/
- ChangeSelectedColor( pd, opu->opu_GInfo, new );
- NotifyAttrChange( obj, opu->opu_GInfo, opu->MethodID == OM_UPDATE ? opu->opu_Flags : 0L, GA_ID, GAD( obj )->GadgetID, PALETTE_CurrentColor, pd->pd_CurrentColor, TAG_END );
- }
- }
- return( rc );
- }
-
- /*
- ** Let's go active :)
- **/
- STATIC ASM ULONG PaletteClassGoActive( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct gpInput *gpi )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
- WORD l, t;
- UWORD newcol;
- ULONG rc = GMR_NOREUSE;
-
- /*
- ** We do not go active when we are
- ** disabled or when we where activated
- ** by the ActivateGadget() call.
- **/
- if (( GAD( obj )->Flags & GFLG_DISABLED ) || ( ! gpi->gpi_IEvent ))
- return( rc );
-
- /*
- ** Save color selected when going
- ** active. This way we can reset
- ** the initial color when the
- ** gadget activity is aborted by
- ** the user or intuition.
- **/
- pd->pd_InitialColor = pd->pd_CurrentColor;
-
- /*
- ** Get the coordinates relative
- ** to the top-left of the colorbox.
- **/
- l = gpi->gpi_Mouse.X - ( pd->pd_ColorBox.Left - GAD( obj )->LeftEdge );
- t = gpi->gpi_Mouse.Y - ( pd->pd_ColorBox.Top - GAD( obj )->TopEdge );
-
- /*
- ** Are we really hit?
- **/
- if ( l >= 0 && t >= 0 && l < pd->pd_ColorBox.Width && t < pd->pd_ColorBox.Height ) {
- /*
- ** Did the color change?
- **/
- if (( newcol = GetColor( pd, l, t )) != pd->pd_CurrentColor ) {
- /*
- ** Yes. Setup the new color and send
- ** a notification.
- **/
- ChangeSelectedColor( pd, gpi->gpi_GInfo, newcol );
- NotifyAttrChange( obj, gpi->gpi_GInfo, 0L, GA_ID, GAD( obj )->GadgetID, PALETTE_CurrentColor, pd->pd_CurrentColor, TAG_END );
- }
- /*
- ** Go active.
- **/
- rc = GMR_MEACTIVE;
- }
- return( rc );
- }
-
- /*
- ** Handle the user input.
- **/
- STATIC ASM ULONG PaletteClassHandleInput( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct gpInput *gpi )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
- WORD l, t;
- UWORD newcol;
- ULONG rc = GMR_MEACTIVE;
-
- /*
- ** Get the coordinates relative
- ** to the top-left of the colorbox.
- **/
- l = gpi->gpi_Mouse.X - ( pd->pd_ColorBox.Left - GAD( obj )->LeftEdge );
- t = gpi->gpi_Mouse.Y - ( pd->pd_ColorBox.Top - GAD( obj )->TopEdge );
-
- /*
- ** Mouse pointer located over the object?
- **/
- if ( l >= 0 && t >= 0 && l < pd->pd_ColorBox.Width && t < pd->pd_ColorBox.Height ) {
- /*
- ** Mouse over a new color?
- **/
- if (( newcol = GetColor( pd, l, t )) != pd->pd_CurrentColor ) {
- /*
- ** Change the selected color.
- **/
- ChangeSelectedColor( pd, gpi->gpi_GInfo, newcol );
- /*
- ** Send notification
- ** about the change.
- **/
- NotifyAttrChange( obj, gpi->gpi_GInfo, 0L, GA_ID, GAD( obj )->GadgetID, PALETTE_CurrentColor, pd->pd_CurrentColor, TAG_END );
- }
- }
-
- /*
- ** Check mouse input.
- **/
- if ( gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE ) {
- switch ( gpi->gpi_IEvent->ie_Code ) {
-
- case SELECTUP:
- /*
- ** Left-mouse button up means we
- ** return GMR_VERIFY.
- **/
- rc = GMR_NOREUSE | GMR_VERIFY;
- break;
-
- case MENUDOWN:
- /*
- ** The menu button aborts the
- ** selection.
- **/
- pd->pd_ResetInitial = TRUE;
- rc = GMR_NOREUSE;
- break;
- }
- }
- return( rc );
- }
-
- /*
- ** Go inactive.
- **/
- STATIC ASM ULONG PaletteClassGoInactive( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct gpGoInactive *ggi )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
-
- /*
- ** Reset initial color?
- **/
- if ( pd->pd_ResetInitial || ggi->gpgi_Abort == 1 ) {
- /*
- ** Reset color.
- **/
- ChangeSelectedColor( pd, ggi->gpgi_GInfo, pd->pd_InitialColor );
- /*
- ** Notification of the reset.
- **/
- NotifyAttrChange( obj, ggi->gpgi_GInfo, 0L, GA_ID, GAD( obj )->GadgetID, PALETTE_CurrentColor, pd->pd_CurrentColor, TAG_END );
- /*
- ** Clear reset flag.
- **/
- pd->pd_ResetInitial = FALSE;
- }
-
- return( DoSuperMethodA( cl, obj, ( Msg )ggi ));
- }
-
- /*
- ** Tell'm our minimum dimensions.
- **/
- STATIC ASM ULONG PaletteClassDimensions( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct grmDimensions *dim )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
- UWORD mx, my;
- ULONG rc;
-
- /*
- ** First the superclass.
- **/
- rc = DoSuperMethodA( cl, obj, ( Msg )dim );
-
- /*
- ** Now we pass our requirements. Note that
- ** it is a bit difficult for this type of
- ** gadgetclass to determine a suitable
- ** minimum size. It would probably be
- ** best to add tags for optional
- ** specification. I'll leave it at this
- ** for now.
- **/
- switch ( pd->pd_NumColors ) {
-
- case 2:
- case 4:
- case 8:
- mx = 16;
- my = 16;
- break;
-
- case 16:
- case 32:
- mx = 32;
- my = 32;
- break;
-
- default:
- mx = 64;
- my = 64;
- break;
- }
-
- /*
- ** Store these values.
- **/
- *( dim->grmd_MinSize.Width ) += mx;
- *( dim->grmd_MinSize.Height ) += my;
-
- return( rc );
- }
-
- /*
- ** Key activation.
- **/
- STATIC ASM PaletteClassKeyActive( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct wmKeyInput *wmki )
- {
- PD *pd = ( PD * )INST_DATA( cl, obj );
- UWORD qual = wmki->wmki_IEvent->ie_Qualifier, new;
-
- /*
- ** Get the ordinal number of
- ** the currently selected pen.
- **/
- new = GetOrdinalNumber( pd, pd->pd_CurrentColor );
-
- /*
- ** Shifted is backwards, normal forward.
- **/
- if ( qual & ( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT )) {
- if ( new ) new--;
- else new = pd->pd_NumColors - 1;
- } else {
- if ( new < ( pd->pd_NumColors - 1 )) new++;
- else new = 0;
- }
-
- /*
- ** Change the color.
- **/
- ChangeSelectedColor( pd, wmki->wmki_GInfo, GetPenNumber( pd, new ));
-
- /*
- ** Notify the change.
- **/
- NotifyAttrChange( obj, wmki->wmki_GInfo, 0L, GA_ID, GAD( obj )->GadgetID, PALETTE_CurrentColor, pd->pd_CurrentColor, TAG_END );
-
- /*
- ** Setup ID to report to
- ** the event handler.
- **/
- *( wmki->wmki_ID ) = GAD( obj )->GadgetID;
-
- return( WMKF_VERIFY );
- }
-
- /*
- ** The class dispatcher. Here's
- ** where the fun starts.
- **
- ** SAS Users: You should either compile this module with
- ** stack checking turned off (NOSTACKCHECK) or
- ** you must use the "__interrupt" qualifier in
- ** this routine.
- **/
- STATIC SAVEDS ASM ULONG PaletteClassDispatch( REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg )
- {
- ULONG rc;
-
- switch ( msg->MethodID ) {
-
- case OM_NEW:
- rc = PaletteClassNew( cl, obj, ( struct opSet * )msg );
- break;
-
- case OM_DISPOSE:
- rc = PaletteClassDispose( cl, obj, msg );
- break;
-
- case OM_GET:
- rc = PaletteClassGet( cl, obj, ( struct opGet * )msg );
- break;
-
- case OM_SET:
- case OM_UPDATE:
- rc = PaletteClassSet( cl, obj, ( struct opUpdate * )msg );
- break;
-
- case GM_RENDER:
- rc = PaletteClassRender( cl, obj, ( struct gpRender * )msg );
- break;
-
- case GM_GOACTIVE:
- rc = PaletteClassGoActive( cl, obj, ( struct gpInput * )msg );
- break;
-
- case GM_HANDLEINPUT:
- rc = PaletteClassHandleInput( cl, obj, ( struct gpInput * )msg );
- break;
-
- case GM_GOINACTIVE:
- rc = PaletteClassGoInactive( cl, obj, ( struct gpGoInactive * )msg );
- break;
-
- case GRM_DIMENSIONS:
- rc = PaletteClassDimensions( cl, obj, ( struct grmDimensions * )msg );
- break;
-
- case WM_KEYACTIVE:
- rc = PaletteClassKeyActive( cl, obj, ( struct wmKeyInput * )msg );
- break;
-
- default:
- rc = DoSuperMethodA( cl, obj, msg );
- break;
- }
- return( rc );
- }
-
- /*
- ** Initialize the class.
- **/
- Class *InitPaletteClass( void )
- {
- Class *super, *cl = NULL;
-
- /*
- ** Obtain the BaseClass pointer which
- ** will be our superclass.
- **/
- if ( super = BGUI_GetClassPtr( BGUI_BASE_GADGET )) {
- /*
- ** Create the class.
- **/
- if ( cl = MakeClass( NULL, NULL, super, sizeof( PD ), 0L ))
- /*
- ** Setup dispatcher.
- **/
- cl->cl_Dispatcher.h_Entry = ( HOOKFUNC )PaletteClassDispatch;
- }
- return( cl );
- }
-
- /*
- ** Kill the class.
- **/
- BOOL FreePaletteClass( Class *cl )
- {
- return( FreeClass( cl ));
- }
-