2 Copyright © 1995-2012, 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 GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
47 struct RastPort
*rp
= msg
->gpr_RPort
;
48 struct IBox container
;
49 UWORD
*pens
= msg
->gpr_GInfo
->gi_DrInfo
->dri_Pens
;
52 if (!(EG(o
)->GadgetText
)) return;
54 GetGadgetIBox((struct Gadget
*)o
, msg
->gpr_GInfo
, &container
);
55 //dprintf("printgadgetlabel: o %p ibox %d %d %d %d\n",o,container.Left,container.Top,container.Width,container.Height);
57 SetFont(rp
, msg
->gpr_GInfo
->gi_DrInfo
->dri_Font
);
59 switch (EG(o
)->Flags
& GFLG_LABELMASK
)
62 /* ITexts must not to be centered! */
64 /* frbuttonclass sets fg/bg/drawmode attributes */
65 int_PrintIText(rp
, EG(o
)->GadgetText
, container
.Left
,container
.Top
, TRUE
, IntuitionBase
);
68 case GFLG_LABELSTRING
:
69 len
= strlen ((STRPTR
) EG(o
)->GadgetText
);
76 x
= container
.Left
+ (container
.Width
/ 2);
78 (STRPTR
)EG(o
)->GadgetText
, len
, IntuitionBase
) / 2;
79 y
= container
.Top
+ (container
.Height
/ 2) +
80 rp
->Font
->tf_Baseline
;
81 y
-= rp
->Font
->tf_YSize
/ 2;
82 SetAPen (rp
, pens
[TEXTPEN
]);
85 (STRPTR
) EG(o
)->GadgetText
, len
,
91 /* center image position */
93 x
= container
.Left
+ ((container
.Width
/ 2) -
94 (IM(EG(o
)->GadgetText
)->Width
/ 2)) - IM(EG(o
)->GadgetText
)->LeftEdge
;
96 y
= container
.Top
+ ((container
.Height
/ 2) -
97 (IM(EG(o
)->GadgetText
)->Height
/ 2)) - IM(EG(o
)->GadgetText
)->TopEdge
;
98 //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);
100 DrawImageState(rp
, IM(EG(o
)->GadgetText
),
102 ((EG(o
)->Flags
& GFLG_SELECTED
) ? IDS_SELECTED
: IDS_NORMAL
),
103 msg
->gpr_GInfo
->gi_DrInfo
);
106 } /* switch (EG(o)->Flags & GFLG_LABELMASK) */
110 /**********************************************************************************************/
112 /* Calculate the size of the Bounding Box of the gadget */
113 void CalcBBox (struct Window
* window
, struct Requester
* req
, struct Gadget
* gadget
,
117 GetDomGadgetIBox(gadget
, window
->WScreen
, window
, req
, (struct IBox
*)bbox
);
121 /**********************************************************************************************/
123 /* Figure out the size/position of the gadget rectangle, taking relative
124 * positioning into account.
126 VOID
GetGadgetIBox(struct Gadget
*g
, struct GadgetInfo
*gi
, struct IBox
*ibox
)
128 ibox
->Left
= g
->LeftEdge
;
129 ibox
->Top
= g
->TopEdge
;
130 ibox
->Width
= g
->Width
;
131 ibox
->Height
= g
->Height
;
135 if (g
->Flags
& GFLG_RELRIGHT
)
136 ibox
->Left
+= gi
->gi_Domain
.Width
- 1;
138 if (g
->Flags
& GFLG_RELBOTTOM
)
139 ibox
->Top
+= gi
->gi_Domain
.Height
- 1;
141 if (g
->Flags
& GFLG_RELWIDTH
)
142 ibox
->Width
+= gi
->gi_Domain
.Width
;
144 if (g
->Flags
& GFLG_RELHEIGHT
)
145 ibox
->Height
+= gi
->gi_Domain
.Height
;
148 DEBUG_GETGADGETIBOX(dprintf("GetGadgetIBox: Gadget 0x%lx GInfo 0x%lx Flags 0x%lx Left %ld Top %ld Width %ld Height %ld\n",
149 g
, gi
, g
->Flags
, ibox
->Left
, ibox
->Top
, ibox
->Width
, ibox
->Height
));
152 /**********************************************************************************************/
154 ULONG
LabelWidth (struct RastPort
* rp
, STRPTR label
, ULONG len
,
155 struct IntuitionBase
* IntuitionBase
)
157 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
158 ULONG totalwidth
, uscorewidth
;
160 totalwidth
= TextLength (rp
, label
, len
);
161 uscorewidth
= TextLength (rp
, "_", 1);
163 while (len
&& *label
)
166 totalwidth
-= uscorewidth
;
175 /**********************************************************************************************/
177 void RenderLabel (struct RastPort
* rp
, STRPTR label
, ULONG len
,
178 struct IntuitionBase
* IntuitionBase
)
180 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
188 while (label
[renderlen
] && label
[renderlen
] != '_')
191 Text (rp
, label
, renderlen
);
195 if (*label
) /* '_' ? */
201 uscorewidth
= TextLength (rp
, label
, 1);
207 Draw (rp
, cx
+uscorewidth
-1, cy
+2);
213 /**********************************************************************************************/
215 VOID
drawrect(struct RastPort
*rp
, WORD x1
, WORD y1
, WORD x2
, WORD y2
,
216 struct IntuitionBase
*IntuitionBase
)
218 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
220 /* We RectFill() because it is generally faster than Draw()
221 (Draw() uses Set/GetPixel() while RectFill() can do higherlevel
222 clipping. Also it is MUCH faster in the x11gfx hidd.
225 RectFill(rp
, x1
, y1
, x2
- 1, y1
); /* Top */
226 RectFill(rp
, x2
, y1
, x2
, y2
- 1); /* Right */
227 RectFill(rp
, x1
+ 1, y2
, x2
, y2
); /* Bottom */
228 RectFill(rp
, x1
, y1
+ 1, x1
, y2
); /* Left */
233 /**********************************************************************************************/
235 void GetGadgetDomain(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
236 struct Requester
*req
, struct IBox
*box
)
238 switch (gad
->GadgetType
& (GTYP_GADGETTYPE
& ~GTYP_SYSGADGET
))
243 box
->Width
= scr
->Width
;
244 box
->Height
= scr
->Height
;
249 /* stegerg: this means gadget is in window border! */
253 box
->Width
= win
->Width
;
254 box
->Height
= win
->Height
;
259 box
->Left
= req
->LeftEdge
+ win
->BorderLeft
;
260 box
->Top
= req
->TopEdge
+ win
->BorderTop
;
261 box
->Width
= req
->Width
;
262 box
->Height
= req
->Height
;
267 if (win
->Flags
& WFLG_GIMMEZEROZERO
)
269 /* stegerg: domain.left and domain.top must not be added
270 to gadget position when it is rendered, because gadgets
271 in the innerlayer of a gzz gadget are already shifted
272 thanks to the innerlayer. */
274 box
->Left
= win
->BorderLeft
;
275 box
->Top
= win
->BorderTop
;
277 box
->Width
= win
->Width
- win
->BorderLeft
- win
->BorderRight
;
278 box
->Height
= win
->Height
- win
->BorderTop
- win
->BorderBottom
;
285 box
->Width
= win
->Width
;
286 box
->Height
= win
->Height
;
292 } /* switch (gadgettype) */
295 /**********************************************************************************************/
297 WORD
GetGadgetLeft(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
, struct Requester
*req
)
301 GetGadgetDomain(gad
, scr
, win
, req
, &box
);
303 return gad
->LeftEdge
+ ADDREL(gad
, GFLG_RELRIGHT
, (&box
), Width
- 1);
306 /**********************************************************************************************/
308 WORD
GetGadgetTop(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
, struct Requester
*req
)
312 GetGadgetDomain(gad
, scr
, win
, req
, &box
);
314 return gad
->TopEdge
+ ADDREL(gad
, GFLG_RELBOTTOM
, (&box
), Height
- 1);
317 /**********************************************************************************************/
319 WORD
GetGadgetWidth(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
, struct Requester
*req
)
323 GetGadgetDomain(gad
, scr
, win
, req
, &box
);
325 return gad
->Width
+ ADDREL(gad
, GFLG_RELWIDTH
, (&box
), Width
);
328 /**********************************************************************************************/
330 WORD
GetGadgetHeight(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
, struct Requester
*req
)
334 GetGadgetDomain(gad
, scr
, win
, req
, &box
);
336 return gad
->Height
+ ADDREL(gad
, GFLG_RELHEIGHT
, (&box
), Height
);
339 /**********************************************************************************************/
341 /* gadget box in screen coords */
342 void GetScrGadgetIBox(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
343 struct Requester
*req
, struct IBox
*box
)
345 GetWinGadgetIBox(gad
, scr
, win
, req
, box
);
349 box
->Left
+= win
->LeftEdge
;
350 box
->Top
+= win
->TopEdge
;
354 /**********************************************************************************************/
356 /* gadget box relative to upper left window edge */
357 void GetWinGadgetIBox(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
358 struct Requester
*req
, struct IBox
*box
)
362 GetGadgetDomain(gad
, scr
, win
, req
, &domain
);
364 box
->Left
= gad
->LeftEdge
;
365 box
->Top
= gad
->TopEdge
;
366 box
->Width
= gad
->Width
;
367 box
->Height
= gad
->Height
;
369 if (gad
->Flags
& GFLG_RELRIGHT
)
370 box
->Left
+= domain
.Width
- 1;
372 if (gad
->Flags
& GFLG_RELBOTTOM
)
373 box
->Top
+= domain
.Height
- 1;
375 if (gad
->Flags
& GFLG_RELWIDTH
)
376 box
->Width
+= domain
.Width
;
378 if (gad
->Flags
& GFLG_RELHEIGHT
)
379 box
->Height
+= domain
.Height
;
381 box
->Left
+= domain
.Left
;
382 box
->Top
+= domain
.Top
;
385 /**********************************************************************************************/
387 /* gadget box in domain coords */
388 void GetDomGadgetIBox(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
389 struct Requester
*req
, struct IBox
*box
)
393 GetWinGadgetIBox(gad
, scr
, win
, req
, box
);
394 GetGadgetDomain(gad
, scr
, win
, req
, &domain
);
396 box
->Left
-= domain
.Left
;
397 box
->Top
-= domain
.Top
;
400 /**********************************************************************************************/
402 /* gadget bounds in screen coords */
403 void GetScrGadgetBounds(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
404 struct Requester
*req
, struct IBox
*box
)
408 if (gad
->Flags
& GFLG_EXTENDED
)
410 if (EG(gad
)->MoreFlags
& GMORE_BOUNDS
)
412 GetGadgetDomain(gad
, scr
, win
, req
, &domain
);
414 box
->Left
= domain
.Left
+
415 EG(gad
)->BoundsLeftEdge
+ ADDREL(gad
, GFLG_RELRIGHT
, (&domain
), Width
- 1) +
416 (win
? win
->LeftEdge
: 0);
418 box
->Top
= domain
.Top
+
419 EG(gad
)->BoundsTopEdge
+ ADDREL(gad
, GFLG_RELBOTTOM
, (&domain
), Height
- 1) +
420 (win
? win
->TopEdge
: 0);
422 box
->Width
= EG(gad
)->BoundsWidth
+ ADDREL(gad
, GFLG_RELWIDTH
, (&domain
), Width
);
424 box
->Height
= EG(gad
)->BoundsHeight
+ ADDREL(gad
, GFLG_RELHEIGHT
, (&domain
), Height
);
428 } /* if (gad->MoreFlags & GMORE_BOUNDS) */
430 } /* if (gad->Flags & GFLG_EXTENDED) */
432 /* if gadget does not have bounds return box */
434 GetScrGadgetIBox(gad
, scr
, win
, req
, box
);
437 /**********************************************************************************************/
439 /* gadget bounds relative to upper left window edge */
440 void GetWinGadgetBounds(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
441 struct Requester
*req
, struct IBox
*box
)
443 GetScrGadgetBounds(gad
, scr
, win
, req
, box
);
447 box
->Left
-= win
->LeftEdge
;
448 box
->Top
-= win
->TopEdge
;
452 /**********************************************************************************************/
454 /* gadget bounds in domain coords */
455 void GetDomGadgetBounds(struct Gadget
*gad
, struct Screen
*scr
, struct Window
*win
,
456 struct Requester
*req
, struct IBox
*box
)
460 GetWinGadgetBounds(gad
, scr
, win
, req
, box
);
461 GetGadgetDomain(gad
, scr
, win
, req
, &domain
);
463 box
->Left
-= domain
.Left
;
464 box
->Top
-= domain
.Top
;
467 /**********************************************************************************************/
469 void EraseRelGadgetArea(struct Window
*win
, struct Rectangle
*clipto
,
470 BOOL onlydamagelist
, struct IntuitionBase
*IntuitionBase
)
472 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
473 struct LayersBase
*LayersBase
= GetPrivIBase(IntuitionBase
)->LayersBase
;
475 struct Region
*old_clipregion
= NULL
; /* shut up the compiler */
476 struct RastPort
*rp
, *rp2
;
479 WORD old_scroll_x
= 0, old_scroll_y
= 0, i
, num_loops
;
481 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: win 0x%lx onlydamage %d\n",
482 win
, onlydamagelist
));
485 rp2
= win
->BorderRPort
;
487 if (rp
->Layer
== rp2
->Layer
)
494 clipto
= NULL
; /* Don't do any border clipping for GZZ windows */
497 for(i
= 0; i
< num_loops
; i
++, rp
= rp2
)
505 old_scroll_x
= lay
->Scroll_X
;
506 old_scroll_y
= lay
->Scroll_Y
;
507 old_clipregion
= InstallClipRegion(lay
, NULL
);
510 gad
= win
->FirstGadget
;
513 BOOL checkgad
= FALSE
;
515 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: Gadget 0x%lx Flags 0x%lx Type 0x%lx Activation 0x%lx %d,%d %d×%d\n",
516 gad
, gad
->Flags
, gad
->GadgetType
, gad
->Activation
,
517 gad
->LeftEdge
, gad
->TopEdge
, gad
->Width
, gad
->Height
));
527 if (!IS_BORDER_GADGET(gad
)) checkgad
= TRUE
;
531 if (IS_BORDER_GADGET(gad
)) checkgad
= TRUE
;
537 if (gad
->Flags
& (GFLG_RELRIGHT
| GFLG_RELBOTTOM
|
538 GFLG_RELWIDTH
| GFLG_RELHEIGHT
| GFLG_RELSPECIAL
))
540 struct Rectangle rect
;
542 GetDomGadgetBounds(gad
, win
->WScreen
, win
, NULL
, &box
);
544 if ((box
.Width
> 0) && (box
.Height
> 0))
546 rect
.MinX
= box
.Left
;
548 rect
.MaxX
= box
.Left
+ box
.Width
- 1;
549 rect
.MaxY
= box
.Top
+ box
.Height
- 1;
551 if (!(lay
->Flags
& LAYERSUPER
))
553 DEBUG_ERASERELGADGETAREA(dprintf("EraseRelGadgetArea: gad 0x%lx add (%d,%d)-(%d,%d)\n", gad
, rect
.MinX
, rect
.MinY
, rect
.MaxX
, rect
.MaxY
));
555 OrRectRegion(lay
->DamageList
, &rect
);
556 lay
->Flags
|= LAYERREFRESH
;
561 if (!clipto
|| AndRectRect(&rect
, clipto
, &rect
))
563 EraseRect(rp
, rect
.MinX
, rect
.MinY
, rect
.MaxX
, rect
.MaxY
);
571 } /* if (checkgad) */
573 gad
= gad
->NextGadget
;
579 InstallClipRegion(lay
, old_clipregion
);
580 lay
->Scroll_X
= old_scroll_x
;
581 lay
->Scroll_Y
= old_scroll_y
;
586 } /* for(i = 0; i < num_loops; i++, rp = rp2) */
590 /**********************************************************************************************/
592 void RenderDisabledPattern(struct RastPort
*rp
, struct DrawInfo
*dri
, WORD x1
, WORD y1
,
593 WORD x2
, WORD y2
, struct IntuitionBase
*IntuitionBase
)
595 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
597 UWORD pattern
[] = { 0x8888, 0x2222 };
599 DEBUG_RENDERDISABLEPATTERN(dprintf("RenderDisabledPattern: rp 0x%lx dri 0x%lx x1 %ld y1 %ld x2 %ld y2 %ld\n",
600 rp
,dri
,x1
,y1
,x2
,y2
));
604 pen
= dri
->dri_Pens
[SHADOWPEN
];
613 SetAfPt( rp
, pattern
, 1);
615 /* render disable pattern */
616 RectFill(rp
, x1
, y1
, x2
, y2
);
618 SetAfPt (rp
, NULL
, 0);
622 /**********************************************************************************************/
624 ULONG
GetGadgetState(struct Window
*window
, struct Gadget
*gadget
)
626 ULONG state
= IDS_NORMAL
;
628 if (IS_BORDER_GADGET(gadget
)
629 && !(window
->Flags
& (WFLG_WINDOWACTIVE
| WFLG_TOOLBOX
)))
631 if (gadget
->Flags
& GFLG_DISABLED
)
633 if (gadget
->Flags
& GFLG_SELECTED
)
635 state
= IDS_INACTIVEDISABLED
; /* Hmm ... there's no INACTIVEDISABLEDSELECTED */
639 state
= IDS_INACTIVEDISABLED
;
644 if (gadget
->Flags
& GFLG_SELECTED
)
646 state
= IDS_INACTIVESELECTED
;
650 state
= IDS_INACTIVENORMAL
;
656 if (gadget
->Flags
& GFLG_DISABLED
)
658 if (gadget
->Flags
& GFLG_SELECTED
)
660 state
= IDS_SELECTEDDISABLED
;
664 state
= IDS_DISABLED
;
669 if (gadget
->Flags
& GFLG_SELECTED
)
671 state
= IDS_SELECTED
;
683 /**********************************************************************************************/
685 void SetupGInfo(struct GadgetInfo
*gi
, struct Window
*win
, struct Requester
*req
,
686 struct Gadget
*gad
, struct IntuitionBase
*IntuitionBase
)
688 struct Window
*tw
= 0;
690 DEBUG_SETUPGINFO(dprintf("SetupGInfo: gi %p win %p req %p gadget %p (Type 0x%x)\n",
691 gi
, win
, req
, gad
, gad
->GadgetType
));
693 memset(gi
, 0, sizeof(*gi
));
706 if (IS_SCREEN_GADGET(gad
))
708 gi
->gi_Window
= NULL
;
709 gi
->gi_Screen
= (struct Screen
*)tw
;
710 gi
->gi_Pens
.DetailPen
= 0;
711 gi
->gi_Pens
.BlockPen
= 0;
716 gi
->gi_Screen
= tw
->WScreen
;
717 gi
->gi_Pens
.DetailPen
= tw
->DetailPen
;
718 gi
->gi_Pens
.BlockPen
= tw
->BlockPen
;
720 gi
->gi_Requester
= req
;
721 gi
->gi_DrInfo
= GetScreenDrawInfo (gi
->gi_Screen
);
723 SET_GI_RPORT(gi
, tw
, req
, gad
);
725 gi
->gi_Layer
= gi
->gi_RastPort
? gi
->gi_RastPort
->Layer
: NULL
;
727 GetGadgetDomain(gad
, gi
->gi_Screen
, gi
->gi_Window
, req
, &gi
->gi_Domain
);
730 DEBUG_SETUPGINFO(dprintf("SetGInfo: Win %p Req %p RP %p Layer %p\n",
731 gi
->gi_Window
, gi
->gi_Requester
, gi
->gi_RastPort
, gi
->gi_Layer
));
734 /**********************************************************************************************/