prism2.device: Compiler delint
[AROS.git] / workbench / prefs / pointer / ppreview.c
blob24ae0f4c5171b4a0ff693d25390f3d00e3274457
1 /*
2 Copyright 2010, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define MUIMASTER_YES_INLINE_STDARG
8 #include <datatypes/pictureclass.h>
10 // #define DEBUG 1
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>
24 #include "locale.h"
25 #include "ppreview.h"
26 #include "prefs.h"
28 /*** Instance Data **********************************************************/
29 struct PPreview_DATA
31 Object *pprv_prevEditor;
32 UWORD pprv_alpha;
33 UWORD pprv_hspot_x;
34 UWORD pprv_hspot_y;
35 STRPTR pprv_filename;
36 struct MUI_EventHandlerNode pprv_ehn;
37 APTR pprv_dto;
38 struct BitMapHeader *pprv_bmhd;
39 struct BitMap *pprv_bm;
40 LONG pprv_offset_x;
41 LONG pprv_offset_y;
42 LONG pprv_draw_width;
43 LONG pprv_draw_height;
44 BOOL pprv_set_hspot;
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)
53 data->pprv_bm = NULL;
54 data->pprv_bmhd = NULL;
56 if (data->pprv_dto)
58 DisposeDTObject(data->pprv_dto);
59 data->pprv_dto = NULL;
63 STATIC IPTR setup_datatype(Class *cl, Object *obj)
65 SETUP_INST_DATA;
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,
82 TAG_DONE);
84 me->pr_WindowPtr = oldwinptr;
86 D(bug("[Pointer/setup] dto %p\n", data->pprv_dto));
87 if (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);
97 if (data->pprv_bmhd)
99 if (data->pprv_bmhd->bmh_Masking != mskNone)
100 SET(obj, MUIA_FillArea, TRUE);
101 else
102 SET(obj, MUIA_FillArea, FALSE);
104 GetDTAttrs(data->pprv_dto, PDTA_DestBitMap, &data->pprv_bm, TAG_DONE);
105 if (!data->pprv_bm)
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) */
116 killdto(data);
118 return TRUE;
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);
128 if (!obj) return 0;
130 SETUP_INST_DATA;
132 while ((tag = NextTagItem(&tstate)) != NULL)
134 switch (tag->ti_Tag)
136 case MUIA_PPreview_Alpha:
137 data->pprv_alpha = tag->ti_Data;
138 break;
140 case MUIA_PPreview_HSpotX:
141 data->pprv_hspot_x = tag->ti_Data;
142 break;
144 case MUIA_PPreview_HSpotY:
145 data->pprv_hspot_y = tag->ti_Data;
146 break;
148 case MUIA_PPreview_SetHSpot:
149 data->pprv_set_hspot= tag->ti_Data;
150 break;
152 case MUIA_PPreview_FileName:
153 FreeVec(data->pprv_filename);
154 data->pprv_filename = StrDup((STRPTR)tag->ti_Data);
155 break;
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;
169 return obj;
172 IPTR PPreview__OM_DISPOSE(Class *cl, Object *obj, Msg msg)
174 SETUP_INST_DATA;
176 FreeVec(data->pprv_filename);
177 return DoSuperMethodA(cl, obj, msg);
180 IPTR PPreview__OM_SET(Class *cl, Object *obj, struct opSet *msg)
182 SETUP_INST_DATA;
184 struct TagItem *tags = msg->ops_AttrList;
185 struct TagItem *tag;
186 BOOL needs_redraw = FALSE;
188 while ((tag = NextTagItem(&tags)) != NULL)
190 switch(tag->ti_Tag)
192 case MUIA_PPreview_Alpha:
193 needs_redraw = TRUE;
194 data->pprv_alpha = tag->ti_Data;
195 break;
197 case MUIA_PPreview_HSpotX:
198 needs_redraw = TRUE;
199 data->pprv_hspot_x = tag->ti_Data;
200 break;
202 case MUIA_PPreview_HSpotY:
203 needs_redraw = TRUE;
204 data->pprv_hspot_y = tag->ti_Data;
205 break;
207 case MUIA_PPreview_SetHSpot:
208 needs_redraw = TRUE;
209 data->pprv_set_hspot = tag->ti_Data;
210 break;
212 case MUIA_PPreview_FileName:
213 needs_redraw = TRUE;
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);
218 break;
220 } /* switch(tag->ti_Tag) */
221 } /* while ((tag = NextTagItem(&tags)) != NULL) */
223 if (needs_redraw)
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)
233 SETUP_INST_DATA;
235 switch (msg->opg_AttrID)
237 case MUIA_PPreview_Alpha:
238 *msg->opg_Storage = data->pprv_alpha;
239 return TRUE;
241 case MUIA_PPreview_HSpotX:
242 *msg->opg_Storage = data->pprv_hspot_x;
243 return TRUE;
245 case MUIA_PPreview_HSpotY:
246 *msg->opg_Storage = data->pprv_hspot_y;
247 return TRUE;
249 case MUIA_PPreview_SetHSpot:
250 *msg->opg_Storage = data->pprv_set_hspot;
251 return TRUE;
253 case MUIA_PPreview_FileName:
254 *msg->opg_Storage = (IPTR)data->pprv_filename;
255 return TRUE;
258 return DoSuperMethodA(cl, obj, (Msg)msg);
261 IPTR PPreview__MUIM_Setup(Class *cl, Object *obj, struct MUIP_Setup *msg)
263 SETUP_INST_DATA;
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)
276 SETUP_INST_DATA;
278 killdto(data);
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)
287 SETUP_INST_DATA;
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
305 drawwidth = bmwidth;
306 drawoffsetx = (_width(obj) - drawwidth) / 2 + _left(obj);
308 else
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);
319 else
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);
336 if (img)
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;
343 pa.pbpa_Left = 0;
344 pa.pbpa_Top = 0;
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"));
350 WritePixelArrayAlpha
352 img, 0, 0, bmwidth * 4, _rp(obj),
353 drawoffsetx, drawoffsety, drawwidth, drawheight, 0xffffffff
356 FreeVec((APTR) img);
359 else
361 if (data->pprv_bmhd->bmh_Masking == mskHasMask)
363 /* Transparency with mask */
364 APTR mask = NULL;
366 GetDTAttrs(data->pprv_dto, PDTA_MaskPlane, (IPTR)&mask, TAG_DONE);
368 if (mask)
369 BltMaskBitMapRastPort(data->pprv_bm, 0, 0, _rp(obj), drawoffsetx,
370 drawoffsety, drawwidth, drawheight, 0xE0, (PLANEPTR)mask);
372 else
374 /* All other cases */
375 BltBitMapRastPort(data->pprv_bm, 0, 0, _rp(obj), drawoffsetx, drawoffsety,
376 drawwidth, drawheight, 0xC0);
380 // draw bounding box
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);
388 // draw hotspot
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);
410 return 0;
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;
424 return retval;
427 IPTR PPreview__MUIM_HandleEvent(Class *cl, Object *obj, struct MUIP_HandleEvent *msg)
429 SETUP_INST_DATA;
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);
458 break;
463 #undef _between
464 #undef _isinobject
466 return 0;
469 /*** Setup ******************************************************************/
470 ZUNE_CUSTOMCLASS_9
472 PPreview, NULL, MUIC_Area, NULL,
473 OM_NEW, struct opSet *,
474 OM_DISPOSE, Msg,
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 *