2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
6 Common routines for Gadgets.
9 /**********************************************************************************************/
11 #include <exec/types.h>
12 #include <proto/intuition.h>
13 #include <intuition/intuition.h>
14 #include <intuition/cghooks.h>
15 #include <intuition/classes.h>
16 #include <intuition/classusr.h>
17 #include <intuition/imageclass.h>
18 #include <proto/graphics.h>
19 #include <proto/layers.h>
20 #include <graphics/rastport.h>
21 #include <graphics/text.h>
22 #include <graphics/gfxmacros.h>
26 #include "intuition_intern.h"
29 #define DEBUG_RENDERDISABLEPATTERN(x) ;
30 #define DEBUG_ERASERELGADGETAREA(x) ;
31 #define DEBUG_SETUPGINFO(x) ;
34 /**********************************************************************************************/
36 #define EG(o) ((struct ExtGadget *)o)
37 #define IM(o) ((struct Image *)o)
39 /**********************************************************************************************/
41 /* print the label of a gadget object */
43 void printgadgetlabel(Class
*cl
, Object
*o
, struct gpRender
*msg
,
44 struct IntuitionBase
*IntuitionBase
)
46 struct RastPort
*rp
= msg
->gpr_RPort
;
47 struct IBox container
;
48 UWORD
*pens
= msg
->gpr_GInfo
->gi_DrInfo
->dri_Pens
;
51 if (!(EG(o
)->GadgetText
)) return;
53 GetGadgetIBox((struct Gadget
*)o
, msg
->gpr_GInfo
, &container
);
54 //dprintf("printgadgetlabel: o %p ibox %d %d %d %d\n",o,container.Left,container.Top,container.Width,container.Height);
56 SetFont(rp
, msg
->gpr_GInfo
->gi_DrInfo
->dri_Font
);
58 switch (EG(o
)->Flags
& GFLG_LABELMASK
)
61 /* ITexts must not to be centered! */
63 /* frbuttonclass sets fg/bg/drawmode attributes */
64 int_PrintIText(rp
, EG(o
)->GadgetText
, container
.Left
,container
.Top
, TRUE
, IntuitionBase
);
67 case GFLG_LABELSTRING
:
68 len
= strlen ((STRPTR
) EG(o
)->GadgetText
);
75 x
= container
.Left
+ (container
.Width
/ 2);
77 (STRPTR
)EG(o
)->GadgetText
, len
, IntuitionBase
) / 2;
78 y
= container
.Top
+ (container
.Height
/ 2) +
79 rp
->Font
->tf_Baseline
;
80 y
-= rp
->Font
->tf_YSize
/ 2;
81 SetAPen (rp
, pens
[TEXTPEN
]);
84 (STRPTR
) EG(o
)->GadgetText
, len
,
90 /* center image position */
92 x
= container
.Left
+ ((container
.Width
/ 2) -
93 (IM(EG(o
)->GadgetText
)->Width
/ 2)) - IM(EG(o
)->GadgetText
)->LeftEdge
;
95 y
= container
.Top
+ ((container
.Height
/ 2) -
96 (IM(EG(o
)->GadgetText
)->Height
/ 2)) - IM(EG(o
)->GadgetText
)->TopEdge
;
97 //dprintf("printgadgetlabel: o %p w %d h %d x %d y %d l %d t %d\n", o,IM(EG(o)->GadgetText)->Width,IM(EG(o)->GadgetText)->Height,x,y,IM(EG(o)->GadgetText)->LeftEdge,IM(EG(o)->GadgetText)->TopEdge);
99 DrawImageState(rp
, IM(EG(o
)->GadgetText
),
101 ((EG(o
)->Flags
& GFLG_SELECTED
) ? IDS_SELECTED
: IDS_NORMAL
),
102 msg
->gpr_GInfo
->gi_DrInfo
);
105 } /* switch (EG(o)->Flags & GFLG_LABELMASK) */
109 /**********************************************************************************************/
111 /* Calculate the size of the Bounding Box of the gadget */
112 void CalcBBox (struct Window
* window
, struct Requester
* req
, struct Gadget
* gadget
,
116 GetDomGadgetIBox(gadget
, window
->WScreen
, window
, req
, (struct IBox
*)bbox
);
120 /**********************************************************************************************/
122 /* Figure out the size of the gadget rectangle, taking relative
123 * positioning into account.
125 VOID
GetGadgetIBox(struct Gadget
*g
, struct GadgetInfo
*gi
, struct IBox
*ibox
)
127 ibox
->Left
= g
->LeftEdge
;
128 ibox
->Top
= g
->TopEdge
;
129 ibox
->Width
= g
->Width
;
130 ibox
->Height
= g
->Height
;
134 if (g
->Flags
& GFLG_RELRIGHT
)
135 ibox
->Left
+= gi
->gi_Domain
.Width
- 1;
137 if (g
->Flags
& GFLG_RELBOTTOM
)
138 ibox
->Top
+= gi
->gi_Domain
.Height
- 1;
140 if (g
->Flags
& GFLG_RELWIDTH
)
141 ibox
->Width
+= gi
->gi_Domain
.Width
;
143 if (g
->Flags
& GFLG_RELHEIGHT
)
144 ibox
->Height
+= gi
->gi_Domain
.Height
;
147 DEBUG_GETGADGETIBOX(dprintf("GetGadgetIBox: Gadget 0x%lx GInfo 0x%lx Flags 0x%lx Left %ld Top %ld Width %ld Height %ld\n",
148 g
, gi
, g
->Flags
, ibox
->Left
, ibox
->Top
, ibox
->Width
, ibox
->Height
));
151 /**********************************************************************************************/
153 ULONG
LabelWidth (struct RastPort
* rp
, STRPTR label
, ULONG len
,
154 struct IntuitionBase
* IntuitionBase
)
156 ULONG totalwidth
, uscorewidth
;
158 totalwidth
= TextLength (rp
, label
, len
);
159 uscorewidth
= TextLength (rp
, "_", 1);
161 while (len
&& *label
)
164 totalwidth
-= uscorewidth
;
173 /**********************************************************************************************/
175 void RenderLabel (struct RastPort
* rp
, STRPTR label
, ULONG len
,
176 struct IntuitionBase
* IntuitionBase
)
185 while (label
[renderlen
] && label
[renderlen
] != '_')
188 Text (rp
, label
, renderlen
);
192 if (*label
) /* '_' ? */
198 uscorewidth
= TextLength (rp
, label
, 1);
204 Draw (rp
, cx
+uscorewidth
-1, cy
+2);
210 /**********************************************************************************************/
212 VOID
drawrect(struct RastPort
*rp
, WORD x1
, WORD y1
, WORD x2
, WORD y2
,
213 struct IntuitionBase
*IntuitionBase
)
217 /* We RectFill() because it is generally faster than Draw()
218 (Draw() uses Set/GetPixel() while RectFill() can do higherlevel
219 clipping. Also it is MUCH faster in the x11gfx hidd.
222 RectFill(rp
, x1
, y1
, x2
- 1, y1
); /* Top */
223 RectFill(rp
, x2
, y1
, x2
, y2
- 1); /* Right */
224 RectFill(rp
, x1
+ 1, y2
, x2
, y2
); /* Bottom */
225 RectFill(rp
, x1
, y1
+ 1, x1
, y2
); /* Left */
230 /**********************************************************************************************/
232 void GetGadgetDomain(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
233 struct Requester
*req
, struct IBox
*box
)
235 switch (gad
->GadgetType
& (GTYP_GADGETTYPE
& ~GTYP_SYSGADGET
))
240 box
->Width
= scr
->Width
;
241 box
->Height
= scr
->Height
;
246 /* stegerg: this means gadget is in window border! */
250 box
->Width
= win
->Width
;
251 box
->Height
= win
->Height
;
256 box
->Left
= req
->LeftEdge
+ win
->BorderLeft
;
257 box
->Top
= req
->TopEdge
+ win
->BorderTop
;
258 box
->Width
= req
->Width
;
259 box
->Height
= req
->Height
;
264 if (win
->Flags
& WFLG_GIMMEZEROZERO
)
266 /* stegerg: domain.left and domain.top must not be added
267 to gadget position when it is rendered, because gadgets
268 in the innerlayer of a gzz gadget are already shifted
269 thanks to the innerlayer. */
271 box
->Left
= win
->BorderLeft
;
272 box
->Top
= win
->BorderTop
;
274 box
->Width
= win
->Width
- win
->BorderLeft
- win
->BorderRight
;
275 box
->Height
= win
->Height
- win
->BorderTop
- win
->BorderBottom
;
282 box
->Width
= win
->Width
;
283 box
->Height
= win
->Height
;
289 } /* switch (gadgettype) */
292 /**********************************************************************************************/
294 WORD
GetGadgetLeft(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
, struct Requester
*req
)
298 GetGadgetDomain(gad
, scr
, win
, req
, &box
);
300 return gad
->LeftEdge
+ ADDREL(gad
, GFLG_RELRIGHT
, (&box
), Width
- 1);
303 /**********************************************************************************************/
305 WORD
GetGadgetTop(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
, struct Requester
*req
)
309 GetGadgetDomain(gad
, scr
, win
, req
, &box
);
311 return gad
->TopEdge
+ ADDREL(gad
, GFLG_RELBOTTOM
, (&box
), Height
- 1);
314 /**********************************************************************************************/
316 WORD
GetGadgetWidth(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
, struct Requester
*req
)
320 GetGadgetDomain(gad
, scr
, win
, req
, &box
);
322 return gad
->Width
+ ADDREL(gad
, GFLG_RELWIDTH
, (&box
), Width
);
325 /**********************************************************************************************/
327 WORD
GetGadgetHeight(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
, struct Requester
*req
)
331 GetGadgetDomain(gad
, scr
, win
, req
, &box
);
333 return gad
->Height
+ ADDREL(gad
, GFLG_RELHEIGHT
, (&box
), Height
);
336 /**********************************************************************************************/
338 /* gadget box in screen coords */
339 void GetScrGadgetIBox(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
340 struct Requester
*req
, struct IBox
*box
)
342 GetWinGadgetIBox(gad
, scr
, win
, req
, box
);
346 box
->Left
+= win
->LeftEdge
;
347 box
->Top
+= win
->TopEdge
;
351 /**********************************************************************************************/
353 /* gadget box relative to upper left window edge */
354 void GetWinGadgetIBox(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
355 struct Requester
*req
, struct IBox
*box
)
359 GetGadgetDomain(gad
, scr
, win
, req
, &domain
);
361 box
->Left
= gad
->LeftEdge
;
362 box
->Top
= gad
->TopEdge
;
363 box
->Width
= gad
->Width
;
364 box
->Height
= gad
->Height
;
366 if (gad
->Flags
& GFLG_RELRIGHT
)
367 box
->Left
+= domain
.Width
- 1;
369 if (gad
->Flags
& GFLG_RELBOTTOM
)
370 box
->Top
+= domain
.Height
- 1;
372 if (gad
->Flags
& GFLG_RELWIDTH
)
373 box
->Width
+= domain
.Width
;
375 if (gad
->Flags
& GFLG_RELHEIGHT
)
376 box
->Height
+= domain
.Height
;
378 box
->Left
+= domain
.Left
;
379 box
->Top
+= domain
.Top
;
382 /**********************************************************************************************/
384 /* gadget box in domain coords */
385 void GetDomGadgetIBox(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
386 struct Requester
*req
, struct IBox
*box
)
390 GetWinGadgetIBox(gad
, scr
, win
, req
, box
);
391 GetGadgetDomain(gad
, scr
, win
, req
, &domain
);
393 box
->Left
-= domain
.Left
;
394 box
->Top
-= domain
.Top
;
397 /**********************************************************************************************/
399 /* gadget bounds in screen coords */
400 void GetScrGadgetBounds(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
401 struct Requester
*req
, struct IBox
*box
)
405 if (gad
->Flags
& GFLG_EXTENDED
)
407 if (EG(gad
)->MoreFlags
& GMORE_BOUNDS
)
409 GetGadgetDomain(gad
, scr
, win
, req
, &domain
);
411 box
->Left
= domain
.Left
+
412 EG(gad
)->BoundsLeftEdge
+ ADDREL(gad
, GFLG_RELRIGHT
, (&domain
), Width
- 1) +
413 (win
? win
->LeftEdge
: 0);
415 box
->Top
= domain
.Top
+
416 EG(gad
)->BoundsTopEdge
+ ADDREL(gad
, GFLG_RELBOTTOM
, (&domain
), Height
- 1) +
417 (win
? win
->TopEdge
: 0);
419 box
->Width
= EG(gad
)->BoundsWidth
+ ADDREL(gad
, GFLG_RELWIDTH
, (&domain
), Width
);
421 box
->Height
= EG(gad
)->BoundsHeight
+ ADDREL(gad
, GFLG_RELHEIGHT
, (&domain
), Height
);
425 } /* if (gad->MoreFlags & GMORE_BOUNDS) */
427 } /* if (gad->Flags & GFLG_EXTENDED) */
429 /* if gadget does not have bounds return box */
431 GetScrGadgetIBox(gad
, scr
, win
, req
, box
);
434 /**********************************************************************************************/
436 /* gadget bounds relative to upper left window edge */
437 void GetWinGadgetBounds(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
438 struct Requester
*req
, struct IBox
*box
)
440 GetScrGadgetBounds(gad
, scr
, win
, req
, box
);
444 box
->Left
-= win
->LeftEdge
;
445 box
->Top
-= win
->TopEdge
;
449 /**********************************************************************************************/
451 /* gadget bounds in domain coords */
452 void GetDomGadgetBounds(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
453 struct Requester
*req
, struct IBox
*box
)
457 GetWinGadgetBounds(gad
, scr
, win
, req
, box
);
458 GetGadgetDomain(gad
, scr
, win
, req
, &domain
);
460 box
->Left
-= domain
.Left
;
461 box
->Top
-= domain
.Top
;
464 /**********************************************************************************************/
466 void EraseRelGadgetArea(struct Window
*win
, struct Rectangle
*clipto
,
467 BOOL onlydamagelist
, struct IntuitionBase
*IntuitionBase
)
470 struct Region
*old_clipregion
= NULL
; /* shut up the compiler */
471 struct RastPort
*rp
, *rp2
;
474 WORD old_scroll_x
= 0, old_scroll_y
= 0, i
, num_loops
;
476 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: win 0x%lx onlydamage %d\n",
477 win
, onlydamagelist
));
480 rp2
= win
->BorderRPort
;
482 if (rp
->Layer
== rp2
->Layer
)
489 clipto
= NULL
; /* Don't do any border clipping for GZZ windows */
492 for(i
= 0; i
< num_loops
; i
++, rp
= rp2
)
500 old_scroll_x
= lay
->Scroll_X
;
501 old_scroll_y
= lay
->Scroll_Y
;
502 old_clipregion
= InstallClipRegion(lay
, NULL
);
505 gad
= win
->FirstGadget
;
508 BOOL checkgad
= FALSE
;
510 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: Gadget 0x%lx Flags 0x%lx Type 0x%lx Activation 0x%lx %d,%d %d×%d\n",
511 gad
, gad
->Flags
, gad
->GadgetType
, gad
->Activation
,
512 gad
->LeftEdge
, gad
->TopEdge
, gad
->Width
, gad
->Height
));
522 if (!IS_BORDER_GADGET(gad
)) checkgad
= TRUE
;
526 if (IS_BORDER_GADGET(gad
)) checkgad
= TRUE
;
532 if (gad
->Flags
& (GFLG_RELRIGHT
| GFLG_RELBOTTOM
|
533 GFLG_RELWIDTH
| GFLG_RELHEIGHT
| GFLG_RELSPECIAL
))
535 struct Rectangle rect
;
537 GetDomGadgetBounds(gad
, win
->WScreen
, win
, NULL
, &box
);
539 if ((box
.Width
> 0) && (box
.Height
> 0))
541 rect
.MinX
= box
.Left
;
543 rect
.MaxX
= box
.Left
+ box
.Width
- 1;
544 rect
.MaxY
= box
.Top
+ box
.Height
- 1;
546 if (!(lay
->Flags
& LAYERSUPER
))
548 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: gad 0x%lx add (%d,%d)-(%d,%d)\n", gad
, rect
.MinX
, rect
.MinY
, rect
.MaxX
, rect
.MaxY
));
550 OrRectRegion(lay
->DamageList
, &rect
);
551 lay
->Flags
|= LAYERREFRESH
;
556 if (!clipto
|| AndRectRect(&rect
, clipto
, &rect
))
558 EraseRect(rp
, rect
.MinX
, rect
.MinY
, rect
.MaxX
, rect
.MaxY
);
566 } /* if (checkgad) */
568 gad
= gad
->NextGadget
;
574 InstallClipRegion(lay
, old_clipregion
);
575 lay
->Scroll_X
= old_scroll_x
;
576 lay
->Scroll_Y
= old_scroll_y
;
581 } /* for(i = 0; i < num_loops; i++, rp = rp2) */
585 /**********************************************************************************************/
587 void RenderDisabledPattern(struct RastPort
*rp
, struct DrawInfo
*dri
, WORD x1
, WORD y1
,
588 WORD x2
, WORD y2
, struct IntuitionBase
*IntuitionBase
)
591 UWORD pattern
[] = { 0x8888, 0x2222 };
593 DEBUG_RENDERDISABLEPATTERN(dprintf("RenderDisabledPattern: rp 0x%lx dri 0x%lx x1 %ld y1 %ld x2 %ld y2 %ld\n",
594 rp
,dri
,x1
,y1
,x2
,y2
));
598 pen
= dri
->dri_Pens
[SHADOWPEN
];
607 SetAfPt( rp
, pattern
, 1);
609 /* render disable pattern */
610 RectFill(rp
, x1
, y1
, x2
, y2
);
612 SetAfPt (rp
, NULL
, 0);
616 /**********************************************************************************************/
618 ULONG
GetGadgetState(struct Window
*window
, struct Gadget
*gadget
)
620 ULONG state
= IDS_NORMAL
;
622 if (IS_BORDER_GADGET(gadget
)
623 && !(window
->Flags
& (WFLG_WINDOWACTIVE
| WFLG_TOOLBOX
)))
625 if (gadget
->Flags
& GFLG_DISABLED
)
627 if (gadget
->Flags
& GFLG_SELECTED
)
629 state
= IDS_INACTIVEDISABLED
; /* Hmm ... there's no INACTIVEDISABLEDSELECTED */
633 state
= IDS_INACTIVEDISABLED
;
638 if (gadget
->Flags
& GFLG_SELECTED
)
640 state
= IDS_INACTIVESELECTED
;
644 state
= IDS_INACTIVENORMAL
;
650 if (gadget
->Flags
& GFLG_DISABLED
)
652 if (gadget
->Flags
& GFLG_SELECTED
)
654 state
= IDS_SELECTEDDISABLED
;
658 state
= IDS_DISABLED
;
663 if (gadget
->Flags
& GFLG_SELECTED
)
665 state
= IDS_SELECTED
;
677 /**********************************************************************************************/
679 void SetupGInfo(struct GadgetInfo
*gi
, struct Window
*win
, struct Requester
*req
,
680 struct Gadget
*gad
, struct IntuitionBase
*IntuitionBase
)
682 struct Window
*tw
= 0;
684 DEBUG_SETUPGINFO(dprintf("SetupGInfo: gi %p win %p req %p gadget %p (Type 0x%x)\n",
685 gi
, win
, req
, gad
, gad
->GadgetType
));
687 memset(gi
, 0, sizeof(*gi
));
700 if (IS_SCREEN_GADGET(gad
))
702 gi
->gi_Window
= NULL
;
703 gi
->gi_Screen
= (struct Screen
*)tw
;
704 gi
->gi_Pens
.DetailPen
= 0;
705 gi
->gi_Pens
.BlockPen
= 0;
710 gi
->gi_Screen
= tw
->WScreen
;
711 gi
->gi_Pens
.DetailPen
= tw
->DetailPen
;
712 gi
->gi_Pens
.BlockPen
= tw
->BlockPen
;
714 gi
->gi_Requester
= req
;
715 gi
->gi_DrInfo
= GetScreenDrawInfo (gi
->gi_Screen
);
717 SET_GI_RPORT(gi
, tw
, req
, gad
);
719 gi
->gi_Layer
= gi
->gi_RastPort
? gi
->gi_RastPort
->Layer
: NULL
;
721 GetGadgetDomain(gad
, gi
->gi_Screen
, gi
->gi_Window
, req
, &gi
->gi_Domain
);
724 DEBUG_SETUPGINFO(dprintf("SetGInfo: Win %p Req %p RP %p Layer %p\n",
725 gi
->gi_Window
, gi
->gi_Requester
, gi
->gi_RastPort
, gi
->gi_Layer
));
728 /**********************************************************************************************/