2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
7 #include <exec/types.h>
10 #include <dos/dosextens.h>
12 #include <intuition/intuition.h>
13 #include <intuition/intuitionbase.h>
14 #include <intuition/classes.h>
15 #include <intuition/classusr.h>
16 #include <intuition/imageclass.h>
17 #include <intuition/cghooks.h>
18 #include <intuition/icclass.h>
20 #include <graphics/gfxbase.h>
21 #include <graphics/gfxmacros.h>
23 #include <utility/tagitem.h>
24 #include <utility/hooks.h>
26 #include <clib/macros.h>
28 #include <proto/exec.h>
29 #include <proto/intuition.h>
30 #include <proto/graphics.h>
31 #include <proto/utility.h>
34 #include "intuition_intern.h"
35 #include <aros/asmcall.h>
36 #include <proto/alib.h>
38 #endif /* !__MORPHOS__ */
40 #define DEBUG_IFRAME(x) ;
42 /****************************************************************************/
44 /* Some handy transparent base class object casting defines.
46 #define IM(o) ((struct Image *)o)
48 /****************************************************************************/
51 #define IntuitionBase ((struct IntuitionBase *)(cl->cl_UserData))
53 /****************************************************************************/
55 /* This is utility function used by frameiclass to draw a simple
58 static void DrawFrame(Class
* cl
, struct RastPort
*rport
, UWORD shine
, UWORD shadow
,
59 WORD left
, WORD top
, WORD width
, WORD height
, BOOL thicken
)
62 Here we attempt to render a bevel as quickly as possible using
63 as few system calls as possible. Note the ORDER of the rendering
64 and pen (or lack of) setting in important. This routine can be
65 useful alone as a basis for GadTools DrawBevelBox() perhaps, but
66 its real function is rendering the frameiclass components for the
67 various supported styles.
69 It should be futher noted, on the native Amiga chipset, rendering
70 bevels via serious of RectFill()'s is potentially as much as two
71 times faster. However, in the case of AROS the implementation
72 of the graphics drivers would ofcourse be the determining factor.
73 Just as on the native OS, 3rd party gfx boards would be a factor.
75 Additionally, if the frame metrics are changed here for whatever
76 reasons, you MUST also compensate the change in the frame class
77 render method, and framebox specifically the offset values.
80 DEBUG_IFRAME(dprintf("drawframe: width %ld height %ld\n",width
,height
));
86 SetABPenDrMd(rport
, shine
, 0, JAM1
);
87 Move(rport
, left
, top
+ height
);
88 Draw(rport
, left
, top
);
89 Draw(rport
, left
+ width
, top
);
92 SetAPen(rport
, shadow
);
93 Draw(rport
, left
+ width
, top
+ height
);
94 Draw(rport
, left
+ 1, top
+ height
);
100 /* Thicken Right Side */
101 Move(rport
, left
+ width
- 1, top
+ height
- 1);
102 Draw(rport
, left
+ width
- 1, top
+ 1);
104 /* Thicken Left Side */
105 SetAPen(rport
, shine
);
106 Move(rport
, left
+ 1, top
+ height
- 1);
107 Draw(rport
, left
+ 1, top
+ 1);
109 else if (FRAME_SIZE
== 2)
111 /* Thicken Right Side */
112 Move(rport
, left
+ width
- 1, top
+ 1);
113 Draw(rport
, left
+ width
- 1, top
+ height
- 1);
115 /* Thicken Bottom Side */
116 Draw(rport
, left
+ 2, top
+ height
- 1);
118 /* Thicken Left Side */
119 SetAPen(rport
, shine
);
121 Move(rport
, left
+ 1, top
+ height
- 1);
122 Draw(rport
, left
+ 1, top
+ 1);
124 /* Thicken Top Side */
125 Draw(rport
, left
+ width
- 2, top
+ 1);
132 /****************************************************************************/
134 /* frame attribute setting method */
135 static ULONG
set_frameiclass(Class
*cl
, Object
*o
, struct opSet
*msg
)
137 struct FrameIData
*fid
= INST_DATA(cl
, o
);
139 struct TagItem
*tstate
= msg
->ops_AttrList
;
143 while ((tag
= NextTagItem((const struct TagItem
**)&tstate
)))
148 fid
->fid_Recessed
= (BOOL
)( tag
->ti_Data
? TRUE
: FALSE
);
152 fid
->fid_EdgesOnly
= (BOOL
)( tag
->ti_Data
? TRUE
: FALSE
);
157 Data values for IA_FrameType (recognized by FrameIClass)
159 FRAME_DEFAULT: The standard V37-type frame, which has
161 FRAME_BUTTON: Standard button gadget frames, having thicker
162 sides and edged corners.
163 FRAME_RIDGE: A ridge such as used by standard string gadgets.
164 You can recess the ridge to get a groove image.
165 FRAME_ICONDROPBOX: A broad ridge which is the standard imagery
166 for areas in AppWindows where icons may be dropped.
168 fid
->fid_FrameType
= (WORD
)tag
->ti_Data
;
170 switch(fid
->fid_FrameType
)
173 fid
->fid_HOffset
= fid
->fid_VOffset
= 1;
177 DEBUG_IFRAME(dprintf("draw_frameiclass: FRAME_BUTTON\n"));
178 fid
->fid_HOffset
= 1;
179 fid
->fid_VOffset
= 1;
183 fid
->fid_HOffset
= 2;
184 fid
->fid_VOffset
= 2;
187 case FRAME_ICONDROPBOX
:
188 fid
->fid_HOffset
= 3;
189 fid
->fid_VOffset
= 3;
192 } /* switch(fid->fid_FrameType) */
196 fid
->fid_HOffset
*= 2;
201 fid
->fid_VOffset
*= 2;
210 } /* set_frameiclass */
212 /****************************************************************************/
214 /* frame render method */
215 static IPTR
draw_frameiclass(Class
*cl
, struct Image
*im
, struct impDraw
*msg
, WORD width
, WORD height
)
217 struct FrameIData
*fid
= INST_DATA(cl
, (Object
*)im
);
220 Default pen array, this should be globally accessable from
221 all the boopsi objects, unless someone as a better idea...
223 UWORD default_pens
[] =
231 1, /* hifilltextPen */
232 0, /* backgroundPen */
233 2 /* hilighttextPen */
237 DEBUG_IFRAME(dprintf("draw_frameiclass: width %ld height %ld\n",width
,height
));
239 /* we will check the rastport present */
242 UWORD
*pens
= default_pens
;
246 struct RastPort
*rp
= msg
->imp_RPort
;
247 BYTE oldapen
= rp
->FgPen
;
248 BYTE oldbpen
= rp
->BgPen
;
249 BYTE olddrmd
= rp
->DrawMode
;
251 /* set up our rendering pens */
254 pens
= msg
->imp_DrInfo
->dri_Pens
;
257 Fall back to mono color bevels if depth is only 1 bitplane.
259 if (msg
->imp_DrInfo
->dri_Depth
== 1)
261 shine
= pens
[SHADOWPEN
];
265 shine
= pens
[SHINEPEN
];
270 shine
= pens
[SHINEPEN
];
273 shadow
= pens
[SHADOWPEN
];
275 switch(msg
->imp_State
)
278 case IDS_INACTIVESELECTED
:
288 I'm so clever :) We want to check if either of selected or
289 recessed is TRUE, and if so, swap the pens. However, if both
290 are true, they effectivly cancel each other out and we do
291 nothing. Rather than two compares against TRUE and an OR of the
292 results, plus the additional check to ignore the case where both
293 are TRUE, we will do an XOR of the bools and check the result.
294 This should prove most efficient too.
297 Recess|select| XOR'd result
298 ------|------|-------
300 ------|------|-------
302 ------|------|-------
304 ------|------|-------
306 ------|------|-------
309 if ( (fid
->fid_Recessed
^ selected
) != 0 )
319 left
= im
->LeftEdge
+ msg
->imp_Offset
.X
;
320 top
= im
->TopEdge
+ msg
->imp_Offset
.Y
;
322 DEBUG_IFRAME(dprintf("draw_frameiclass: type %ld height %ld\n",fid
->fid_FrameType
));
324 switch(fid
->fid_FrameType
)
327 DrawFrame(cl
, rp
, shine
, shadow
, left
, top
, width
, height
, FALSE
);
331 DrawFrame(cl
, rp
, shine
, shadow
, left
, top
, width
, height
, TRUE
);
335 /* render outer pen-inverted thick bevel */
336 DrawFrame(cl
, rp
, shine
, shadow
, left
, top
, width
, height
, TRUE
);
338 /* render inner thick bevel */
339 DrawFrame(cl
, rp
, shadow
, shine
,
340 left
+ fid
->fid_HOffset
/ 2, top
+ fid
->fid_VOffset
/ 2,
341 width
- fid
->fid_HOffset
, height
- fid
->fid_VOffset
,
345 case FRAME_ICONDROPBOX
:
347 WORD hoffset
= fid
->fid_HOffset
* 2 / 3;
348 WORD voffset
= fid
->fid_VOffset
* 2 / 3;
350 /* render outer pen-inverted thick bevel */
351 DrawFrame(cl
, rp
, shine
, shadow
, left
, top
, width
, height
, TRUE
);
353 /* render inner thick bevel */
354 DrawFrame(cl
, rp
, shadow
, shine
, left
+ hoffset
, top
+ voffset
,
355 width
- hoffset
* 2, height
- voffset
* 2, TRUE
);
361 if(!fid
->fid_EdgesOnly
)
365 SetABPenDrMd(rp
, pens
[FILLPEN
], pens
[BACKGROUNDPEN
], JAM1
);
369 SetABPenDrMd(rp
, pens
[BACKGROUNDPEN
], pens
[BACKGROUNDPEN
], JAM1
);
373 left
+ fid
->fid_HOffset
,
374 top
+ fid
->fid_VOffset
,
375 left
+ width
- fid
->fid_HOffset
- 1,
376 top
+ height
- fid
->fid_VOffset
- 1);
380 switch(msg
->imp_State
)
383 case IDS_INACTIVEDISABLED
:
384 case IDS_SELECTEDDISABLED
:
385 RenderDisabledPattern(rp
,
395 SetABPenDrMd(rp
, oldapen
, oldbpen
, olddrmd
);
406 } /* draw_frameiclass */
409 /****************************************************************************/
411 /* frameiclass framebox method */
412 IPTR
FrameIClass__IM_FRAMEBOX(Class
*cl
, Object
*o
, struct impFrameBox
*msg
)
414 struct FrameIData
*fid
= INST_DATA(cl
, o
);
416 /* stegerg: the RKRM docs seem to be wrong. source box (around which
417 the frame goes) is imp_ContentsBox and dest box filled in by
418 this method is imp_FrameBox. */
420 DEBUG_IFRAME(dprintf("framebox_frameiclass: Contents Left %ld Top %ld Width %ld Height %ld\n",
421 msg
->imp_ContentsBox
->Left
,
422 msg
->imp_ContentsBox
->Top
,
423 msg
->imp_ContentsBox
->Width
,
424 msg
->imp_ContentsBox
->Height
));
426 DEBUG_IFRAME(dprintf("framebox_frameiclass: Flags 0x%lx\n",
427 msg
->imp_FrameFlags
));
429 if (msg
->imp_FrameFlags
& FRAMEF_SPECIFY
)
431 msg
->imp_FrameBox
->Left
= msg
->imp_ContentsBox
->Left
+
432 (msg
->imp_ContentsBox
->Width
- msg
->imp_FrameBox
->Width
) / 2;
433 msg
->imp_FrameBox
->Top
= msg
->imp_ContentsBox
->Top
+
434 (msg
->imp_ContentsBox
->Height
- msg
->imp_FrameBox
->Height
) / 2;
438 msg
->imp_FrameBox
->Left
= msg
->imp_ContentsBox
->Left
- fid
->fid_HOffset
;
439 msg
->imp_FrameBox
->Top
= msg
->imp_ContentsBox
->Top
- fid
->fid_VOffset
;
440 msg
->imp_FrameBox
->Width
= msg
->imp_ContentsBox
->Width
+ fid
->fid_HOffset
* 2;
441 msg
->imp_FrameBox
->Height
= msg
->imp_ContentsBox
->Height
+ fid
->fid_VOffset
* 2;
444 DEBUG_IFRAME(dprintf("framebox_frameiclass: Left %ld Top %ld Width %ld Height %ld\n",
445 msg
->imp_FrameBox
->Left
,
446 msg
->imp_FrameBox
->Top
,
447 msg
->imp_FrameBox
->Width
,
448 msg
->imp_FrameBox
->Height
));
451 } /* framebox_frameiclass */
453 IPTR
FrameIClass__OM_SET(Class
*cl
, Object
*o
, struct opSet
*msg
)
455 DEBUG_IFRAME(dprintf("dispatch_frameiclass: set\n"));
456 return DoSuperMethodA(cl
, o
, (Msg
)msg
) + (IPTR
)set_frameiclass(cl
, o
, msg
);
459 IPTR
FrameIClass__OM_NEW(Class
*cl
, Object
*o
, struct opSet
*msg
)
461 DEBUG_IFRAME(dprintf("dispatch_frameiclass: new\n"));
463 o
= (Object
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
466 struct FrameIData
*fid
= INST_DATA(cl
, o
);
468 /* set some defaults */
469 fid
->fid_EdgesOnly
= FALSE
;
470 fid
->fid_Recessed
= FALSE
;
471 fid
->fid_FrameType
= FRAME_DEFAULT
;
472 fid
->fid_HOffset
= 1;
473 fid
->fid_VOffset
= 1;
475 /* Handle our special tags - overrides defaults */
476 set_frameiclass(cl
, o
, msg
);
482 IPTR
FrameIClass__IM_DRAWFRAME(Class
*cl
, struct Image
*im
, struct impDraw
*msg
)
484 DEBUG_IFRAME(dprintf("dispatch_frameiclass: drawframe Width %ld Height %ld\n", msg
->imp_Dimensions
.Width
, msg
->imp_Dimensions
.Height
));
485 return draw_frameiclass(cl
, im
, msg
, msg
->imp_Dimensions
.Width
, msg
->imp_Dimensions
.Height
);
488 IPTR
FrameIClass__IM_DRAW(Class
*cl
, struct Image
*im
, struct impDraw
*msg
)
490 DEBUG_IFRAME(dprintf("dispatch_frameiclass: draw Width %ld Height %ld\n",im
->Width
, im
->Height
));
491 return draw_frameiclass(cl
, im
, msg
, im
->Width
, im
->Height
);