2 Copyright 2011-2012, The AROS Development Team.
7 #include <aros/debug.h>
9 #include <clib/alib_protos.h>
11 #include <graphics/rpattr.h>
12 #include <proto/utility.h>
13 #include <proto/intuition.h>
14 #include <proto/graphics.h>
15 #include <proto/exec.h>
18 #include <intuition/cghooks.h>
20 #include "screendecorclass.h"
21 #include "drawfuncs.h"
24 #define SETIMAGE_SCR(id) sd->di->img_##id = CreateNewImageContainerMatchingScreen(data->di->img_##id, truecolor, screen)
26 #define CHILDPADDING 1
30 struct Screen
*Screen
;
31 /* These are original images loaded from disk */
32 struct DecorImages
* di
;
33 struct DecorConfig
* dc
;
37 static void DisposeScreenSkinning(struct scrdecor_data
*data
)
41 static BOOL
InitScreenSkinning(struct scrdecor_data
*data
, struct DecorImages
* di
, struct DecorConfig
* dc
)
49 if (data
->di
->img_sdepth
) return TRUE
;
51 DisposeScreenSkinning(data
);
59 static IPTR
scrdecor_new(Class
*cl
, Object
*obj
, struct opSet
*msg
)
61 struct scrdecor_data
*data
;
64 D(bug("scrdecor_new(tags @ 0x%p)\n", msg
->ops_AttrList
));
66 obj
= (Object
*)DoSuperMethodA(cl
, obj
, (Msg
)msg
);
70 data
= INST_DATA(cl
, obj
);
72 struct DecorConfig
* dc
= (struct DecorConfig
*) GetTagData(SDA_DecorConfig
, (IPTR
) NULL
, msg
->ops_AttrList
);
73 struct DecorImages
* di
= (struct DecorImages
*) GetTagData(SDA_DecorImages
, (IPTR
) NULL
, msg
->ops_AttrList
);
75 D(bug("scrdecor_new: DecorImages @ 0x%p\n", di
));
76 D(bug("scrdecor_new: DecorConfig @ 0x%p\n", dc
));
78 data
->FirstChild
= NULL
;
80 if (!InitScreenSkinning(data
, di
, dc
))
82 CoerceMethod(cl
,obj
,OM_DISPOSE
);
87 barh
= data
->dc
->SBarHeight
;
89 if (data
->di
->img_sbarlogo
) if (data
->di
->img_sbarlogo
->h
> barh
) barh
= data
->di
->img_sbarlogo
->h
;
90 if (data
->di
->img_stitlebar
) if (data
->di
->img_stitlebar
->h
> barh
) barh
= data
->di
->img_stitlebar
->h
;
96 static IPTR
scrdecor_dispose(Class
*cl
, Object
*obj
, struct opSet
*msg
)
98 struct scrdecor_data
*data
= INST_DATA(cl
, obj
);
100 DisposeScreenSkinning(data
);
105 /**************************************************************************************************/
107 static IPTR
scrdecor_get(Class
*cl
, Object
*obj
, struct opGet
*msg
)
109 switch(msg
->opg_AttrID
)
111 case SDA_TrueColorOnly
:
112 *msg
->opg_Storage
= TRUE
;
116 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
121 /**************************************************************************************************/
123 static void scr_findtitlearea(struct Screen
*scr
, LONG
*left
, LONG
*right
)
128 *right
= scr
->Width
- 1;
130 for (g
= scr
->FirstGadget
; g
; g
= g
->NextGadget
)
132 if (!(g
->Flags
& GFLG_RELRIGHT
))
134 if (g
->LeftEdge
+ g
->Width
> *left
) *left
= g
->LeftEdge
+ g
->Width
;
138 if (g
->LeftEdge
+ scr
->Width
- 1 - 1 < *right
) *right
= g
->LeftEdge
+ scr
->Width
- 1 - 1;
143 static IPTR
scrdecor_set(Class
*cl
, Object
*obj
, struct opSet
*msg
)
145 struct scrdecor_data
*data
= INST_DATA(cl
, obj
);
146 struct TagItem
*tags
= msg
->ops_AttrList
;
147 struct TagItem
*tstate
;
151 while ((tag
= NextTagItem(&tstate
)))
158 if (!(data
->FirstChild
))
160 LONG left
, right
= 0;
161 struct GadgetInfo childgadinf
;
162 struct gpLayout childlayoutmsg
;
163 D(bug("[screendecor] SDA_TitleChild: 0x%p\n", tag
->ti_Data
));
165 if ((childgadinf
.gi_Screen
= LockPubScreen(NULL
)) != NULL
)
167 UnlockPubScreen(NULL
, childgadinf
.gi_Screen
);
168 data
->FirstChild
= (Object
*)tag
->ti_Data
;
169 ((struct Gadget
*)(data
->FirstChild
))->SpecialInfo
= childgadinf
.gi_Screen
;
171 childgadinf
.gi_RastPort
= childgadinf
.gi_Screen
->BarLayer
->rp
;
173 if ((childgadinf
.gi_DrInfo
= GetScreenDrawInfo(childgadinf
.gi_Screen
)) != NULL
)
175 childgadinf
.gi_Pens
.DetailPen
= childgadinf
.gi_DrInfo
->dri_Pens
[DETAILPEN
];
176 childgadinf
.gi_Pens
.BlockPen
= childgadinf
.gi_DrInfo
->dri_Pens
[BLOCKPEN
];
179 childlayoutmsg
.MethodID
= GM_LAYOUT
;
180 childlayoutmsg
.gpl_GInfo
= &childgadinf
;
181 childlayoutmsg
.gpl_Initial
= 0;
183 ((struct Gadget
*)(data
->FirstChild
))->TopEdge
= 0 + CHILDPADDING
;
184 ((struct Gadget
*)(data
->FirstChild
))->Height
= childgadinf
.gi_Screen
->BarHeight
- (CHILDPADDING
<< 1);
186 DoMethodA(data
->FirstChild
, &childlayoutmsg
);
188 scr_findtitlearea((childgadinf
.gi_Screen
), &left
, &right
);
190 ((struct Gadget
*)(data
->FirstChild
))->LeftEdge
= right
- ((struct Gadget
*)(data
->FirstChild
))->Width
+ 1;
192 childlayoutmsg
.MethodID
= GM_GOACTIVE
;
193 DoMethodA(data
->FirstChild
, &childlayoutmsg
);
199 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
205 static IPTR
scrdecor_draw_screenbar(Class
*cl
, Object
*obj
, struct sdpDrawScreenBar
*msg
)
207 struct scrdecor_data
*data
= INST_DATA(cl
, obj
);
208 struct ScreenData
*sd
= (struct ScreenData
*) msg
->sdp_UserBuffer
;
209 struct TextExtent te
;
210 struct RastPort
*rp
= msg
->sdp_RPort
;
211 struct Screen
*scr
= msg
->sdp_Screen
;
212 struct DrawInfo
*dri
= msg
->sdp_Dri
;
213 UWORD
*pens
= dri
->dri_Pens
;
214 LONG left
, right
= 0, titlelen
= 0;
215 BOOL hastitle
= TRUE
;
216 BOOL beeping
= scr
->Flags
& BEEPING
;
219 SetAPen(rp
, pens
[BARDETAILPEN
]);
220 RectFill(rp
, 0, 0, scr
->Width
, sd
->img_stitlebar
->h
);
222 if (sd
->img_stitlebar
->ok
)
223 WriteVerticalScaledTiledImageHorizontal(rp
, sd
->img_stitlebar
, 0, 0,
224 sd
->img_stitlebar
->w
, 0, 0, data
->dc
->SBarHeight
, scr
->Width
, scr
->BarHeight
+ 1);
226 if (sd
->img_sbarlogo
->ok
)
227 WriteTiledImageHorizontal(rp
, sd
->img_sbarlogo
, 0, 0,
228 sd
->img_sbarlogo
->w
, data
->dc
->SLogoOffset
,
229 (scr
->BarHeight
+ 1 - sd
->img_sbarlogo
->h
) / 2, sd
->img_sbarlogo
->w
);
231 if (scr
->Title
== NULL
)
236 scr_findtitlearea(scr
, &left
, &right
);
237 titlelen
= strlen(scr
->Title
);
238 if (data
->FirstChild
)
240 if (((struct Gadget
*)(data
->FirstChild
))->Width
> 2) {
241 D(bug("[screendecor] draw_screenbar: titlechild width = %d\n", ((struct Gadget
*)(data
->FirstChild
))->Width
));
242 right
= right
- ((struct Gadget
*)(data
->FirstChild
))->Width
+ 1;
245 titlelen
= TextFit(rp
, scr
->Title
, titlelen
, &te
, NULL
, 1, right
- data
->dc
->STitleOffset
, scr
->BarHeight
);
246 if (titlelen
== 0) hastitle
= 0;
251 UWORD tx
= data
->dc
->STitleOffset
;
252 UWORD tymax
= scr
->BarHeight
- (dri
->dri_Font
->tf_YSize
- dri
->dri_Font
->tf_Baseline
) - 1;
253 UWORD ty
= ((scr
->BarHeight
+ dri
->dri_Font
->tf_Baseline
- 1) >> 1);
254 if (ty
> tymax
) ty
= tymax
;
256 SetFont(rp
, msg
->sdp_Dri
->dri_Font
);
259 if (!sd
->truecolor
|| ((data
->dc
->STitleOutline
== FALSE
) && (data
->dc
->STitleShadow
== FALSE
)))
261 SetAPen(rp
, pens
[beeping
? BARBLOCKPEN
: BARDETAILPEN
]);
263 Text(rp
, scr
->Title
, titlelen
);
265 else if (data
->dc
->STitleOutline
)
267 SetSoftStyle(rp
, FSF_BOLD
, AskSoftStyle(rp
));
268 SetRPAttrs(rp
, RPTAG_PenMode
, FALSE
, RPTAG_FgColor
, data
->dc
->STitleColorShadow
, TAG_DONE
);
270 Move(rp
, tx
+ 1, ty
); Text(rp
, scr
->Title
, titlelen
);
271 Move(rp
, tx
+ 2, ty
); Text(rp
, scr
->Title
, titlelen
);
272 Move(rp
, tx
, ty
); Text(rp
, scr
->Title
, titlelen
);
273 Move(rp
, tx
, ty
+ 1); Text(rp
, scr
->Title
, titlelen
);
274 Move(rp
, tx
, ty
+ 2); Text(rp
, scr
->Title
, titlelen
);
275 Move(rp
, tx
+ 1, ty
+ 2); Text(rp
, scr
->Title
, titlelen
);
276 Move(rp
, tx
+ 2, ty
+ 1); Text(rp
, scr
->Title
, titlelen
);
277 Move(rp
, tx
+ 2, ty
+ 2); Text(rp
, scr
->Title
, titlelen
);
279 SetRPAttrs(rp
, RPTAG_PenMode
, FALSE
, RPTAG_FgColor
, data
->dc
->STitleColorText
, TAG_DONE
);
280 Move(rp
, tx
+ 1, ty
+ 1);
281 Text(rp
, scr
->Title
, titlelen
);
282 SetSoftStyle(rp
, FS_NORMAL
, AskSoftStyle(rp
));
286 SetRPAttrs(rp
, RPTAG_PenMode
, FALSE
, RPTAG_FgColor
, data
->dc
->STitleColorShadow
, TAG_DONE
);
287 Move(rp
, tx
+ 1, ty
+ 1 );
288 Text(rp
, scr
->Title
, titlelen
);
290 SetRPAttrs(rp
, RPTAG_PenMode
, FALSE
, RPTAG_FgColor
, data
->dc
->STitleColorText
, TAG_DONE
);
292 Text(rp
, scr
->Title
, titlelen
);
296 if (data
->FirstChild
&& (((struct Gadget
*)(data
->FirstChild
))->Width
> 0)) {
297 struct GadgetInfo childgadinf
;
298 struct gpRender childrendermsg
=
306 childgadinf
.gi_Screen
= ((struct Gadget
*)(data
->FirstChild
))->SpecialInfo
= scr
;
307 childgadinf
.gi_RastPort
= rp
;
308 childgadinf
.gi_Pens
.DetailPen
= pens
[DETAILPEN
];
309 childgadinf
.gi_Pens
.BlockPen
= pens
[BLOCKPEN
];
310 childgadinf
.gi_DrInfo
= dri
;
311 childgadinf
.gi_Domain
.Left
= right
;
312 childgadinf
.gi_Domain
.Top
= 0 + CHILDPADDING
;
313 childgadinf
.gi_Domain
.Width
= ((struct Gadget
*)(data
->FirstChild
))->Width
;
314 childgadinf
.gi_Domain
.Height
= sd
->img_stitlebar
->h
- (CHILDPADDING
<< 1);
315 D(bug("[screendecor] draw_screenbar: rendering titlechild @ 0x%p, msg @ 0x%p, info @ 0x%p\n", data
->FirstChild
, &childrendermsg
, &childgadinf
));
316 DoMethodA(data
->FirstChild
, &childrendermsg
);
322 static IPTR
scrdecor_getdefsize_sysimage(Class
*cl
, Object
*obj
, struct sdpGetDefSizeSysImage
*msg
)
324 struct scrdecor_data
*data
= INST_DATA(cl
, obj
);
326 if (msg
->sdp_Which
== SDEPTHIMAGE
)
328 if (data
->di
&& data
->di
->img_sdepth
)
330 *msg
->sdp_Height
= data
->di
->img_sdepth
->h
;
331 *msg
->sdp_Width
= data
->di
->img_sdepth
->w
>> 1;
333 else return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
335 else return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
340 static IPTR
scrdecor_draw_sysimage(Class
*cl
, Object
*obj
, struct sdpDrawSysImage
*msg
)
342 struct ScreenData
*sd
= (struct ScreenData
*) msg
->sdp_UserBuffer
;
344 struct RastPort
*rp
= msg
->sdp_RPort
;
345 LONG left
= msg
->sdp_X
;
346 LONG top
= msg
->sdp_Y
;
347 LONG width
= msg
->sdp_Width
;
348 LONG height
= msg
->sdp_Height
;
349 LONG state
= msg
->sdp_State
;
351 if (msg
->sdp_Which
== SDEPTHIMAGE
)
355 DrawScaledStatefulGadgetImageToRP(rp
, sd
->img_sdepth
, state
, left
, top
, width
, height
);
357 else return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
359 else return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
364 static IPTR
scrdecor_layoutscrgadgets(Class
*cl
, Object
*obj
, struct sdpLayoutScreenGadgets
*msg
)
366 struct Gadget
*gadget
= msg
->sdp_Gadgets
;
367 struct ScreenData
*sd
= (struct ScreenData
*) msg
->sdp_UserBuffer
;
369 struct scrdecor_data
*data
= INST_DATA(cl
, obj
);
373 switch(gadget
->GadgetType
& GTYP_SYSTYPEMASK
)
376 gadget
->LeftEdge
= -gadget
->Width
+ 1;
377 gadget
->TopEdge
= (data
->dc
->SBarHeight
- sd
->img_sdepth
->h
) >> 1;
378 gadget
->Flags
&= ~GFLG_RELWIDTH
;
379 gadget
->Flags
|= GFLG_RELRIGHT
;
383 if (msg
->sdp_Flags
& SDF_LSG_MULTIPLE
)
385 gadget
= gadget
->NextGadget
;
396 static IPTR
scrdecor_initscreen(Class
*cl
, Object
*obj
, struct sdpInitScreen
*msg
)
398 struct scrdecor_data
*data
= INST_DATA(cl
, obj
);
399 struct ScreenData
*sd
= (struct ScreenData
*)msg
->sdp_UserBuffer
;
400 struct Screen
*screen
= msg
->sdp_Screen
;
402 sd
->truecolor
= msg
->sdp_TrueColor
;
404 BOOL truecolor
= sd
->truecolor
;
407 * This depends on openwindow.c adding font height to w->BorderTop.
408 * It allows the window title bar to grow when font is bigger than decoration defined height
410 if ((msg
->sdp_FontHeight
+ 2) > data
->dc
->BarHeight
)
411 msg
->sdp_WBorTop
= 1;
413 msg
->sdp_WBorTop
= data
->dc
->BarHeight
- 1 - msg
->sdp_FontHeight
;
415 /* Allow scaling title bar above decoration defined height */
416 msg
->sdp_BarHeight
= msg
->sdp_FontHeight
> (data
->dc
->SBarHeight
- 1) ? msg
->sdp_FontHeight
: (data
->dc
->SBarHeight
- 1);
418 msg
->sdp_BarHBorder
= 1;
419 msg
->sdp_WBorLeft
= data
->dc
->LeftBorder
;
420 msg
->sdp_WBorRight
= data
->dc
->RightBorder
;
421 msg
->sdp_WBorBottom
= data
->dc
->BottomBorder
;
424 sd
->DeactivePen
= -1;
425 #if 0 // Omitting this gives better colours on low-color screens
427 sd
->ActivePen
= ObtainPen(screen
->ViewPort
.ColorMap
, -1, (data
->dc
->LUTBaseColors_a
<< 8) & 0xff000000, (data
->dc
->LUTBaseColors_a
<< 16) & 0xff000000, (data
->dc
->LUTBaseColors_a
<< 24) & 0xff000000, PEN_EXCLUSIVE
);
428 sd
->DeactivePen
= ObtainPen(screen
->ViewPort
.ColorMap
, -1, (data
->dc
->LUTBaseColors_d
<< 8) & 0xff000000, (data
->dc
->LUTBaseColors_d
<< 16) & 0xff000000, (data
->dc
->LUTBaseColors_d
<< 24) & 0xff000000, PEN_EXCLUSIVE
);
432 /* Convert initial images to current screen */
433 /* Make sure a structure is always generated even if there is no image
434 That was the assumption of previous code :/ */
436 sd
->di
= NewImages();
438 SETIMAGE_SCR(sdepth
);
439 SETIMAGE_SCR(sbarlogo
);
440 SETIMAGE_SCR(stitlebar
);
452 SETIMAGE_SCR(snapshot
);
453 SETIMAGE_SCR(iconify
);
455 SETIMAGE_SCR(winbar_normal
);
456 SETIMAGE_SCR(border_normal
);
457 SETIMAGE_SCR(border_deactivated
);
458 SETIMAGE_SCR(verticalcontainer
);
459 SETIMAGE_SCR(verticalknob
);
460 SETIMAGE_SCR(horizontalcontainer
);
461 SETIMAGE_SCR(horizontalknob
);
464 SETIMAGE_SCR(amigakey
);
465 SETIMAGE_SCR(menucheck
);
466 SETIMAGE_SCR(submenu
);
468 /* Set pointers to converted images */
469 sd
->img_sdepth
= sd
->di
->img_sdepth
;
470 sd
->img_sbarlogo
= sd
->di
->img_sbarlogo
;
471 sd
->img_stitlebar
= sd
->di
->img_stitlebar
;
473 sd
->img_amigakey
= sd
->di
->img_amigakey
;
474 sd
->img_menucheck
= sd
->di
->img_menucheck
;
475 sd
->img_submenu
= sd
->di
->img_submenu
;
480 static IPTR
scrdecor_exitscreen(Class
*cl
, Object
*obj
, struct sdpExitScreen
*msg
)
482 struct ScreenData
*sd
= (struct ScreenData
*)msg
->sdp_UserBuffer
;
489 /**************************************************************************************************/
491 static IPTR
scrdecor_dispatcher(struct IClass
*cl
, Object
*obj
, Msg msg
)
495 switch(msg
->MethodID
)
498 retval
= scrdecor_new(cl
, obj
, (struct opSet
*)msg
);
502 retval
= scrdecor_dispose(cl
, obj
, (struct opSet
*)msg
);
506 retval
= scrdecor_get(cl
, obj
, (struct opGet
*)msg
);
510 retval
= scrdecor_set(cl
, obj
, (struct opSet
*)msg
);
513 case SDM_GETDEFSIZE_SYSIMAGE
:
514 retval
= scrdecor_getdefsize_sysimage(cl
, obj
, (struct sdpGetDefSizeSysImage
*)msg
);
517 case SDM_DRAW_SCREENBAR
:
518 retval
= scrdecor_draw_screenbar(cl
, obj
, (struct sdpDrawScreenBar
*)msg
);
521 case SDM_DRAW_SYSIMAGE
:
522 retval
= scrdecor_draw_sysimage(cl
, obj
, (struct sdpDrawSysImage
*)msg
);
525 case SDM_LAYOUT_SCREENGADGETS
:
526 retval
= scrdecor_layoutscrgadgets(cl
, obj
, (struct sdpLayoutScreenGadgets
*)msg
);
530 retval
= scrdecor_initscreen(cl
, obj
, (struct sdpInitScreen
*)msg
);
534 retval
= scrdecor_exitscreen(cl
, obj
, (struct sdpExitScreen
*)msg
);
538 retval
= DoSuperMethodA(cl
, obj
, msg
);
545 struct IClass
* MakeScreenDecorClass()
547 struct IClass
* cl
= MakeClass(NULL
, SCRDECORCLASS
, NULL
, sizeof(struct scrdecor_data
), 0);
550 cl
->cl_Dispatcher
.h_Entry
= HookEntry
;
551 cl
->cl_Dispatcher
.h_SubEntry
= (HOOKFUNC
)scrdecor_dispatcher
;