2 Copyright © 1995-2011, 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 /****************************************************************************/
50 /* This is utility function used by frameiclass to draw a simple
53 static void DrawFrame(Class
* cl
, struct RastPort
*rport
, UWORD shine
, UWORD shadow
,
54 WORD left
, WORD top
, WORD width
, WORD height
, BOOL thicken
)
56 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
57 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
59 Here we attempt to render a bevel as quickly as possible using
60 as few system calls as possible. Note the ORDER of the rendering
61 and pen (or lack of) setting in important. This routine can be
62 useful alone as a basis for GadTools DrawBevelBox() perhaps, but
63 its real function is rendering the frameiclass components for the
64 various supported styles.
66 It should be futher noted, on the native Amiga chipset, rendering
67 bevels via serious of RectFill()'s is potentially as much as two
68 times faster. However, in the case of AROS the implementation
69 of the graphics drivers would of course be the determining factor.
70 Just as on the native OS, 3rd party gfx boards would be a factor.
72 Additionally, if the frame metrics are changed here for whatever
73 reasons, you MUST also compensate the change in the frame class
74 render method, and framebox specifically the offset values.
77 DEBUG_IFRAME(dprintf("drawframe: width %ld height %ld\n",width
,height
));
83 SetABPenDrMd(rport
, shine
, 0, JAM1
);
84 Move(rport
, left
, top
+ height
);
85 Draw(rport
, left
, top
);
86 Draw(rport
, left
+ width
, top
);
89 SetAPen(rport
, shadow
);
90 Draw(rport
, left
+ width
, top
+ height
);
91 Draw(rport
, left
+ 1, top
+ height
);
95 if (FRAME_SIZE(IntuitionBase
) == 1)
97 /* Thicken Right Side */
98 Move(rport
, left
+ width
- 1, top
+ height
- 1);
99 Draw(rport
, left
+ width
- 1, top
+ 1);
101 /* Thicken Left Side */
102 SetAPen(rport
, shine
);
103 Move(rport
, left
+ 1, top
+ height
- 1);
104 Draw(rport
, left
+ 1, top
+ 1);
106 else if (FRAME_SIZE(IntuitionBase
) == 2)
108 /* Thicken Right Side */
109 Move(rport
, left
+ width
- 1, top
+ 1);
110 Draw(rport
, left
+ width
- 1, top
+ height
- 1);
112 /* Thicken Bottom Side */
113 Draw(rport
, left
+ 2, top
+ height
- 1);
115 /* Thicken Left Side */
116 SetAPen(rport
, shine
);
118 Move(rport
, left
+ 1, top
+ height
- 1);
119 Draw(rport
, left
+ 1, top
+ 1);
121 /* Thicken Top Side */
122 Draw(rport
, left
+ width
- 2, top
+ 1);
129 /****************************************************************************/
131 /* frame attribute setting method */
132 static ULONG
set_frameiclass(Class
*cl
, Object
*o
, struct opSet
*msg
)
134 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
135 struct Library
*UtilityBase
= GetPrivIBase(IntuitionBase
)->UtilityBase
;
136 struct FrameIData
*fid
= INST_DATA(cl
, o
);
138 struct TagItem
*tstate
= msg
->ops_AttrList
;
142 while ((tag
= NextTagItem(&tstate
)))
147 fid
->fid_Recessed
= (BOOL
)( tag
->ti_Data
? TRUE
: FALSE
);
151 fid
->fid_EdgesOnly
= (BOOL
)( tag
->ti_Data
? TRUE
: FALSE
);
156 Data values for IA_FrameType (recognized by FrameIClass)
158 FRAME_DEFAULT: The standard V37-type frame, which has
160 FRAME_BUTTON: Standard button gadget frames, having thicker
161 sides and edged corners.
162 FRAME_RIDGE: A ridge such as used by standard string gadgets.
163 You can recess the ridge to get a groove image.
164 FRAME_ICONDROPBOX: A broad ridge which is the standard imagery
165 for areas in AppWindows where icons may be dropped.
167 fid
->fid_FrameType
= (WORD
)tag
->ti_Data
;
169 switch(fid
->fid_FrameType
)
172 fid
->fid_HOffset
= fid
->fid_VOffset
= 1;
176 DEBUG_IFRAME(dprintf("draw_frameiclass: FRAME_BUTTON\n"));
177 fid
->fid_HOffset
= 1;
178 fid
->fid_VOffset
= 1;
182 fid
->fid_HOffset
= 2;
183 fid
->fid_VOffset
= 2;
186 case FRAME_ICONDROPBOX
:
187 fid
->fid_HOffset
= 3;
188 fid
->fid_VOffset
= 3;
191 } /* switch(fid->fid_FrameType) */
193 if (FRAME_SIZE(IntuitionBase
) > 0)
195 fid
->fid_HOffset
*= 2;
198 if (FRAME_SIZE(IntuitionBase
) == 2)
200 fid
->fid_VOffset
*= 2;
209 } /* set_frameiclass */
211 /****************************************************************************/
213 /* frame render method */
214 static IPTR
draw_frameiclass(Class
*cl
, struct Image
*im
, struct impDraw
*msg
, WORD width
, WORD height
)
216 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)cl
->cl_UserData
;
217 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
218 struct FrameIData
*fid
= INST_DATA(cl
, (Object
*)im
);
221 Default pen array, this should be globally accessable from
222 all the boopsi objects, unless someone as a better idea...
224 UWORD default_pens
[] =
232 1, /* hifilltextPen */
233 0, /* backgroundPen */
234 2 /* hilighttextPen */
238 DEBUG_IFRAME(dprintf("draw_frameiclass: width %ld height %ld\n",width
,height
));
240 /* we will check the rastport present */
243 UWORD
*pens
= default_pens
;
247 struct RastPort
*rp
= msg
->imp_RPort
;
248 BYTE oldapen
= rp
->FgPen
;
249 BYTE oldbpen
= rp
->BgPen
;
250 BYTE olddrmd
= rp
->DrawMode
;
252 /* set up our rendering pens */
255 pens
= msg
->imp_DrInfo
->dri_Pens
;
258 Fall back to mono color bevels if depth is only 1 bitplane.
260 if (msg
->imp_DrInfo
->dri_Depth
== 1)
262 shine
= pens
[SHADOWPEN
];
266 shine
= pens
[SHINEPEN
];
271 shine
= pens
[SHINEPEN
];
274 shadow
= pens
[SHADOWPEN
];
276 switch(msg
->imp_State
)
279 case IDS_INACTIVESELECTED
:
289 I'm so clever :) We want to check if either of selected or
290 recessed is TRUE, and if so, swap the pens. However, if both
291 are true, they effectivly cancel each other out and we do
292 nothing. Rather than two compares against TRUE and an OR of the
293 results, plus the additional check to ignore the case where both
294 are TRUE, we will do an XOR of the bools and check the result.
295 This should prove most efficient too.
298 Recess|select| XOR'd result
299 ------|------|-------
301 ------|------|-------
303 ------|------|-------
305 ------|------|-------
307 ------|------|-------
310 if ( (fid
->fid_Recessed
^ selected
) != 0 )
320 left
= im
->LeftEdge
+ msg
->imp_Offset
.X
;
321 top
= im
->TopEdge
+ msg
->imp_Offset
.Y
;
323 DEBUG_IFRAME(dprintf("draw_frameiclass: type %ld height %ld\n",fid
->fid_FrameType
));
325 switch(fid
->fid_FrameType
)
328 DrawFrame(cl
, rp
, shine
, shadow
, left
, top
, width
, height
, FALSE
);
332 DrawFrame(cl
, rp
, shine
, shadow
, left
, top
, width
, height
, TRUE
);
336 /* render outer pen-inverted thick bevel */
337 DrawFrame(cl
, rp
, shine
, shadow
, left
, top
, width
, height
, TRUE
);
339 /* render inner thick bevel */
340 DrawFrame(cl
, rp
, shadow
, shine
,
341 left
+ fid
->fid_HOffset
/ 2, top
+ fid
->fid_VOffset
/ 2,
342 width
- fid
->fid_HOffset
, height
- fid
->fid_VOffset
,
346 case FRAME_ICONDROPBOX
:
348 WORD hoffset
= fid
->fid_HOffset
* 2 / 3;
349 WORD voffset
= fid
->fid_VOffset
* 2 / 3;
351 /* render outer pen-inverted thick bevel */
352 DrawFrame(cl
, rp
, shine
, shadow
, left
, top
, width
, height
, TRUE
);
354 /* render inner thick bevel */
355 DrawFrame(cl
, rp
, shadow
, shine
, left
+ hoffset
, top
+ voffset
,
356 width
- hoffset
* 2, height
- voffset
* 2, TRUE
);
362 if(!fid
->fid_EdgesOnly
)
366 SetABPenDrMd(rp
, pens
[FILLPEN
], pens
[BACKGROUNDPEN
], JAM1
);
370 SetABPenDrMd(rp
, pens
[BACKGROUNDPEN
], pens
[BACKGROUNDPEN
], JAM1
);
374 left
+ fid
->fid_HOffset
,
375 top
+ fid
->fid_VOffset
,
376 left
+ width
- fid
->fid_HOffset
- 1,
377 top
+ height
- fid
->fid_VOffset
- 1);
381 switch(msg
->imp_State
)
384 case IDS_INACTIVEDISABLED
:
385 case IDS_SELECTEDDISABLED
:
386 RenderDisabledPattern(rp
,
396 SetABPenDrMd(rp
, oldapen
, oldbpen
, olddrmd
);
407 } /* draw_frameiclass */
410 /****************************************************************************/
412 /* frameiclass framebox method */
413 IPTR
FrameIClass__IM_FRAMEBOX(Class
*cl
, Object
*o
, struct impFrameBox
*msg
)
415 struct FrameIData
*fid
= INST_DATA(cl
, o
);
417 /* stegerg: the RKRM docs seem to be wrong. source box (around which
418 the frame goes) is imp_ContentsBox and dest box filled in by
419 this method is imp_FrameBox. */
421 DEBUG_IFRAME(dprintf("framebox_frameiclass: Contents Left %ld Top %ld Width %ld Height %ld\n",
422 msg
->imp_ContentsBox
->Left
,
423 msg
->imp_ContentsBox
->Top
,
424 msg
->imp_ContentsBox
->Width
,
425 msg
->imp_ContentsBox
->Height
));
427 DEBUG_IFRAME(dprintf("framebox_frameiclass: Flags 0x%lx\n",
428 msg
->imp_FrameFlags
));
430 if (msg
->imp_FrameFlags
& FRAMEF_SPECIFY
)
432 msg
->imp_FrameBox
->Left
= msg
->imp_ContentsBox
->Left
+
433 (msg
->imp_ContentsBox
->Width
- msg
->imp_FrameBox
->Width
) / 2;
434 msg
->imp_FrameBox
->Top
= msg
->imp_ContentsBox
->Top
+
435 (msg
->imp_ContentsBox
->Height
- msg
->imp_FrameBox
->Height
) / 2;
439 msg
->imp_FrameBox
->Left
= msg
->imp_ContentsBox
->Left
- fid
->fid_HOffset
;
440 msg
->imp_FrameBox
->Top
= msg
->imp_ContentsBox
->Top
- fid
->fid_VOffset
;
441 msg
->imp_FrameBox
->Width
= msg
->imp_ContentsBox
->Width
+ fid
->fid_HOffset
* 2;
442 msg
->imp_FrameBox
->Height
= msg
->imp_ContentsBox
->Height
+ fid
->fid_VOffset
* 2;
445 DEBUG_IFRAME(dprintf("framebox_frameiclass: Left %ld Top %ld Width %ld Height %ld\n",
446 msg
->imp_FrameBox
->Left
,
447 msg
->imp_FrameBox
->Top
,
448 msg
->imp_FrameBox
->Width
,
449 msg
->imp_FrameBox
->Height
));
452 } /* framebox_frameiclass */
454 IPTR
FrameIClass__OM_SET(Class
*cl
, Object
*o
, struct opSet
*msg
)
456 DEBUG_IFRAME(dprintf("dispatch_frameiclass: set\n"));
457 return DoSuperMethodA(cl
, o
, (Msg
)msg
) + (IPTR
)set_frameiclass(cl
, o
, msg
);
460 IPTR
FrameIClass__OM_NEW(Class
*cl
, Object
*o
, struct opSet
*msg
)
462 DEBUG_IFRAME(dprintf("dispatch_frameiclass: new\n"));
464 o
= (Object
*)DoSuperMethodA(cl
, o
, (Msg
)msg
);
467 struct FrameIData
*fid
= INST_DATA(cl
, o
);
469 /* set some defaults */
470 fid
->fid_EdgesOnly
= FALSE
;
471 fid
->fid_Recessed
= FALSE
;
472 fid
->fid_FrameType
= FRAME_DEFAULT
;
473 fid
->fid_HOffset
= 1;
474 fid
->fid_VOffset
= 1;
476 /* Handle our special tags - overrides defaults */
477 set_frameiclass(cl
, o
, msg
);
483 IPTR
FrameIClass__IM_DRAWFRAME(Class
*cl
, struct Image
*im
, struct impDraw
*msg
)
485 DEBUG_IFRAME(dprintf("dispatch_frameiclass: drawframe Width %ld Height %ld\n", msg
->imp_Dimensions
.Width
, msg
->imp_Dimensions
.Height
));
486 return draw_frameiclass(cl
, im
, msg
, msg
->imp_Dimensions
.Width
, msg
->imp_Dimensions
.Height
);
489 IPTR
FrameIClass__IM_DRAW(Class
*cl
, struct Image
*im
, struct impDraw
*msg
)
491 DEBUG_IFRAME(dprintf("dispatch_frameiclass: draw Width %ld Height %ld\n",im
->Width
, im
->Height
));
492 return draw_frameiclass(cl
, im
, msg
, im
->Width
, im
->Height
);