2 Copyright 2010, The AROS Development Team. All rights reserved.
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <datatypes/pictureclass.h>
11 #include <zune/customclasses.h>
12 #include <zune/prefseditor.h>
14 #include <proto/alib.h>
15 #include <proto/intuition.h>
16 #include <proto/utility.h>
17 #include <proto/muimaster.h>
18 #include <proto/graphics.h>
19 #include <proto/datatypes.h>
20 #include <proto/cybergraphics.h>
22 #include <aros/debug.h>
28 /*** Instance Data **********************************************************/
31 Object
*pprv_prevEditor
;
36 struct MUI_EventHandlerNode pprv_ehn
;
38 struct BitMapHeader
*pprv_bmhd
;
39 struct BitMap
*pprv_bm
;
43 LONG pprv_draw_height
;
47 /*** Macros *****************************************************************/
48 #define SETUP_INST_DATA struct PPreview_DATA *data = INST_DATA(cl, obj)
50 /*** Functions **************************************************************/
51 STATIC VOID
killdto(struct PPreview_DATA
*data
)
54 data
->pprv_bmhd
= NULL
;
58 DisposeDTObject(data
->pprv_dto
);
59 data
->pprv_dto
= NULL
;
63 STATIC IPTR
setup_datatype(Class
*cl
, Object
*obj
)
67 if (data
->pprv_dto
) killdto(data
); /* Object already existed */
69 if (data
->pprv_filename
)
71 /* Prevent DOS Requesters from showing up */
72 struct Process
*me
= (struct Process
*)FindTask(0);
73 APTR oldwinptr
= me
->pr_WindowPtr
;
74 me
->pr_WindowPtr
= (APTR
)-1;
76 data
->pprv_dto
= NewDTObject(data
->pprv_filename
,
77 DTA_GroupID
, GID_PICTURE
,
78 OBP_Precision
, PRECISION_IMAGE
,
79 PDTA_Screen
, _screen(obj
),
80 PDTA_DestMode
, PMODE_V43
,
81 PDTA_UseFriendBitMap
, TRUE
,
84 me
->pr_WindowPtr
= oldwinptr
;
86 D(bug("[Pointer/setup] dto %p\n", data
->pprv_dto
));
89 struct FrameInfo fri
= {0};
91 DoMethod(data
->pprv_dto
, DTM_FRAMEBOX
, 0, &fri
, &fri
, sizeof(struct FrameInfo
), 0);
92 if (fri
.fri_Dimensions
.Depth
> 0)
94 if (DoMethod(data
->pprv_dto
, DTM_PROCLAYOUT
, 0, 1))
96 GET(data
->pprv_dto
, PDTA_BitMapHeader
, &data
->pprv_bmhd
);
99 if (data
->pprv_bmhd
->bmh_Masking
!= mskNone
)
100 SET(obj
, MUIA_FillArea
, TRUE
);
102 SET(obj
, MUIA_FillArea
, FALSE
);
104 GetDTAttrs(data
->pprv_dto
, PDTA_DestBitMap
, &data
->pprv_bm
, TAG_DONE
);
107 GetDTAttrs(data
->pprv_dto
, PDTA_BitMap
, &data
->pprv_bm
, TAG_DONE
);
109 D(bug("[Pointer/setup] BitMap %p\n", data
->pprv_bm
));
110 if (data
->pprv_bm
) return TRUE
;
111 } /* if (data->bmhd) */
112 } /* if (DoMethod(data->dto, DTM_PROCLAYOUT, 0, 1)) */
113 } /* if (fri.fri_Dimensions.Depth > 0) */
114 } /* if (data->dto) */
115 } /* if (data->name) */
121 /*** Methods ****************************************************************/
122 Object
*PPreview__OM_NEW(Class
*cl
, Object
*obj
, struct opSet
*msg
)
124 struct TagItem
*tstate
= msg
->ops_AttrList
;
125 struct TagItem
*tag
= NULL
;
127 obj
= (Object
*)DoSuperMethodA(cl
, obj
, (Msg
)msg
);
132 while ((tag
= NextTagItem(&tstate
)) != NULL
)
136 case MUIA_PPreview_Alpha
:
137 data
->pprv_alpha
= tag
->ti_Data
;
140 case MUIA_PPreview_HSpotX
:
141 data
->pprv_hspot_x
= tag
->ti_Data
;
144 case MUIA_PPreview_HSpotY
:
145 data
->pprv_hspot_y
= tag
->ti_Data
;
148 case MUIA_PPreview_SetHSpot
:
149 data
->pprv_set_hspot
= tag
->ti_Data
;
152 case MUIA_PPreview_FileName
:
153 FreeVec(data
->pprv_filename
);
154 data
->pprv_filename
= StrDup((STRPTR
)tag
->ti_Data
);
160 data
->pprv_offset_x
= -1;
161 data
->pprv_offset_y
= -1;
163 data
->pprv_ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
164 data
->pprv_ehn
.ehn_Priority
= 0;
165 data
->pprv_ehn
.ehn_Flags
= 0;
166 data
->pprv_ehn
.ehn_Object
= obj
;
167 data
->pprv_ehn
.ehn_Class
= cl
;
172 IPTR
PPreview__OM_DISPOSE(Class
*cl
, Object
*obj
, Msg msg
)
176 FreeVec(data
->pprv_filename
);
177 return DoSuperMethodA(cl
, obj
, msg
);
180 IPTR
PPreview__OM_SET(Class
*cl
, Object
*obj
, struct opSet
*msg
)
184 struct TagItem
*tags
= msg
->ops_AttrList
;
186 BOOL needs_redraw
= FALSE
;
188 while ((tag
= NextTagItem(&tags
)) != NULL
)
192 case MUIA_PPreview_Alpha
:
194 data
->pprv_alpha
= tag
->ti_Data
;
197 case MUIA_PPreview_HSpotX
:
199 data
->pprv_hspot_x
= tag
->ti_Data
;
202 case MUIA_PPreview_HSpotY
:
204 data
->pprv_hspot_y
= tag
->ti_Data
;
207 case MUIA_PPreview_SetHSpot
:
209 data
->pprv_set_hspot
= tag
->ti_Data
;
212 case MUIA_PPreview_FileName
:
214 FreeVec(data
->pprv_filename
);
215 data
->pprv_filename
= StrDup((STRPTR
)tag
->ti_Data
);
216 //if (_flags(obj) & MADF_SETUP) setup_datatype(cl, obj);
217 setup_datatype(cl
, obj
);
220 } /* switch(tag->ti_Tag) */
221 } /* while ((tag = NextTagItem(&tags)) != NULL) */
225 MUI_Redraw(obj
, MADF_DRAWOBJECT
);
228 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
231 IPTR
PPreview__OM_GET(Class
*cl
, Object
*obj
, struct opGet
*msg
)
235 switch (msg
->opg_AttrID
)
237 case MUIA_PPreview_Alpha
:
238 *msg
->opg_Storage
= data
->pprv_alpha
;
241 case MUIA_PPreview_HSpotX
:
242 *msg
->opg_Storage
= data
->pprv_hspot_x
;
245 case MUIA_PPreview_HSpotY
:
246 *msg
->opg_Storage
= data
->pprv_hspot_y
;
249 case MUIA_PPreview_SetHSpot
:
250 *msg
->opg_Storage
= data
->pprv_set_hspot
;
253 case MUIA_PPreview_FileName
:
254 *msg
->opg_Storage
= (IPTR
)data
->pprv_filename
;
258 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
261 IPTR
PPreview__MUIM_Setup(Class
*cl
, Object
*obj
, struct MUIP_Setup
*msg
)
265 if (!DoSuperMethodA(cl
, obj
, (Msg
)msg
)) return FALSE
;
267 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) &data
->pprv_ehn
);
269 data
->pprv_prevEditor
= (Object
*)XGET((Object
*)XGET(obj
, MUIA_Parent
), MUIA_Parent
);
271 return setup_datatype(cl
, obj
);
274 IPTR
PPreview__MUIM_Cleanup(Class
*cl
, Object
*obj
, struct MUIP_Cleanup
*msg
)
280 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) &data
->pprv_ehn
);
282 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
285 IPTR
PPreview__MUIM_Draw(Class
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
289 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
291 data
->pprv_offset_x
= -1;
292 data
->pprv_offset_y
= -1;
294 if ((msg
->flags
& MADF_DRAWOBJECT
) && data
->pprv_bm
)
296 ULONG drawwidth
, drawheight
, drawoffsetx
, drawoffsety
;
298 ULONG depth
= (ULONG
) GetBitMapAttr(_rp(obj
)->BitMap
, BMA_DEPTH
);
299 LONG bmwidth
= data
->pprv_bmhd
->bmh_Width
;
300 LONG bmheight
= data
->pprv_bmhd
->bmh_Height
;
302 // calculate for centered rendering
303 if (_width(obj
) > bmwidth
+ 2) // two pixels for bounding box
306 drawoffsetx
= (_width(obj
) - drawwidth
) / 2 + _left(obj
);
310 drawwidth
= _width(obj
);
311 drawoffsetx
= _left(obj
);
314 if (_height(obj
) > bmheight
+ 2)
316 drawheight
= bmheight
;
317 drawoffsety
= (_height(obj
) - drawheight
) / 2 + _top(obj
);
321 drawheight
= _height(obj
);
322 drawoffsety
= _top(obj
);
325 // remember offset for event handler
326 data
->pprv_offset_x
= drawoffsetx
;
327 data
->pprv_offset_y
= drawoffsety
;
328 data
->pprv_draw_width
= drawwidth
;
329 data
->pprv_draw_height
= drawheight
;
331 D(bug("[Pointer/Draw] bitmap %p depth %u\n", data
->pprv_bm
, depth
));
332 if ((depth
>= 15) && (data
->pprv_bmhd
->bmh_Masking
== mskHasAlpha
))
334 /* Transparency on high color rast port with alpha channel in picture*/
335 ULONG
* img
= AllocVec(bmwidth
* bmheight
* 4, MEMF_ANY
);
338 struct pdtBlitPixelArray pa
;
339 pa
.MethodID
= PDTM_READPIXELARRAY
;
340 pa
.pbpa_PixelData
= (UBYTE
*) img
;
341 pa
.pbpa_PixelFormat
= PBPAFMT_ARGB
;
342 pa
.pbpa_PixelArrayMod
= bmwidth
* 4;
345 pa
.pbpa_Width
= bmwidth
;
346 pa
.pbpa_Height
= bmheight
;
347 if (DoMethodA(data
->pprv_dto
, (Msg
) &pa
))
349 D(bug("[Pointer/Draw] ReadPixelarray for d>=15 OK\n"));
352 img
, 0, 0, bmwidth
* 4, _rp(obj
),
353 drawoffsetx
, drawoffsety
, drawwidth
, drawheight
, 0xffffffff
361 if (data
->pprv_bmhd
->bmh_Masking
== mskHasMask
)
363 /* Transparency with mask */
366 GetDTAttrs(data
->pprv_dto
, PDTA_MaskPlane
, (IPTR
)&mask
, TAG_DONE
);
369 BltMaskBitMapRastPort(data
->pprv_bm
, 0, 0, _rp(obj
), drawoffsetx
,
370 drawoffsety
, drawwidth
, drawheight
, 0xE0, (PLANEPTR
)mask
);
374 /* All other cases */
375 BltBitMapRastPort(data
->pprv_bm
, 0, 0, _rp(obj
), drawoffsetx
, drawoffsety
,
376 drawwidth
, drawheight
, 0xC0);
381 SetAPen(_rp(obj
), 1);
382 Move(_rp(obj
), drawoffsetx
- 1, drawoffsety
- 1);
383 Draw(_rp(obj
), drawoffsetx
+ drawwidth
+ 1, drawoffsety
- 1);
384 Draw(_rp(obj
), drawoffsetx
+ drawwidth
+ 1, drawoffsety
+ drawheight
+ 1);
385 Draw(_rp(obj
), drawoffsetx
- 1, drawoffsety
+ drawheight
+ 1);
386 Draw(_rp(obj
), drawoffsetx
- 1, drawoffsety
- 1);
389 if (data
->pprv_set_hspot
)
391 D(bug("[Pointer/Draw] Draw hotspot at %d %d\n", drawoffsetx
+ data
->pprv_hspot_x
, drawoffsety
+ data
->pprv_hspot_y
));
392 /* I experimented with inversion, it looks better IMHO - sonic
393 SetAPen(_rp(obj), 1); */
394 SetDrMd(_rp(obj
), COMPLEMENT
);
395 if (data
->pprv_hspot_x
< drawwidth
)
397 Move(_rp(obj
), drawoffsetx
+ data
->pprv_hspot_x
, drawoffsety
);
398 Draw(_rp(obj
), drawoffsetx
+ data
->pprv_hspot_x
, drawoffsety
+ drawheight
);
400 if (data
->pprv_hspot_y
< drawheight
)
402 Move(_rp(obj
), drawoffsetx
, drawoffsety
+ data
->pprv_hspot_y
);
403 Draw(_rp(obj
), drawoffsetx
+ drawwidth
, drawoffsety
+ data
->pprv_hspot_y
);
405 /* Reset drawmode back to JAM2, otherwise shit happens */
406 SetDrMd(_rp(obj
), JAM2
);
413 IPTR
PPreview__MUIM_AskMinMax(Class
*cl
, Object
*obj
, struct MUIP_AskMinMax
*msg
)
415 IPTR retval
= DoSuperMethodA(cl
, obj
, (Msg
)msg
);
417 msg
->MinMaxInfo
->MinWidth
+= 64;
418 msg
->MinMaxInfo
->MinHeight
+= 64;
419 msg
->MinMaxInfo
->DefWidth
+= 64;
420 msg
->MinMaxInfo
->DefHeight
+= 64;
421 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
422 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
427 IPTR
PPreview__MUIM_HandleEvent(Class
*cl
, Object
*obj
, struct MUIP_HandleEvent
*msg
)
431 #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
432 #define _isinobject(x,y) (_between(data->pprv_offset_x,(x),data->pprv_offset_x+data->pprv_draw_width) && \
433 _between(data->pprv_offset_y,(y),data->pprv_offset_y+data->pprv_draw_height))
435 if (data
->pprv_set_hspot
&& (data
->pprv_offset_x
!= -1) && msg
->imsg
)
437 switch (msg
->imsg
->Class
)
439 case IDCMP_MOUSEBUTTONS
:
441 if (msg
->imsg
->Code
== SELECTUP
)
443 D(bug("[PPreview/HandleEvent] offx %d offy %d w %d h %d mx %d my %d\n",
444 data
->pprv_offset_x
, data
->pprv_offset_y
,
445 data
->pprv_draw_width
, data
->pprv_draw_height
,
446 msg
->imsg
->MouseX
, msg
->imsg
->MouseY
));
447 if (_isinobject(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
))
449 data
->pprv_hspot_x
= msg
->imsg
->MouseX
- data
->pprv_offset_x
;
450 data
->pprv_hspot_y
= msg
->imsg
->MouseY
- data
->pprv_offset_y
;
451 D(bug("[PPreview/HandleEvent] X %d Y %d\n", data
->pprv_hspot_x
, data
->pprv_hspot_y
));
452 MUI_Redraw(obj
, MADF_DRAWOBJECT
);
454 SET(data
->pprv_prevEditor
, MUIA_PrefsEditor_Changed
, TRUE
);
469 /*** Setup ******************************************************************/
472 PPreview
, NULL
, MUIC_Area
, NULL
,
473 OM_NEW
, struct opSet
*,
475 OM_SET
, struct opSet
*,
476 OM_GET
, struct opGet
*,
477 MUIM_Setup
, struct MUIP_Setup
*,
478 MUIM_Cleanup
, struct MUIP_Cleanup
*,
479 MUIM_Draw
, struct MUIP_Draw
*,
480 MUIM_AskMinMax
, struct MUIP_AskMinMax
*,
481 MUIM_HandleEvent
, struct MUIP_HandleEvent
*