tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / rom / intuition / frameiclass.c
blob60b733ba10d95bda7c16f875f3a8c8f93818bb0c
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
5 */
7 #include <exec/types.h>
9 #include <dos/dos.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>
33 #ifndef __MORPHOS__
34 #include "intuition_intern.h"
35 #include <aros/asmcall.h>
36 #include <proto/alib.h>
37 #include "gadgets.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
51 * bevel.
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));
79 height -= 1;
80 width -= 1;
82 /* Top/Left */
83 SetABPenDrMd(rport, shine, 0, JAM1);
84 Move(rport, left, top + height);
85 Draw(rport, left, top);
86 Draw(rport, left + width, top);
88 /* Bottom/Right */
89 SetAPen(rport, shadow);
90 Draw(rport, left + width, top + height);
91 Draw(rport, left + 1, top + height);
93 if (thicken)
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);
125 } /* if */
127 } /* DrawFrame */
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;
139 struct TagItem *tag;
140 ULONG retval = 0UL;
142 while ((tag = NextTagItem(&tstate)))
144 switch(tag->ti_Tag)
146 case IA_Recessed:
147 fid->fid_Recessed = (BOOL)( tag->ti_Data ? TRUE : FALSE );
148 break;
150 case IA_EdgesOnly:
151 fid->fid_EdgesOnly = (BOOL)( tag->ti_Data ? TRUE : FALSE );
152 break;
154 case IA_FrameType:
156 Data values for IA_FrameType (recognized by FrameIClass)
158 FRAME_DEFAULT: The standard V37-type frame, which has
159 thin edges.
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)
171 case FRAME_DEFAULT:
172 fid->fid_HOffset = fid->fid_VOffset = 1;
173 break;
175 case FRAME_BUTTON:
176 DEBUG_IFRAME(dprintf("draw_frameiclass: FRAME_BUTTON\n"));
177 fid->fid_HOffset = 1;
178 fid->fid_VOffset = 1;
179 break;
181 case FRAME_RIDGE:
182 fid->fid_HOffset = 2;
183 fid->fid_VOffset = 2;
184 break;
186 case FRAME_ICONDROPBOX:
187 fid->fid_HOffset = 3;
188 fid->fid_VOffset = 3;
189 break;
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;
202 break;
204 } /* switch */
206 } /* while */
208 return(retval);
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[] =
226 1, /* detailPen */
227 0, /* blockPen */
228 1, /* textPen */
229 2, /* shinePen */
230 1, /* shadowPen */
231 3, /* hiFillPen */
232 1, /* hifilltextPen */
233 0, /* backgroundPen */
234 2 /* hilighttextPen */
236 ULONG retval;
238 DEBUG_IFRAME(dprintf("draw_frameiclass: width %ld height %ld\n",width,height));
240 /* we will check the rastport present */
241 if(msg->imp_RPort)
243 UWORD *pens = default_pens;
244 UWORD left, top;
245 UWORD shine, shadow;
246 BOOL selected;
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 */
253 if (msg->imp_DrInfo)
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];
264 else
266 shine = pens[SHINEPEN];
267 } /* if */
269 else
271 shine = pens[SHINEPEN];
272 } /* if */
274 shadow = pens[SHADOWPEN];
276 switch(msg->imp_State)
278 case IDS_SELECTED:
279 case IDS_INACTIVESELECTED:
280 selected = TRUE;
281 break;
283 default:
284 selected = FALSE;
285 break;
286 } /* switch */
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 ------|------|-------
300 0 | 0 | 0
301 ------|------|-------
302 0 | 1 | 1
303 ------|------|-------
304 1 | 0 | 1
305 ------|------|-------
306 1 | 1 | 0
307 ------|------|-------
310 if ( (fid->fid_Recessed ^ selected) != 0 )
312 /* swap pens */
313 UWORD tmp;
315 tmp = shine;
316 shine = shadow;
317 shadow = tmp;
318 } /* if */
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)
327 case FRAME_DEFAULT:
328 DrawFrame(cl, rp, shine, shadow, left, top, width, height, FALSE);
329 break;
331 case FRAME_BUTTON:
332 DrawFrame(cl, rp, shine, shadow, left, top, width, height, TRUE);
333 break;
335 case FRAME_RIDGE:
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,
343 TRUE);
344 break;
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);
357 break;
360 } /* switch */
362 if(!fid->fid_EdgesOnly)
364 if(selected)
366 SetABPenDrMd(rp, pens[FILLPEN], pens[BACKGROUNDPEN], JAM1);
368 else
370 SetABPenDrMd(rp, pens[BACKGROUNDPEN], pens[BACKGROUNDPEN], JAM1);
371 } /* if */
373 RectFill(rp,
374 left + fid->fid_HOffset,
375 top + fid->fid_VOffset,
376 left + width - fid->fid_HOffset - 1,
377 top + height - fid->fid_VOffset - 1);
379 } /* if */
381 switch(msg->imp_State)
383 case IDS_DISABLED:
384 case IDS_INACTIVEDISABLED:
385 case IDS_SELECTEDDISABLED:
386 RenderDisabledPattern(rp,
387 msg->imp_DrInfo,
388 left,
389 top,
390 left + width - 1,
391 top + height - 1,
392 IntuitionBase);
393 break;
396 SetABPenDrMd(rp, oldapen, oldbpen, olddrmd);
398 retval = 1UL;
400 else
402 /* return failure */
403 retval = 0UL;
404 } /* if */
406 return retval;
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;
437 else
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;
443 } /* if */
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));
451 return (IPTR)1;
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);
465 if (o)
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);
480 return (IPTR)o;
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);