Avoid buttons getting "stuck down":
[AROS.git] / workbench / libs / muimaster / classes / area.c
blobb8abb2ba2aae0b5e84ecffe75ca0884c16434b6f
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2016, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
9 #include <stdlib.h>
10 #include <string.h>
11 #include <exec/types.h>
12 #include <graphics/gfxmacros.h>
13 #include <intuition/imageclass.h>
14 #include <libraries/gadtools.h>
15 #include <devices/rawkeycodes.h>
17 #include <clib/alib_protos.h>
18 #include <proto/exec.h>
19 #include <proto/intuition.h>
20 #include <proto/graphics.h>
21 #include <proto/utility.h>
22 #include <proto/muimaster.h>
24 extern struct Library *MUIMasterBase;
25 #include "muimaster_intern.h"
27 #include "mui.h"
28 #include "support.h"
29 #include "imspec.h"
30 #include "menu.h"
31 #include "prefs.h"
32 #include "font.h"
33 #include "textengine.h"
34 #include "bubbleengine.h"
35 #include "datatypescache.h"
38 // #define MYDEBUG 1
39 #include "debug.h"
42 Area.mui/MUIA_Background done
43 Area.mui/MUIA_BottomEdge done
44 Area.mui/MUIA_ContextMenu done
45 Area.mui/MUIA_ContextMenuTrigger
46 Area.mui/MUIA_ControlChar done
47 Area.mui/MUIA_CycleChain done
48 Area.mui/MUIA_Disabled done
49 Area.mui/MUIA_Draggable done
50 Area.mui/MUIA_Dropable done
51 Area.mui/MUIA_ExportID
52 Area.mui/MUIA_FillArea done
53 Area.mui/MUIA_FixHeight done
54 Area.mui/MUIA_FixHeightTxt done
55 Area.mui/MUIA_FixWidth done
56 Area.mui/MUIA_FixWidthTxt done
57 Area.mui/MUIA_Font done
58 Area.mui/MUIA_Frame done
59 Area.mui/MUIA_FramePhantomHoriz done
60 Area.mui/MUIA_FrameTitle done
61 Area.mui/MUIA_Height done
62 Area.mui/MUIA_HorizDisappear
63 Area.mui/MUIA_HorizWeight done
64 Area.mui/MUIA_InnerBottom done
65 Area.mui/MUIA_InnerLeft done
66 Area.mui/MUIA_InnerRight done
67 Area.mui/MUIA_InnerTop done
68 Area.mui/MUIA_InputMode done
69 Area.mui/MUIA_LeftEdge done
70 Area.mui/MUIA_MaxHeight done
71 Area.mui/MUIA_MaxWidth done
72 Area.mui/MUIA_Pressed done
73 Area.mui/MUIA_RightEdge done
74 Area.mui/MUIA_Selected done
75 Area.mui/MUIA_ShortHelp done
76 Area.mui/MUIA_ShowMe done
77 Area.mui/MUIA_ShowSelState done (I only)
78 Area.mui/MUIA_Timer done
79 Area.mui/MUIA_TopEdge done
80 Area.mui/MUIA_VertDisappear
81 Area.mui/MUIA_VertWeight done
82 Area.mui/MUIA_Weight done
83 Area.mui/MUIA_Width done
84 Area.mui/MUIA_Window done
85 Area.mui/MUIA_WindowObject done
87 Area.mui/MUIM_AskMinMax done
88 Area.mui/MUIM_Cleanup done
89 Area.mui/MUIM_ContextMenuBuild done
90 Area.mui/MUIM_ContextMenuChoice done
91 Area.mui/MUIM_CreateBubble done
92 Area.mui/MUIM_CreateShortHelp done
93 Area.mui/MUIM_DeleteBubble done
94 Area.mui/MUIM_DeleteShortHelp done
95 Area.mui/MUIM_DragBegin
96 Area.mui/MUIM_DragDrop done
97 Area.mui/MUIM_DragFinish
98 Area.mui/MUIM_DragQuery done
99 Area.mui/MUIM_DragReport
100 Area.mui/MUIM_Draw done
101 Area.mui/MUIM_DrawBackground done
102 Area.mui/MUIM_HandleEvent done
103 Area.mui/MUIM_HandleInput
104 Area.mui/MUIM_Hide done
105 Area.mui/MUIM_Setup done
106 Area.mui/MUIM_Show done
109 static const int __version = 1;
110 static const int __revision = 1;
112 //#ifdef DEBUG
113 //static STRPTR zune_area_to_string (Object *area);
114 //#endif
116 static const struct MUI_FrameSpec_intern *get_intframe(Object *obj,
117 struct MUI_AreaData *data, struct MUI_FrameSpec_intern *tempstore);
118 static void set_inner_sizes(Object *obj, struct MUI_AreaData *data);
119 static void set_title_sizes(Object *obj, struct MUI_AreaData *data);
120 static void handle_release(struct IClass *cl, Object *obj, int cancel);
122 static void area_update_msizes(Object *obj, struct MUI_AreaData *data,
123 const struct MUI_FrameSpec_intern *frame,
124 const struct ZuneFrameGfx *zframe);
125 static void setup_control_char(struct MUI_AreaData *data, Object *obj,
126 struct IClass *cl);
127 static void cleanup_control_char(struct MUI_AreaData *data, Object *obj);
129 //static void setup_cycle_chain (struct MUI_AreaData *data, Object *obj);
130 //static void cleanup_cycle_chain (struct MUI_AreaData *data, Object *obj);
132 #define ZUNE_FOCUS_TYPE_ACTIVE_OBJ 0
133 #define ZUNE_FOCUS_TYPE_DROP_OBJ 1
135 static void _zune_focus_new(Object *obj, int type)
137 Object *parent;
138 struct RastPort *rp;
139 UWORD oldDrPt;
141 //bug("_zune_focus_new 1 %p\n", obj);
143 if (NULL == obj || !(_flags(obj) & MADF_CANDRAW))
144 return;
146 parent = _parent(obj);
147 rp = _rp(obj);
148 oldDrPt = rp->LinePtrn;
150 int x1 = _left(obj);
151 int y1 = _top(obj);
152 int x2 = _left(obj) + _width(obj) - 1;
153 int y2 = _top(obj) + _height(obj) - 1;
155 if (!parent || parent == _win(obj))
156 return;
158 SetABPenDrMd(rp, _pens(obj)[MPEN_SHINE], _pens(obj)[MPEN_SHADOW], JAM2);
160 if (type == ZUNE_FOCUS_TYPE_ACTIVE_OBJ)
162 SetDrPt(rp, 0xCCCC);
163 x1--;
164 y1--;
165 x2++;
166 y2++;
168 else
170 SetDrPt(rp, 0xF0F0);
173 Move(rp, x1, y1);
174 Draw(rp, x2, y1);
175 Draw(rp, x2, y2);
176 Draw(rp, x1, y2);
177 Draw(rp, x1, y1);
178 SetDrPt(rp, oldDrPt);
181 static void _zune_focus_destroy(Object *obj, int type)
183 Object *parent;
185 //bug("_zune_focus_destroy 1 %p\n", obj);
187 if (NULL == obj || !(_flags(obj) & MADF_CANDRAW))
188 return;
190 parent = _parent(obj);
191 int x1 = _left(obj);
192 int y1 = _top(obj);
193 int x2 = _left(obj) + _width(obj) - 1;
194 int y2 = _top(obj) + _height(obj) - 1;
195 int width;
196 int height;
198 if (type == ZUNE_FOCUS_TYPE_ACTIVE_OBJ)
200 if (!parent || parent == _win(obj))
201 return;
203 x1--;
204 y1--;
205 x2++;
206 y2++;
207 width = x2 - x1 + 1;
208 height = y2 - y1 + 1;
210 DoMethod(parent, MUIM_DrawBackground, x1, y1, width, 1, x1, y1, 0);
211 DoMethod(parent, MUIM_DrawBackground, x2, y1, 1, height, x2, y1, 0);
212 DoMethod(parent, MUIM_DrawBackground, x1, y2, width, 1, x1, y2, 0);
213 DoMethod(parent, MUIM_DrawBackground, x1, y1, 1, height, x1, y1, 0);
215 else
217 struct Region *region;
218 struct Rectangle rect;
219 APTR clip = NULL;
221 region = NewRegion();
222 if (region)
224 rect.MinX = _left(obj);
225 rect.MinY = _top(obj);
226 rect.MaxX = _right(obj);
227 rect.MaxY = _top(obj);
229 OrRectRegion(region, &rect);
231 rect.MinX = _right(obj);
232 rect.MinY = _top(obj);
233 rect.MaxX = _right(obj);
234 rect.MaxY = _bottom(obj);
236 OrRectRegion(region, &rect);
238 rect.MinX = _left(obj);
239 rect.MinY = _bottom(obj);
240 rect.MaxX = _right(obj);
241 rect.MaxY = _bottom(obj);
243 OrRectRegion(region, &rect);
245 rect.MinX = _left(obj);
246 rect.MinY = _top(obj);
247 rect.MaxX = _left(obj);
248 rect.MaxY = _bottom(obj);
250 OrRectRegion(region, &rect);
252 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
256 MUI_Redraw(obj, MADF_DRAWOBJECT);
258 if (region)
260 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
266 /**************************************************************************
267 OM_NEW
268 **************************************************************************/
269 static IPTR Area__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
271 struct MUI_AreaData *data;
272 struct TagItem *tags, *tag;
274 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
275 if (!obj)
276 return FALSE;
278 /* Initial local instance data */
279 data = INST_DATA(cl, obj);
281 data->mad_Flags =
282 MADF_FILLAREA | MADF_SHOWME | MADF_SHOWSELSTATE | MADF_DROPABLE;
283 data->mad_HorizWeight = data->mad_VertWeight = 100;
284 data->mad_InputMode = MUIV_InputMode_None;
286 /* parse initial taglist */
288 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
290 switch (tag->ti_Tag)
292 case MUIA_Background:
294 data->mad_Flags |= MADF_OWNBG;
295 if (data->mad_BackgroundSpec)
297 zune_image_spec_free(data->mad_BackgroundSpec);
299 data->mad_BackgroundSpec =
300 zune_image_spec_duplicate(tag->ti_Data);
302 break;
304 case MUIA_ControlChar:
305 data->mad_ControlChar = tag->ti_Data;
306 break;
308 case MUIA_CycleChain:
309 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
310 MADF_CYCLECHAIN);
311 break;
313 case MUIA_Disabled:
314 case MUIA_NestedDisabled:
315 if (tag->ti_Data)
317 data->mad_DisableCount = 1;
319 break;
321 case MUIA_FillArea:
322 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_FILLAREA);
323 break;
325 case MUIA_Draggable:
326 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DRAGGABLE);
327 break;
329 case MUIA_Dropable:
330 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DROPABLE);
331 break;
333 case MUIA_FixHeight:
334 data->mad_Flags |= MADF_FIXHEIGHT;
335 data->mad_HardHeight = tag->ti_Data;
336 break;
338 case MUIA_FixHeightTxt:
339 data->mad_HardHeightTxt = (STRPTR) tag->ti_Data;
340 break;
342 case MUIA_FixWidth:
343 data->mad_Flags |= MADF_FIXWIDTH;
344 data->mad_HardWidth = tag->ti_Data;
345 break;
347 case MUIA_FixWidthTxt:
348 data->mad_HardWidthTxt = (STRPTR) tag->ti_Data;
349 break;
351 case MUIA_Font:
352 data->mad_FontPreset = tag->ti_Data;
353 break;
355 case MUIA_Frame:
356 data->mad_Frame = tag->ti_Data;
357 break;
359 case MUIA_FramePhantomHoriz:
360 data->mad_Flags |= MADF_FRAMEPHANTOM;
361 break;
363 case MUIA_FrameTitle:
364 data->mad_FrameTitle = (STRPTR) tag->ti_Data;
365 break;
367 case MUIA_HorizWeight:
368 data->mad_HorizWeight = tag->ti_Data;
369 break;
371 case MUIA_InnerBottom:
372 data->mad_Flags |= MADF_INNERBOTTOM;
373 data->mad_InnerBottom = CLAMP((IPTR) tag->ti_Data, 0, 32);
374 break;
376 case MUIA_InnerLeft:
377 data->mad_Flags |= MADF_INNERLEFT;
378 data->mad_InnerLeft = CLAMP((IPTR) tag->ti_Data, 0, 32);
379 break;
381 case MUIA_InnerRight:
382 data->mad_Flags |= MADF_INNERRIGHT;
383 data->mad_InnerRight = CLAMP((IPTR) tag->ti_Data, 0, 32);
384 break;
386 case MUIA_InnerTop:
387 data->mad_Flags |= MADF_INNERTOP;
388 data->mad_InnerTop = CLAMP((IPTR) tag->ti_Data, 0, 32);
389 break;
391 case MUIA_InputMode:
392 data->mad_InputMode = tag->ti_Data;
393 break;
395 case MUIA_MaxHeight:
396 data->mad_Flags |= MADF_MAXHEIGHT;
397 data->mad_HardHeight = tag->ti_Data;
398 break;
400 case MUIA_MaxWidth:
401 data->mad_Flags |= MADF_MAXWIDTH;
402 data->mad_HardWidth = tag->ti_Data;
403 break;
405 case MUIA_Selected:
406 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_SELECTED);
407 break;
409 case MUIA_ShortHelp:
410 data->mad_ShortHelp = (STRPTR) tag->ti_Data;
411 break;
413 case MUIA_ShowMe:
414 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_SHOWME);
415 break;
417 case MUIA_ShowSelState:
418 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
419 MADF_SHOWSELSTATE);
420 break;
422 case MUIA_VertWeight:
423 data->mad_VertWeight = tag->ti_Data;
424 break;
426 case MUIA_Weight:
427 data->mad_HorizWeight = data->mad_VertWeight = tag->ti_Data;
428 break;
430 case MUIA_ContextMenu:
431 data->mad_ContextMenu = (Object *) tag->ti_Data;
432 break;
436 /* In Soliton MUIA_Selected was set to MUIV_InputMode_RelVerify (=1)
437 ** for MUIA_Input_Mode MUIV_InputMode_RelVerify which is wrong of
438 ** course but MUI seems to filter this out so we have to do it also
440 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
442 if (data->mad_Flags & MADF_SELECTED)
443 D(bug("MUIA_Selected was set in OM_NEW, "
444 "although being in MUIV_InputMode_RelVerify\n"));
445 data->mad_Flags &= ~MADF_SELECTED;
448 data->mad_ehn.ehn_Events = 0; /* Will be filled on demand */
449 data->mad_ehn.ehn_Priority = -5;
451 /* Please also send mui key events to us, no idea if mui handles this
452 * like this */
453 data->mad_ehn.ehn_Flags = MUI_EHF_ALWAYSKEYS;
454 data->mad_ehn.ehn_Object = obj;
455 data->mad_ehn.ehn_Class = cl;
457 data->mad_hiehn.ehn_Events = 0;
458 data->mad_hiehn.ehn_Priority = -10;
459 data->mad_hiehn.ehn_Flags = MUI_EHF_HANDLEINPUT;
460 data->mad_hiehn.ehn_Object = obj;
461 data->mad_hiehn.ehn_Class = 0;
463 return (IPTR) obj;
466 /**************************************************************************
467 OM_DISPOSE
468 **************************************************************************/
469 static IPTR Area__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
471 struct MUI_AreaData *data = INST_DATA(cl, obj);
473 /* Safe to call this with NULL */
474 zune_image_spec_free(data->mad_BackgroundSpec);
476 return DoSuperMethodA(cl, obj, msg);
480 /**************************************************************************
481 OM_SET
482 **************************************************************************/
483 static IPTR Area__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
485 struct MUI_AreaData *data = INST_DATA(cl, obj);
486 struct TagItem *tags = msg->ops_AttrList;
487 struct TagItem *tag;
488 CONST_STRPTR old_backgroundspec;
490 int change_disable = 0; /* Has the disable state changed? */
492 while ((tag = NextTagItem(&tags)) != NULL)
494 switch (tag->ti_Tag)
496 case MUIA_Background:
497 old_backgroundspec = data->mad_BackgroundSpec;
498 data->mad_BackgroundSpec =
499 zune_image_spec_duplicate(tag->ti_Data);
500 if (!data->mad_BackgroundSpec)
502 /* Out of memory */
503 data->mad_BackgroundSpec = old_backgroundspec;
504 break;
507 data->mad_Flags |= MADF_OWNBG;
509 if (old_backgroundspec
510 && (strcmp(data->mad_BackgroundSpec,
511 old_backgroundspec) == 0))
513 /* New background does not differ from old one */
514 zune_image_spec_free(old_backgroundspec);
515 tag->ti_Tag = TAG_IGNORE;
516 break;
519 zune_image_spec_free(old_backgroundspec);
521 if (data->mad_Background)
523 if (_flags(obj) & MADF_CANDRAW)
525 zune_imspec_hide(data->mad_Background);
527 if (_flags(obj) & MADF_SETUP)
529 zune_imspec_cleanup(data->mad_Background);
530 data->mad_Background = NULL;
534 if (_flags(obj) & MADF_SETUP)
536 data->mad_Background =
537 zune_imspec_setup((IPTR) data->mad_BackgroundSpec,
538 muiRenderInfo(obj));
540 if (_flags(obj) & MADF_CANDRAW)
542 zune_imspec_show(data->mad_Background, obj);
544 MUI_Redraw(obj, MADF_DRAWOBJECT);
545 break;
547 case MUIA_FillArea:
548 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_FILLAREA);
549 break;
551 case MUIA_Frame:
552 /* this is not documented in MUI but it is possible,
553 and needed to suppress frame for external images */
554 data->mad_Frame = tag->ti_Data;
555 if (muiGlobalInfo(obj))
557 set_inner_sizes(obj, data);
558 set_title_sizes(obj, data);
560 break;
562 case MUIA_ControlChar:
563 if (_flags(obj) & MADF_SETUP)
564 cleanup_control_char(data, obj);
565 data->mad_ControlChar = tag->ti_Data;
566 if (_flags(obj) & MADF_SETUP)
567 setup_control_char(data, obj, cl);
568 break;
570 case MUIA_CycleChain:
571 // if (data->mad_InputMode == MUIV_InputMode_None)
572 // break;
574 if ((!(_flags(obj) & MADF_CYCLECHAIN) && tag->ti_Data)
575 || ((_flags(obj) & MADF_CYCLECHAIN) && !tag->ti_Data))
577 if (_flags(obj) & MADF_SETUP)
579 cleanup_control_char(data, obj);
580 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
581 MADF_CYCLECHAIN);
582 setup_control_char(data, obj, cl);
584 else
585 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
586 MADF_CYCLECHAIN);
588 break;
590 case MUIA_Disabled:
591 if (tag->ti_Data)
593 if (!data->mad_DisableCount)
595 data->mad_DisableCount = 1;
596 change_disable = 1;
599 else
601 if (data->mad_DisableCount)
603 data->mad_DisableCount = 0;
604 change_disable = 1;
607 break;
609 case MUIA_NestedDisabled:
610 if (tag->ti_Data)
612 if (!data->mad_DisableCount)
613 change_disable = 1;
614 data->mad_DisableCount++;
616 else
618 if (data->mad_DisableCount)
620 data->mad_DisableCount--;
621 if (!data->mad_DisableCount)
622 change_disable = 1;
625 break;
628 case MUIA_HorizWeight:
629 data->mad_HorizWeight = tag->ti_Data;
630 break;
632 case MUIA_Pressed:
633 if (tag->ti_Data)
634 data->mad_Flags |= MADF_PRESSED;
635 else
636 data->mad_Flags &= ~MADF_PRESSED;
637 break;
639 case MUIA_ShortHelp:
640 data->mad_ShortHelp = (STRPTR) tag->ti_Data;
641 break;
643 case MUIA_ShowMe:
645 ULONG oldflags = data->mad_Flags;
646 int recalc = 0;
648 if (tag->ti_Data)
649 data->mad_Flags |= MADF_SHOWME;
650 else
651 data->mad_Flags &= ~MADF_SHOWME;
653 if (oldflags != data->mad_Flags)
655 if (!tag->ti_Data)
657 /* Should be made invisible, so send a MUIM_Hide and
658 ** then a MUIM_Cleanup to the object if needed,
659 ** as objects with MUIA_ShowMe to false get neither
660 ** MUIM_Setup nor MUIM_Show */
661 if (_flags(obj) & MADF_CANDRAW)
663 DoHideMethod(obj);
664 recalc = 1;
666 #if 0 /* SHOWME affects only show/hide */
667 if (_flags(obj) & MADF_SETUP)
668 DoMethod(obj, MUIM_Cleanup);
669 #endif
671 else
673 Object *parent = _parent(obj);
674 /* Will be NULL if direct child of a window! */
676 if (parent)
678 #if 0 /* SHOWME affects only show/hide */
679 if (_flags(parent) & MADF_SETUP)
680 DoSetupMethod(obj, muiRenderInfo(parent));
681 #endif
682 if (_flags(parent) & MADF_CANDRAW)
684 DoShowMethod(obj);
685 recalc = 1;
688 else
690 /* Check if window is open... */
694 /* If renderinfo is NULL _win(obj) doesn't work (crash) */
695 if (recalc && muiRenderInfo(obj))
697 DoMethod(_win(obj), MUIM_Window_RecalcDisplay,
698 (IPTR) _parent(obj));
702 break;
704 case MUIA_Selected:
705 /* D(bug(" Area_Set(%p) :
706 MUIA_Selected val=%ld sss=%d\n", obj, tag->ti_Data,
707 !!(data->mad_Flags & MADF_SHOWSELSTATE)));
709 if (tag->ti_Data && !(data->mad_Flags & MADF_SELECTED))
711 data->mad_Flags |= MADF_SELECTED;
712 MUI_Redraw(obj, MADF_DRAWOBJECT);
714 else if (!tag->ti_Data && (data->mad_Flags & MADF_SELECTED))
716 data->mad_Flags &= ~MADF_SELECTED;
717 MUI_Redraw(obj, MADF_DRAWOBJECT);
719 #if 0 // CHECKME: What's the purpose of this? What superclass will care?
720 else
722 tag->ti_Tag = TAG_IGNORE;
724 #endif
725 break;
727 case MUIA_Timer:
728 data->mad_Timeval = tag->ti_Data;
729 break;
731 case MUIA_VertWeight:
732 data->mad_VertWeight = tag->ti_Data;
733 break;
735 case MUIA_Draggable:
736 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DRAGGABLE);
737 break;
739 case MUIA_Dropable:
740 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DROPABLE);
741 break;
743 case MUIA_ContextMenu:
744 data->mad_ContextMenu = (Object *) tag->ti_Data;
745 break;
747 case MUIA_Font:
748 data->mad_FontPreset = tag->ti_Data;
749 break;
751 case MUIA_InputMode:
752 data->mad_InputMode = tag->ti_Data;
753 break;
758 if (change_disable)
760 /* Simulate left mouse button release if the area becomes disabled */
761 if (_flags(obj) & MADF_SETUP)
762 handle_release(cl, obj, TRUE);
763 MUI_Redraw(obj, MADF_DRAWOBJECT);
766 return DoSuperMethodA(cl, obj, (Msg) msg);
770 /**************************************************************************
771 OM_GET
772 **************************************************************************/
773 static IPTR Area__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
775 #define STORE *(msg->opg_Storage)
777 struct MUI_AreaData *data = INST_DATA(cl, obj);
779 switch (msg->opg_AttrID)
781 case MUIA_Background:
782 STORE = (IPTR) data->mad_Background;
783 return TRUE;
785 case MUIA_BottomEdge:
786 STORE = (IPTR) _bottom(obj);
787 return TRUE;
789 case MUIA_ControlChar:
790 STORE = data->mad_ControlChar;
791 return TRUE;
793 case MUIA_CycleChain:
794 STORE = ((data->mad_Flags & MADF_CYCLECHAIN) != 0);
795 return TRUE;
797 case MUIA_Disabled:
798 case MUIA_NestedDisabled:
799 STORE = ! !data->mad_DisableCount; /* BOOLEAN */
800 return TRUE;
802 case MUIA_Font:
803 STORE = (IPTR) data->mad_FontPreset;
804 return TRUE;
806 case MUIA_Height:
807 STORE = (IPTR) _height(obj);
808 return TRUE;
810 case MUIA_HorizWeight:
811 STORE = (IPTR) data->mad_HorizWeight;
812 return TRUE;
814 case MUIA_InnerBottom:
815 STORE = (IPTR) data->mad_InnerBottom;
816 return TRUE;
818 case MUIA_InnerLeft:
819 STORE = (IPTR) data->mad_InnerLeft;
820 return TRUE;
822 case MUIA_InnerRight:
823 STORE = (IPTR) data->mad_InnerRight;
824 return TRUE;
826 case MUIA_InnerTop:
827 STORE = (IPTR) data->mad_InnerTop;
828 return TRUE;
830 case MUIA_LeftEdge:
831 STORE = (IPTR) _left(obj);
832 return TRUE;
834 case MUIA_Pressed:
835 STORE = ! !(data->mad_Flags & MADF_PRESSED);
836 return TRUE;
838 case MUIA_RightEdge:
839 STORE = (IPTR) _right(obj);
840 return TRUE;
842 case MUIA_Selected:
843 STORE = ! !(data->mad_Flags & MADF_SELECTED);
844 return TRUE;
846 case MUIA_ShortHelp:
847 STORE = (IPTR) data->mad_ShortHelp;
848 return TRUE;
850 case MUIA_ShowMe:
851 STORE = ! !(data->mad_Flags & MADF_SHOWME);
852 return TRUE;
854 case MUIA_Timer:
855 STORE = data->mad_Timeval;
856 return TRUE;
858 case MUIA_TopEdge:
859 STORE = (IPTR) _top(obj);
860 return TRUE;
862 case MUIA_VertWeight:
863 STORE = (IPTR) data->mad_VertWeight;
864 return TRUE;
866 case MUIA_Width:
867 STORE = (IPTR) _width(obj);
868 return TRUE;
870 case MUIA_Window:
871 if (muiAreaData(obj)->mad_RenderInfo)
872 STORE = (IPTR) _window(obj);
873 else
874 STORE = 0L;
875 return TRUE;
877 case MUIA_WindowObject:
878 if (muiAreaData(obj)->mad_RenderInfo)
879 STORE = (IPTR) _win(obj);
880 else
881 STORE = 0L;
882 return TRUE;
884 case MUIA_ContextMenu:
885 STORE = (IPTR) data->mad_ContextMenu;
886 return TRUE;
888 case MUIA_Frame:
889 STORE = (IPTR) data->mad_Frame;
890 return TRUE;
892 case MUIA_Draggable:
893 STORE = !!(data->mad_Flags & MADF_DRAGGABLE);
894 return TRUE;
896 case MUIA_Dropable:
897 STORE = !!(data->mad_Flags & MADF_DROPABLE);
898 return TRUE;
901 return (DoSuperMethodA(cl, obj, (Msg) msg));
902 #undef STORE
906 /**************************************************************************
907 MUIM_AskMinMax
908 **************************************************************************/
909 static IPTR Area__MUIM_AskMinMax(struct IClass *cl, Object *obj,
910 struct MUIP_AskMinMax *msg)
912 struct MUI_AreaData *data = INST_DATA(cl, obj);
913 const struct ZuneFrameGfx *zframe;
914 const struct MUI_FrameSpec_intern *frame;
915 struct MUI_FrameSpec_intern tempframe;
917 frame = get_intframe(obj, data, &tempframe);
918 zframe = zune_zframe_get(obj, frame);
920 area_update_msizes(obj, data, frame, zframe);
922 msg->MinMaxInfo->MinWidth = _subwidth(obj);
923 msg->MinMaxInfo->MinHeight = _subheight(obj);
925 msg->MinMaxInfo->MaxWidth = msg->MinMaxInfo->MinWidth;
926 msg->MinMaxInfo->MaxHeight = msg->MinMaxInfo->MinHeight;
927 msg->MinMaxInfo->DefWidth = msg->MinMaxInfo->MinWidth;
928 msg->MinMaxInfo->DefHeight = msg->MinMaxInfo->MinHeight;
930 /* D(bug("Area_AskMinMax 0x%lx (%s): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n",
931 obj, data->mad_FrameTitle, */
932 /* msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight, */
933 /* msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight, */
934 /* msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight)); */
936 return TRUE;
940 * Called after MUIM_AskMinMax, to handle fixed and max sizes.
942 void __area_finish_minmax(Object *obj, struct MUI_MinMax *MinMaxInfo)
944 struct MUI_AreaData *data = muiAreaData(obj);
946 if ((_flags(obj) & MADF_FIXHEIGHT) && (data->mad_HardHeight > 0))
948 int h = data->mad_HardHeight + data->mad_subheight;
950 MinMaxInfo->MinHeight =
951 MinMaxInfo->DefHeight =
952 MinMaxInfo->MaxHeight =
953 CLAMP(h, MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
955 else if (data->mad_HardHeightTxt)
957 ZText *text;
959 if ((text =
960 zune_text_new(NULL, data->mad_HardHeightTxt, ZTEXT_ARG_NONE,
961 0)))
963 zune_text_get_bounds(text, obj);
965 MinMaxInfo->MinHeight =
966 MinMaxInfo->DefHeight =
967 MinMaxInfo->MaxHeight =
968 CLAMP(text->height + data->mad_subheight,
969 MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
971 zune_text_destroy(text);
975 else if (_flags(obj) & MADF_MAXHEIGHT)
977 MinMaxInfo->MaxHeight =
978 CLAMP(data->mad_HardHeight + data->mad_subheight,
979 MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
982 if ((_flags(obj) & MADF_FIXWIDTH) && (data->mad_HardWidth > 0))
984 int w = data->mad_HardWidth + data->mad_subwidth;
986 MinMaxInfo->MinWidth =
987 MinMaxInfo->DefWidth =
988 MinMaxInfo->MaxWidth =
989 CLAMP(w, MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
991 else if (data->mad_HardWidthTxt)
993 ZText *text;
995 if ((text =
996 zune_text_new(NULL, data->mad_HardWidthTxt, ZTEXT_ARG_NONE,
997 0)))
999 zune_text_get_bounds(text, obj);
1001 MinMaxInfo->MinWidth =
1002 MinMaxInfo->DefWidth =
1003 MinMaxInfo->MaxWidth =
1004 CLAMP(text->width + data->mad_subwidth,
1005 MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
1007 zune_text_destroy(text);
1011 else if (_flags(obj) & MADF_MAXWIDTH)
1013 MinMaxInfo->MaxWidth =
1014 CLAMP(data->mad_HardWidth + data->mad_subwidth,
1015 MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
1018 /* Set minmax */
1019 _minwidth(obj) = MinMaxInfo->MinWidth;
1020 _minheight(obj) = MinMaxInfo->MinHeight;
1021 _maxwidth(obj) = MinMaxInfo->MaxWidth;
1022 _maxheight(obj) = MinMaxInfo->MaxHeight;
1023 _defwidth(obj) = MinMaxInfo->DefWidth;
1024 _defheight(obj) = MinMaxInfo->DefHeight;
1027 /* <-- _top(obj) (frame title position depends of _top(obj))
1028 * ==== Title === <-- frame_top (depends of title, if centered/above)
1029 * | | <-- bgtop (depends of frame, bg always begins under frame)
1030 * | |
1031 * | |
1032 * ============== <-- "bgbottom" and "frame_bottom" (frame overwrites bg (1))
1034 * (1) : needed for phantom frame objects, where no frame overwrites bg, thus bg
1035 * must go as far as theoretical bottom frame border.
1039 * draw object background if MADF_FILLAREA.
1041 static void Area_Draw_handle_background(Object *obj,
1042 struct MUI_AreaData *data, ULONG flags,
1043 const struct ZuneFrameGfx *zframe)
1045 struct MUI_ImageSpec_intern *background;
1046 struct Rectangle r, r2, rects[4];
1047 int i, bgtop, bgleft, bgw, bgh, numrects;
1049 if (!(data->mad_Flags & MADF_SELECTED)
1050 || !(data->mad_Flags & MADF_SHOWSELSTATE))
1051 background = data->mad_Background;
1052 else
1053 background = data->mad_SelBack;
1055 if (zframe->customframe)
1057 bgtop = _top(obj) + data->mad_TitleHeightAbove;
1059 else
1061 bgtop = _top(obj) + data->mad_TitleHeightAbove + zframe->itop;
1064 bgleft = _left(obj);
1065 bgw = _width(obj);
1066 bgh = _height(obj) - bgtop + _top(obj);
1068 r.MinX = bgleft;
1069 r.MinY = bgtop;
1070 r.MaxX = bgleft + bgw - 1;
1071 r.MaxY = bgtop + bgh - 1;
1073 if (data->mad_Flags & MADF_FILLAREA)
1075 rects[0] = r;
1076 numrects = 1;
1078 else
1080 /* MADF_FILLAREA not set. Only draw frame outside of
1081 innerbox (_mleft, _mtop, _mright, _mbottom):
1083 .............
1084 .***********.
1085 .*#########*.
1086 .*#########*.
1087 .***********.
1088 .............
1090 # = innerbox
1091 * = frame outside of innerbox
1092 . = object frame
1095 r2.MinX = _mleft(obj);
1096 r2.MinY = _mtop(obj);
1097 r2.MaxX = _mright(obj);
1098 r2.MaxY = _mbottom(obj);
1100 numrects = SubtractRectFromRect(&r, &r2, rects);
1103 for (i = 0; i < numrects; i++)
1105 if (!background)
1107 /* This will do the rest, TODO: on MADF_DRAWALL we not really
1108 * need to draw this */
1109 /* D(bug(" Area_Draw(%p):%ld: MUIM_DrawBackground\n", obj,
1110 __LINE__)); */
1111 /* ATTENTION: This draws the clipped away regions of the area.
1112 * Comment out and check the result to see what I mean. */
1113 DoMethod(obj, MUIM_DrawBackground,
1114 rects[i].MinX, rects[i].MinY,
1115 rects[i].MaxX - rects[i].MinX + 1,
1116 rects[i].MaxY - rects[i].MinY + 1, rects[i].MinX,
1117 rects[i].MinY, data->mad_Flags);
1119 else
1121 /* D(bug(" Area_Draw(%p):%ld: zune_imspec_draw\n", obj,
1122 __LINE__)); */
1123 zune_imspec_draw(background, data->mad_RenderInfo,
1124 rects[i].MinX, rects[i].MinY,
1125 rects[i].MaxX - rects[i].MinX + 1,
1126 rects[i].MaxY - rects[i].MinY + 1, rects[i].MinX,
1127 rects[i].MinY, 0);
1131 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
1132 WINDOW_REDRAW_WITHOUT_CLEAR)
1134 if (bgtop > _top(obj) && !(flags & MADF_DRAWALL))
1136 /* Fill in the gap produced by the title with the background
1137 * of the parent object but only if
1138 * the upper object hasn't drawn it already
1139 * (which is the case if MADF_DRAWALL is setted) */
1140 DoMethod(obj, MUIM_DrawParentBackground, bgleft, _top(obj), bgw,
1141 bgtop - _top(obj), bgleft, _top(obj), data->mad_Flags);
1148 * draw object frame + title if not MADF_FRAMEPHANTOM.
1150 static void Area_Draw_handle_frame(Object *obj, struct MUI_AreaData *data,
1151 const struct ZuneFrameGfx *zframe)
1153 APTR textdrawclip = (APTR) - 1;
1154 struct Region *region;
1155 int tx;
1156 int tw, frame_height, frame_top;
1157 int addtw;
1158 struct TextExtent te;
1159 int nchars;
1160 int maxtxtwidth;
1162 /* no frametitle, just draw frame and return */
1163 if (!data->mad_FrameTitle)
1165 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1166 _top(obj), _width(obj), _height(obj), _left(obj), _top(obj),
1167 _width(obj), _height(obj));
1168 return;
1171 /* set clipping so that frame is not drawn behind title */
1173 switch (muiGlobalInfo(obj)->mgi_Prefs->group_title_color)
1175 case GROUP_TITLE_COLOR_OUTLINE:
1176 addtw = 2;
1177 break;
1178 case GROUP_TITLE_COLOR_3D:
1179 addtw = 1;
1180 break;
1181 default:
1182 addtw = 0;
1185 maxtxtwidth =
1186 _width(obj) - zframe->ileft - zframe->iright - 2 * 5 - addtw;
1188 nchars = TextFit(_rp(obj), data->mad_FrameTitle,
1189 strlen(data->mad_FrameTitle),
1190 &te, NULL, 1, maxtxtwidth, _font(obj)->tf_YSize);
1192 tw = te.te_Width + addtw;
1193 tx = _left(obj) + (_width(obj) - tw) / 2;
1195 frame_top = _top(obj) + data->mad_TitleHeightAbove;
1196 frame_height = _height(obj) - frame_top + _top(obj);
1198 if ((region = NewRegion()))
1200 struct Rectangle rect;
1201 int hspace = _font(obj)->tf_YSize / 8;
1203 rect.MinX = tx - hspace;
1204 rect.MinY = _top(obj);
1205 rect.MaxX = tx + tw - 1 + hspace;
1206 rect.MaxY = _top(obj) + _font(obj)->tf_YSize - 1;
1207 // frame is not thick enough anyway
1208 OrRectRegion(region, &rect);
1210 rect.MinX = _left(obj);
1211 rect.MinY = _top(obj);
1212 rect.MaxX = _right(obj);
1213 rect.MaxY = _bottom(obj);
1214 XorRectRegion(region, &rect);
1216 textdrawclip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1219 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1220 frame_top, _width(obj), frame_height, _left(obj), frame_top,
1221 _width(obj), frame_height);
1223 if (region && textdrawclip != (APTR) - 1)
1225 MUI_RemoveClipRegion(muiRenderInfo(obj), textdrawclip);
1226 /* DisposeRegion(region);*/ /* sba: DisposeRegion happens in MUI_RemoveClipRegion, this seems wrong to me */
1229 /* Title text drawing */
1230 SetDrMd(_rp(obj), JAM1);
1231 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
1232 if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1233 GROUP_TITLE_COLOR_3D)
1235 Move(_rp(obj), tx + 1, _top(obj) + _font(obj)->tf_Baseline + 1);
1236 Text(_rp(obj), data->mad_FrameTitle, nchars);
1237 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1238 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1239 Text(_rp(obj), data->mad_FrameTitle, nchars);
1241 else if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1242 GROUP_TITLE_COLOR_OUTLINE)
1244 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1246 tx += addtw / 2;
1247 Move(_rp(obj), tx + 1, _top(obj) + _font(obj)->tf_Baseline);
1248 Text(_rp(obj), data->mad_FrameTitle, nchars);
1249 Move(_rp(obj), tx - 1, _top(obj) + _font(obj)->tf_Baseline);
1250 Text(_rp(obj), data->mad_FrameTitle, nchars);
1251 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline + 1);
1252 Text(_rp(obj), data->mad_FrameTitle, nchars);
1253 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline - 1);
1254 Text(_rp(obj), data->mad_FrameTitle, nchars);
1256 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
1257 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1258 Text(_rp(obj), data->mad_FrameTitle, nchars);
1260 else
1262 if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1263 GROUP_TITLE_COLOR_HILITE)
1265 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1267 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1268 Text(_rp(obj), data->mad_FrameTitle, nchars);
1272 /**************************************************************************
1273 MUIM_Draw
1274 **************************************************************************/
1275 static IPTR Area__MUIM_Draw(struct IClass *cl, Object *obj,
1276 struct MUIP_Draw *msg)
1278 struct MUI_AreaData *data = INST_DATA(cl, obj);
1279 const struct ZuneFrameGfx *zframe;
1280 struct TextFont *obj_font = NULL;
1281 ULONG flags = data->mad_Flags & MADF_DRAWFLAGS;
1283 //APTR areaclip;
1285 /* D(bug("Area_Draw(0x%lx) %ldx%ldx%ldx%ld\n", obj, _left(obj),
1286 _top(obj),_right(obj),_bottom(obj))); */
1287 /* D(bug(" Area_Draw(%p) msg=0x%08lx flags=0x%08lx\n", obj, msg->flags,
1288 _flags(obj))); */
1290 if (flags & MADF_DRAWALL)
1291 flags |= MADF_DRAWOBJECT;
1293 msg->flags = flags;
1294 data->mad_Flags &= ~MADF_DRAWFLAGS;
1296 if (!(flags & MADF_DRAWOBJECT))
1298 /* dont draw bg/frame, let subclass redraw content only
1300 return 0;
1304 /* Background can't be drawn without knowing anything about frame, thus some
1305 * calculations are made before background and frame drawing.
1308 /* on selected state, will get the opposite frame */
1309 const struct MUI_FrameSpec_intern *frame;
1310 struct MUI_FrameSpec_intern tempframe;
1311 int state;
1313 frame = get_intframe(obj, data, &tempframe);
1314 state = frame->state;
1315 if ((data->mad_Flags & MADF_SELECTED)
1316 && (data->mad_Flags & MADF_SHOWSELSTATE))
1317 state ^= 1;
1319 zframe = zune_zframe_get_with_state(obj, frame, state);
1321 /* update innersizes as there are frames which have different inner
1322 * spacings in selected state */
1323 area_update_msizes(obj, data, frame, zframe);
1326 /* Background drawing */
1327 Area_Draw_handle_background(obj, data, msg->flags, zframe);
1329 obj_font = _font(obj);
1330 _font(obj) = zune_font_get(obj, MUIV_Font_Title);
1331 SetFont(_rp(obj), _font(obj));
1333 /* Frame and frametitle drawing */
1334 if (!(data->mad_Flags & MADF_FRAMEPHANTOM))
1336 Area_Draw_handle_frame(obj, data, zframe);
1339 _font(obj) = obj_font;
1340 SetFont(_rp(obj), _font(obj));
1342 /* MUI_RemoveClipping(muiRenderInfo(obj), areaclip);*/
1344 return TRUE;
1347 /**************************************************************************
1348 MUIM_DrawParentBackground
1349 **************************************************************************/
1350 static IPTR Area__MUIM_DrawParentBackground(struct IClass *cl, Object *obj,
1351 struct MUIP_DrawParentBackground *msg)
1353 struct MUI_AreaData *data = INST_DATA(cl, obj);
1354 Object *parent = NULL;
1356 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1357 return FALSE;
1359 get(obj, MUIA_Parent, &parent);
1360 if (parent)
1362 DoMethod(parent, MUIM_DrawBackground, msg->left, msg->top,
1363 msg->width, msg->height, msg->xoffset, msg->yoffset,
1364 msg->flags);
1366 else
1368 D(bug
1369 ("Area_DrawParentBackground(%p) : MUIM_Window_DrawBackground\n",
1370 obj));
1371 DoMethod(_win(obj), MUIM_Window_DrawBackground, msg->left, msg->top,
1372 msg->width, msg->height, msg->xoffset, msg->yoffset,
1373 msg->flags);
1375 return TRUE;
1378 /**************************************************************************
1379 MUIM_DrawBackground
1380 **************************************************************************/
1381 static IPTR Area__MUIM_DrawBackground(struct IClass *cl, Object *obj,
1382 struct MUIP_DrawBackground *msg)
1384 struct MUI_AreaData *data = INST_DATA(cl, obj);
1385 struct MUI_ImageSpec_intern *bg;
1386 LONG state;
1388 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1389 return FALSE;
1391 if ((msg->flags & MADF_SELECTED) && (msg->flags & MADF_SHOWSELSTATE)
1392 && data->mad_SelBack)
1394 /* D(bug("Area_DrawBackground(%p): selected bg\n", obj)); */
1395 bg = data->mad_SelBack;
1396 state = IDS_SELECTED;
1398 else
1400 /* D(bug("Area_DrawBackground(%p): normal bg\n", obj)); */
1401 bg = data->mad_Background;
1402 state = IDS_NORMAL;
1405 const struct ZuneFrameGfx *zframe;
1406 const struct MUI_FrameSpec_intern *frame;
1407 struct MUI_FrameSpec_intern tempframe;
1409 if (!bg)
1411 D(bug("Area_DrawBackground(%p) : MUIM_DrawParentBackground\n",
1412 obj));
1414 return DoMethod(obj, MUIM_DrawParentBackground, msg->left, msg->top,
1415 msg->width, msg->height, msg->xoffset, msg->yoffset,
1416 msg->flags);
1419 frame = get_intframe(obj, data, &tempframe);
1421 int xstate = frame->state;
1422 if ((data->mad_Flags & MADF_SELECTED)
1423 && (data->mad_Flags & MADF_SHOWSELSTATE))
1424 xstate ^= 1;
1426 zframe = zune_zframe_get_with_state(obj, frame, xstate);
1428 if (zframe->customframe == NULL)
1430 /* D(bug("Area_DrawBackground(%p): draw bg\n", obj)); */
1431 zune_imspec_draw(bg, data->mad_RenderInfo,
1432 msg->left, msg->top, msg->width, msg->height,
1433 msg->xoffset, msg->yoffset, state);
1435 // if (!data->mad_FrameTitle)
1436 // {
1439 else
1441 if (zframe->noalpha == FALSE)
1443 zune_imspec_draw(bg, data->mad_RenderInfo,
1444 msg->left, msg->top, msg->width, msg->height,
1445 msg->xoffset, msg->yoffset, state);
1450 if (zframe->customframe)
1452 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1453 _top(obj), _width(obj), _height(obj), msg->left, msg->top,
1454 msg->width, msg->height);
1457 return TRUE;
1460 static IPTR Area__MUIM_DrawBackgroundBuffered(struct IClass *cl,
1461 Object *obj, struct MUIP_DrawBackgroundBuffered *msg)
1463 struct MUI_AreaData *data = INST_DATA(cl, obj);
1464 struct MUI_ImageSpec_intern *bg;
1465 LONG state = 0;
1467 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1468 return FALSE;
1470 bg = data->mad_Background;
1472 /* D(bug("Area_DrawBackground(%p): draw bg\n", obj)); */
1473 zune_imspec_drawbuffered(bg, msg->rp, data->mad_RenderInfo,
1474 msg->left, msg->top, msg->width, msg->height,
1475 msg->xoffset + msg->left, msg->yoffset + msg->top, state, msg->left,
1476 msg->top, 1, _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj));
1478 return TRUE;
1481 /* Perverting the EventHandlerNode structure to specify a shortcut.
1483 static void setup_control_char(struct MUI_AreaData *data, Object *obj,
1484 struct IClass *cl)
1486 if (data->mad_ControlChar != 0 || data->mad_Flags & MADF_CYCLECHAIN)
1488 data->mad_ccn.ehn_Events = data->mad_ControlChar;
1489 switch (data->mad_InputMode)
1491 case MUIV_InputMode_RelVerify:
1492 data->mad_ccn.ehn_Flags = MUIKEY_PRESS;
1493 break;
1494 case MUIV_InputMode_Toggle:
1495 data->mad_ccn.ehn_Flags = MUIKEY_TOGGLE;
1496 break;
1497 case MUIV_InputMode_Immediate:
1498 data->mad_ccn.ehn_Flags = MUIKEY_PRESS;
1499 break;
1501 data->mad_ccn.ehn_Priority = 0;
1502 data->mad_ccn.ehn_Object = obj;
1503 data->mad_ccn.ehn_Class = cl;
1504 DoMethod(_win(obj), MUIM_Window_AddControlCharHandler,
1505 (IPTR) & data->mad_ccn);
1510 static void cleanup_control_char(struct MUI_AreaData *data, Object *obj)
1512 if (data->mad_ControlChar != 0 || data->mad_Flags & MADF_CYCLECHAIN)
1514 DoMethod(_win(obj),
1515 MUIM_Window_RemControlCharHandler, (IPTR) & data->mad_ccn);
1519 static const struct MUI_FrameSpec_intern *get_intframe(Object *obj,
1520 struct MUI_AreaData *data, struct MUI_FrameSpec_intern *tempstore)
1522 if (data->mad_Frame > 100)
1524 /* Frame is spec in string format. Store it in tempstore and return
1525 a pointer to it. The caller should have such a temp variable on
1526 the stack. Don't want to add it to MUI_AreaData as that will
1527 increase mem usage of every object. */
1529 if (zune_frame_spec_to_intern((CONST_STRPTR) data->mad_Frame,
1530 tempstore))
1532 return tempstore;
1534 else
1536 return &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_None];
1539 else
1541 /* Frame is MUIV_Frame_<something> */
1542 return &muiGlobalInfo(obj)->mgi_Prefs->frames[data->mad_Frame];
1546 static void set_inner_sizes(Object *obj, struct MUI_AreaData *data)
1548 const struct MUI_FrameSpec_intern *frame;
1549 struct MUI_FrameSpec_intern tempframe;
1551 frame = get_intframe(obj, data, &tempframe);
1552 // Use frame inner spacing when not hardcoded
1553 if (!(data->mad_Flags & MADF_INNERLEFT))
1554 data->mad_InnerLeft = frame->innerLeft;
1555 if (!(data->mad_Flags & MADF_INNERTOP))
1556 data->mad_InnerTop = frame->innerTop;
1557 if (!(data->mad_Flags & MADF_INNERRIGHT))
1558 data->mad_InnerRight = frame->innerRight;
1559 if (!(data->mad_Flags & MADF_INNERBOTTOM))
1560 data->mad_InnerBottom = frame->innerBottom;
1564 static void set_title_sizes(Object *obj, struct MUI_AreaData *data)
1566 if (data->mad_FrameTitle)
1568 const struct ZuneFrameGfx *zframe;
1569 const struct MUI_FrameSpec_intern *frame;
1570 struct MUI_FrameSpec_intern tempframe;
1572 frame = get_intframe(obj, data, &tempframe);
1573 zframe = zune_zframe_get(obj, frame);
1575 _font(obj) = zune_font_get(obj, MUIV_Font_Title);
1577 switch (muiGlobalInfo(obj)->mgi_Prefs->group_title_position)
1579 case GROUP_TITLE_POSITION_ABOVE:
1580 data->mad_TitleHeightAbove = _font(obj)->tf_Baseline;
1581 break;
1582 case GROUP_TITLE_POSITION_CENTERED:
1583 data->mad_TitleHeightAbove = _font(obj)->tf_YSize / 2;
1584 break;
1587 data->mad_TitleHeightAdd =
1588 _font(obj)->tf_YSize - data->mad_InnerTop - zframe->itop;
1589 data->mad_TitleHeightBelow =
1590 data->mad_TitleHeightAdd - data->mad_TitleHeightAbove;
1595 /**************************************************************************
1596 First method to be called after an OM_NEW, it is the place
1597 for all initializations depending on the environment, but not
1598 on the gadget size/position. Matched by MUIM_Cleanup.
1599 **************************************************************************/
1600 static IPTR Area__MUIM_Setup(struct IClass *cl, Object *obj,
1601 struct MUIP_Setup *msg)
1603 struct MUI_AreaData *data = INST_DATA(cl, obj);
1604 const struct ZuneFrameGfx *zframe;
1605 const struct MUI_FrameSpec_intern *frame;
1606 struct MUI_FrameSpec_intern tempframe;
1608 muiRenderInfo(obj) = msg->RenderInfo;
1610 if (data->mad_Frame)
1612 /* no frame allowed for root object (see Area.doc) */
1613 Object *rootobj = NULL;
1614 get(_win(obj), MUIA_Window_RootObject, &rootobj);
1615 if (rootobj == obj)
1617 data->mad_Frame = MUIV_Frame_None;
1618 data->mad_FrameTitle = NULL;
1622 set_inner_sizes(obj, data);
1623 set_title_sizes(obj, data);
1625 frame = get_intframe(obj, data, &tempframe);
1626 zframe = zune_zframe_get(obj, frame);
1628 area_update_msizes(obj, data, frame, zframe);
1630 if (data->mad_Flags & MADF_OWNBG)
1632 data->mad_Background =
1633 zune_imspec_setup((IPTR) data->mad_BackgroundSpec,
1634 muiRenderInfo(obj));
1637 if ((data->mad_Flags & MADF_SHOWSELSTATE) &&
1638 (data->mad_InputMode != MUIV_InputMode_None))
1640 data->mad_SelBack =
1641 zune_imspec_setup(MUII_SelectedBack, muiRenderInfo(obj));
1644 if (data->mad_InputMode != MUIV_InputMode_None || data->mad_ContextMenu)
1646 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1647 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1648 (IPTR) & data->mad_ehn);
1651 /* Those are filled by RequestIDCMP() */
1652 if (data->mad_hiehn.ehn_Events)
1653 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1654 (IPTR) & data->mad_hiehn);
1656 setup_control_char(data, obj, cl);
1657 // setup_cycle_chain (data, obj);
1659 if (data->mad_FontPreset == MUIV_Font_Inherit)
1661 if (_parent(obj) != NULL && _parent(obj) != _win(obj))
1662 data->mad_Font = _font(_parent(obj));
1663 else
1665 D(bug("Area_Setup %p: getting normal font\n", obj));
1666 data->mad_Font = zune_font_get(obj, MUIV_Font_Normal);
1667 D(bug("Area_Setup %p: got normal font %p\n", obj,
1668 data->mad_Font));
1671 else
1673 data->mad_Font = zune_font_get(obj, data->mad_FontPreset);
1676 _flags(obj) |= MADF_SETUP;
1678 data->mad_Timer.ihn_Flags = MUIIHNF_TIMER;
1679 data->mad_Timer.ihn_Method = MUIM_Timer;
1680 data->mad_Timer.ihn_Object = obj;
1682 return TRUE;
1686 /**************************************************************************
1687 Called to match a MUIM_Setup, when environment is no longer available.
1688 **************************************************************************/
1689 static IPTR Area__MUIM_Cleanup(struct IClass *cl, Object *obj,
1690 struct MUIP_Cleanup *msg)
1692 struct MUI_AreaData *data = INST_DATA(cl, obj);
1694 _flags(obj) &= ~MADF_SETUP;
1696 // cleanup_cycle_chain (data, obj);
1697 cleanup_control_char(data, obj);
1699 if (data->mad_Timer.ihn_Millis)
1701 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
1702 (IPTR) & data->mad_Timer);
1703 data->mad_Timer.ihn_Millis = 0;
1706 /* Remove the handler if it is added */
1707 if (data->mad_hiehn.ehn_Events)
1708 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1709 (IPTR) & data->mad_hiehn);
1711 /* Remove the event handler if it has been added */
1712 if (data->mad_ehn.ehn_Events)
1713 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1714 (IPTR) & data->mad_ehn);
1716 D(bug("Area cleanup %p active=%p\n", obj,
1717 (Object *) XGET(_win(obj), MUIA_Window_ActiveObject)));
1718 if (obj == (Object *) XGET(_win(obj), MUIA_Window_ActiveObject))
1720 D(bug("we are active, unset us\n"));
1721 set(_win(obj), MUIA_Window_ActiveObject,
1722 MUIV_Window_ActiveObject_None);
1725 /* It's safe to call the following function with NULL */
1726 if ((data->mad_Flags & MADF_SHOWSELSTATE) &&
1727 (data->mad_InputMode != MUIV_InputMode_None))
1729 zune_imspec_cleanup(data->mad_SelBack);
1730 data->mad_SelBack = NULL;
1732 if (data->mad_Flags & MADF_OWNBG)
1734 zune_imspec_cleanup(data->mad_Background);
1735 data->mad_Background = NULL;
1738 muiRenderInfo(obj) = NULL;
1740 return TRUE;
1744 /**************************************************************************
1745 Called after the window is open and the area layouted, but before
1746 any drawing. Matched by one MUIM_Hide.
1747 Good place to init things depending on gadget size/position.
1748 **************************************************************************/
1749 static IPTR Area__MUIM_Show(struct IClass *cl, Object *obj,
1750 struct MUIP_Show *msg)
1752 struct MUI_AreaData *data = INST_DATA(cl, obj);
1754 zune_imspec_show(data->mad_Background, obj);
1756 if (data->mad_Flags & MADF_SHOWSELSTATE
1757 && data->mad_InputMode != MUIV_InputMode_None)
1759 zune_imspec_show(data->mad_SelBack, obj);
1762 return TRUE;
1765 /**************************************************************************
1766 Called when the window is about to be closed, to match MUIM_Show.
1767 **************************************************************************/
1768 static IPTR Area__MUIM_Hide(struct IClass *cl, Object *obj,
1769 struct MUIP_Hide *msg)
1771 struct MUI_AreaData *data = INST_DATA(cl, obj);
1773 zune_imspec_hide(data->mad_Background);
1774 if (data->mad_Flags & MADF_SHOWSELSTATE
1775 && data->mad_InputMode != MUIV_InputMode_None)
1777 zune_imspec_hide(data->mad_SelBack);
1780 if (data->mad_ContextZMenu)
1782 zune_close_menu(data->mad_ContextZMenu);
1783 data->mad_ContextZMenu = NULL;
1786 return TRUE;
1789 /**************************************************************************
1790 Called when gadget activated
1791 **************************************************************************/
1792 static IPTR Area__MUIM_GoActive(struct IClass *cl, Object *obj, Msg msg)
1794 //bug("Area_GoActive %p\n", obj);
1795 if (_flags(obj) & MADF_CANDRAW)
1796 _zune_focus_new(obj, ZUNE_FOCUS_TYPE_ACTIVE_OBJ);
1797 return TRUE;
1800 /**************************************************************************
1801 Called when gadget deactivated
1802 **************************************************************************/
1803 static IPTR Area__MUIM_GoInactive(struct IClass *cl, Object *obj, Msg msg)
1805 //bug("Area_GoInactive %p\n", obj);
1806 if (_flags(obj) & MADF_CANDRAW)
1807 _zune_focus_destroy(obj, ZUNE_FOCUS_TYPE_ACTIVE_OBJ);
1808 return TRUE;
1811 /**************************************************************************
1812 This one or derived methods won't be called if short help is
1813 not set in area instdata. So set this to a dummy val if overriding
1814 **************************************************************************/
1815 static IPTR Area__MUIM_CreateShortHelp(struct IClass *cl, Object *obj,
1816 struct MUIP_CreateShortHelp *msg)
1818 struct MUI_AreaData *data = INST_DATA(cl, obj);
1820 return (IPTR) data->mad_ShortHelp;
1823 /**************************************************************************
1825 **************************************************************************/
1826 static IPTR Area__MUIM_DeleteShortHelp(struct IClass *cl, Object *obj,
1827 struct MUIP_DeleteShortHelp *msg)
1829 return TRUE;
1832 /**************************************************************************
1834 **************************************************************************/
1835 static IPTR Area__MUIM_CreateBubble(struct IClass *cl, Object *obj,
1836 struct MUIP_CreateBubble *msg)
1838 return (IPTR) zune_bubble_create(obj, msg->x, msg->y, msg->txt,
1839 msg->flags);
1842 /**************************************************************************
1844 **************************************************************************/
1845 static IPTR Area__MUIM_DeleteBubble(struct IClass *cl, Object *obj,
1846 struct MUIP_DeleteBubble *msg)
1848 zune_bubble_delete(obj, msg->bubble);
1850 return TRUE;
1853 /* either lmb or press key */
1854 static void handle_press(struct IClass *cl, Object *obj)
1856 struct MUI_AreaData *data = INST_DATA(cl, obj);
1858 switch (data->mad_InputMode)
1860 case MUIV_InputMode_RelVerify:
1861 SetAttrs(obj, MUIA_Selected, TRUE, MUIA_Pressed, TRUE, TAG_DONE);
1862 set(obj, MUIA_Timer, ++muiAreaData(obj)->mad_Timeval);
1863 if (!data->mad_Timer.ihn_Millis && data->mad_DisableCount == 0)
1865 data->mad_Timer.ihn_Millis = 300;
1866 DoMethod(_app(obj), MUIM_Application_AddInputHandler,
1867 (IPTR) & data->mad_Timer);
1869 break;
1871 case MUIV_InputMode_Immediate:
1873 IPTR selected = FALSE;
1875 get(obj, MUIA_Selected, &selected);
1876 if (selected)
1878 /* D(bug("handle_press(%p) : nnset MUIA_Selected FALSE\n", obj)); */
1879 nnset(obj, MUIA_Selected, FALSE);
1881 /* D(bug("handle_press(%p) : set MUIA_Selected TRUE\n", obj)); */
1882 set(obj, MUIA_Selected, TRUE);
1883 /* D(bug("handle_press(%p) : done\n", obj)); */
1884 break;
1886 case MUIV_InputMode_Toggle:
1887 // although undocumented, MUI sets MUIA_Pressed too
1888 SetAttrs(obj, MUIA_Selected, !(data->mad_Flags & MADF_SELECTED),
1889 MUIA_Pressed, !(data->mad_Flags & MADF_PRESSED), TAG_DONE);
1890 break;
1894 /* either lmb or release key */
1895 static void handle_release(struct IClass *cl, Object *obj, int cancel)
1897 struct MUI_AreaData *data = INST_DATA(cl, obj);
1899 if (data->mad_ehn.ehn_Events)
1900 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1901 (IPTR) &data->mad_ehn);
1902 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1903 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1904 (IPTR) &data->mad_ehn);
1906 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
1908 if (data->mad_Flags & MADF_SELECTED)
1910 if (cancel)
1911 nnset(obj, MUIA_Pressed, FALSE);
1912 else
1913 set(obj, MUIA_Pressed, FALSE);
1915 set(obj, MUIA_Selected, FALSE);
1919 if (data->mad_Timer.ihn_Millis)
1921 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
1922 (IPTR) & data->mad_Timer);
1923 data->mad_Timer.ihn_Millis = 0;
1928 static IPTR event_button(Class *cl, Object *obj,
1929 struct IntuiMessage *imsg)
1931 struct MUI_AreaData *data = INST_DATA(cl, obj);
1932 BOOL in = _between(_left(obj), imsg->MouseX, _right(obj))
1933 && _between(_top(obj), imsg->MouseY, _bottom(obj));
1935 switch (imsg->Code)
1937 case SELECTDOWN:
1938 if (data->mad_InputMode == MUIV_InputMode_None)
1939 break;
1941 if (in)
1943 // set(_win(obj), MUIA_Window_ActiveObject, obj);
1944 data->mad_ClickX = imsg->MouseX;
1945 data->mad_ClickY = imsg->MouseY;
1947 if ((data->mad_InputMode != MUIV_InputMode_Toggle)
1948 && (data->mad_Flags & MADF_SELECTED))
1949 break;
1950 nnset(obj, MUIA_Timer, 0);
1951 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
1953 if (data->mad_ehn.ehn_Events)
1954 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1955 (IPTR) &data->mad_ehn);
1956 data->mad_ehn.ehn_Events |= IDCMP_MOUSEMOVE | IDCMP_RAWKEY;
1957 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1958 (IPTR) &data->mad_ehn);
1960 handle_press(cl, obj);
1961 return MUI_EventHandlerRC_Eat;
1963 break;
1965 case SELECTUP:
1966 if (data->mad_InputMode == MUIV_InputMode_None)
1967 break;
1969 if (data->mad_ehn.ehn_Events != IDCMP_MOUSEBUTTONS)
1971 handle_release(cl, obj, FALSE /* cancel */ );
1972 return MUI_EventHandlerRC_Eat;
1974 break;
1976 case MENUDOWN:
1977 if (in && data->mad_ContextMenu)
1979 Object *menuobj =
1980 (Object *) DoMethod(obj, MUIM_ContextMenuBuild,
1981 imsg->MouseX, imsg->MouseY);
1982 if (menuobj)
1984 struct NewMenu *newmenu = NULL;
1986 /* stegerg: HACKME, CHECKME! The menu/menu item objs should
1987 automatically be connected (parentobject setup) without
1988 need for this, but they aren't. Because of how family
1989 class is and is used by other classes, I think!? */
1990 DoMethod(menuobj, MUIM_ConnectParent, obj);
1992 get(menuobj, MUIA_Menuitem_NewMenu, &newmenu);
1993 if (newmenu)
1995 if (data->mad_ContextZMenu)
1996 zune_close_menu(data->mad_ContextZMenu);
1997 data->mad_ContextZMenu =
1998 zune_open_menu(_window(obj), newmenu);
2001 if (data->mad_ehn.ehn_Events)
2002 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2003 (IPTR) &data->mad_ehn);
2004 data->mad_ehn.ehn_Events |= IDCMP_MOUSEMOVE;
2005 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2006 (IPTR) &data->mad_ehn);
2008 return MUI_EventHandlerRC_Eat;
2010 break;
2012 case MENUUP:
2013 if (data->mad_ContextZMenu)
2015 struct MenuItem *item = zune_leave_menu(data->mad_ContextZMenu);
2017 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2018 (IPTR) &data->mad_ehn);
2019 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2020 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2021 (IPTR) &data->mad_ehn);
2023 if (item)
2025 Object *itemobj = (Object *) GTMENUITEM_USERDATA(item);
2027 /* CHECKME: MUIA_MenuItem_Trigger should probably be set inside
2028 MUIM_ContextMenuChoice!? But there I only know about
2029 itemobj, not MenuItem itself! */
2030 if (item->Flags & CHECKIT)
2032 set(itemobj, MUIA_Menuitem_Checked,
2033 ! !(item->Flags & CHECKED));
2037 set(itemobj, MUIA_Menuitem_Trigger, item);
2039 DoMethod(obj, MUIM_ContextMenuChoice, itemobj);
2043 zune_close_menu(data->mad_ContextZMenu);
2044 data->mad_ContextZMenu = NULL;
2046 return MUI_EventHandlerRC_Eat;
2049 break;
2052 return 0;
2055 static IPTR event_motion(Class *cl, Object *obj,
2056 struct IntuiMessage *imsg)
2058 struct MUI_AreaData *data = INST_DATA(cl, obj);
2060 if ((imsg->Qualifier & IEQUALIFIER_RBUTTON) && data->mad_ContextZMenu)
2062 zune_mouse_update(data->mad_ContextZMenu, 0);
2063 return MUI_EventHandlerRC_Eat;
2066 if (imsg->Qualifier & IEQUALIFIER_LEFTBUTTON)
2068 BOOL in = _between(_left(obj), imsg->MouseX, _right(obj))
2069 && _between(_top(obj), imsg->MouseY, _bottom(obj));
2071 if (in)
2073 if ((data->mad_Flags & MADF_DRAGGABLE)
2074 && ((abs(data->mad_ClickX - imsg->MouseX) >= 3)
2075 || (abs(data->mad_ClickY - imsg->MouseY) >= 3)))
2076 /* should be user configurable */
2078 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
2079 set(obj, MUIA_Selected, FALSE);
2080 nnset(obj, MUIA_Pressed, FALSE);
2082 if (data->mad_ehn.ehn_Events)
2083 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2084 (IPTR) &data->mad_ehn);
2085 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2086 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2087 (IPTR) &data->mad_ehn);
2088 if (data->mad_Timer.ihn_Millis)
2090 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
2091 (IPTR) & data->mad_Timer);
2092 data->mad_Timer.ihn_Millis = 0;
2095 DoMethod(obj, MUIM_DoDrag, data->mad_ClickX - _left(obj),
2096 data->mad_ClickY - _top(obj), 0);
2097 return MUI_EventHandlerRC_Eat;
2101 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
2103 if (!in && (data->mad_Flags & MADF_SELECTED)) /* going out */
2105 set(obj, MUIA_Selected, FALSE);
2107 else if (in && !(data->mad_Flags & MADF_SELECTED)) /* going in */
2109 set(obj, MUIA_Selected, TRUE);
2113 return MUI_EventHandlerRC_Eat;
2116 /**************************************************************************
2118 **************************************************************************/
2119 static IPTR Area__MUIM_HandleEvent(struct IClass *cl, Object *obj,
2120 struct MUIP_HandleEvent *msg)
2122 struct MUI_AreaData *data = INST_DATA(cl, obj);
2124 if (data->mad_DisableCount)
2125 return 0;
2126 if (data->mad_InputMode == MUIV_InputMode_None
2127 && !data->mad_ContextMenu)
2128 return 0;
2130 if (msg->muikey != MUIKEY_NONE)
2132 switch (msg->muikey)
2134 case MUIKEY_PRESS:
2135 if (data->mad_Flags & MADF_SELECTED)
2136 break;
2137 if (data->mad_ehn.ehn_Events)
2138 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2139 (IPTR) &data->mad_ehn);
2140 data->mad_ehn.ehn_Events |= IDCMP_RAWKEY;
2141 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2142 (IPTR) &data->mad_ehn);
2143 handle_press(cl, obj);
2144 return MUI_EventHandlerRC_Eat;
2146 case MUIKEY_TOGGLE:
2147 if (data->mad_InputMode == MUIV_InputMode_Toggle)
2148 set(obj, MUIA_Selected, !(data->mad_Flags & MADF_SELECTED));
2149 return MUI_EventHandlerRC_Eat;
2151 case MUIKEY_RELEASE:
2152 handle_release(cl, obj, FALSE /* cancel */ );
2153 return MUI_EventHandlerRC_Eat;
2155 return 0;
2158 if (msg->imsg)
2160 switch (msg->imsg->Class)
2162 case IDCMP_MOUSEBUTTONS:
2163 return event_button(cl, obj, msg->imsg);
2164 case IDCMP_MOUSEMOVE:
2165 return event_motion(cl, obj, msg->imsg);
2166 case IDCMP_RAWKEY:
2168 unsigned char code;
2169 UWORD msg_code;
2170 /* Remove the up prefix as convert key does not convert an
2171 * upkey event */
2172 msg_code = msg->imsg->Code;
2173 msg->imsg->Code &= ~IECODE_UP_PREFIX;
2174 code = ConvertKey(msg->imsg);
2175 msg->imsg->Code = msg_code;
2177 if (code != 0 && code == data->mad_ControlChar)
2179 if (msg->imsg->Code & IECODE_UP_PREFIX)
2181 msg->muikey = MUIKEY_RELEASE;
2183 else
2185 msg->muikey = MUIKEY_PRESS;
2187 msg->imsg = NULL;
2188 return Area__MUIM_HandleEvent(cl, obj, msg);
2191 if (msg->imsg->
2192 Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
2194 handle_release(cl, obj, TRUE /* cancel */ );
2197 /* Do not eat wheel movement events */
2198 if ((msg->imsg->Code == RAWKEY_NM_WHEEL_UP)
2199 || (msg->imsg->Code == RAWKEY_NM_WHEEL_DOWN))
2200 return 0;
2202 return MUI_EventHandlerRC_Eat;
2204 break;
2207 return 0;
2210 /**************************************************************************
2212 **************************************************************************/
2213 static IPTR Area__MUIM_HandleInput(struct IClass *cl, Object *obj,
2214 struct MUIP_HandleInput *msg)
2216 /* Actually a dummy, but real MUI does handle here the input stuff which
2217 * Zune has in Area_HandleEvent. For compatibility we should do this too */
2218 //bug("Area_HandleEvent [%p] imsg=%p muikey=%ld\b", obj, msg->imsg,
2219 // msg->muikey);
2220 return 0;
2223 /**************************************************************************
2224 Trivial; custom classes may override this to get dynamic menus.
2225 **************************************************************************/
2226 static IPTR Area__MUIM_ContextMenuBuild(struct IClass *cl, Object *obj,
2227 struct MUIP_ContextMenuBuild *msg)
2229 struct MUI_AreaData *data = INST_DATA(cl, obj);
2230 return (IPTR) data->mad_ContextMenu; /* a Menustrip object */
2233 /**************************************************************************/
2234 static IPTR Area__MUIM_ContextMenuChoice(struct IClass *cl, Object *obj,
2235 struct MUIP_ContextMenuChoice *msg)
2237 set(obj, MUIA_ContextMenuTrigger, msg->item);
2238 return 0;
2242 /**************************************************************************
2243 MUIM_Export : to export an object's "contents" to a dataspace object.
2244 **************************************************************************/
2245 static IPTR Area__MUIM_Export(struct IClass *cl, Object *obj,
2246 struct MUIP_Export *msg)
2248 struct MUI_AreaData *data = INST_DATA(cl, obj);
2249 ULONG id;
2251 if ((id = muiNotifyData(obj)->mnd_ObjectID))
2253 char selected = (data->mad_Flags & MADF_SELECTED) ? 1 : 0;
2254 DoMethod(msg->dataspace, MUIM_Dataspace_Add, (IPTR) & selected,
2255 sizeof(char), (IPTR) id);
2257 return 0;
2261 /**************************************************************************
2262 MUIM_Import : to import an object's "contents" from a dataspace object.
2263 **************************************************************************/
2264 static IPTR Area__MUIM_Import(struct IClass *cl, Object *obj,
2265 struct MUIP_Import *msg)
2267 ULONG id;
2269 if ((id = muiNotifyData(obj)->mnd_ObjectID))
2271 char *selected =
2272 (char *)DoMethod(msg->dataspace, MUIM_Dataspace_Find,
2273 (IPTR) id);
2275 if (selected)
2276 set(obj, MUIA_Selected, *selected);
2278 return 0;
2281 /**************************************************************************
2282 MUIM_Timer
2283 **************************************************************************/
2284 static IPTR Area__MUIM_Timer(struct IClass *cl, Object *obj, Msg msg)
2286 struct MUI_AreaData *data = INST_DATA(cl, obj);
2287 if (data->mad_Timer.ihn_Millis)
2288 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
2289 (IPTR) & data->mad_Timer);
2290 data->mad_Timer.ihn_Millis = 50;
2291 DoMethod(_app(obj), MUIM_Application_AddInputHandler,
2292 (IPTR) & data->mad_Timer);
2294 if (data->mad_Flags & MADF_SELECTED)
2295 set(obj, MUIA_Timer, ++muiAreaData(obj)->mad_Timeval);
2296 return 0;
2299 /**************************************************************************
2300 MUIM_DoDrag
2301 **************************************************************************/
2302 static IPTR Area__MUIM_DoDrag(struct IClass *cl, Object *obj,
2303 struct MUIP_DoDrag *msg)
2305 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2306 DoMethod(_win(obj), MUIM_Window_DragObject, (IPTR) obj, msg->touchx,
2307 msg->touchy, msg->flags);
2308 return 0;
2311 /**************************************************************************
2312 MUIM_CreateDragImage
2313 **************************************************************************/
2314 static IPTR Area__MUIM_CreateDragImage(struct IClass *cl, Object *obj,
2315 struct MUIP_CreateDragImage *msg)
2317 struct MUI_DragImage *img = (struct MUI_DragImage *)
2318 AllocVec(sizeof(struct MUI_DragImage), MEMF_CLEAR);
2319 if (img)
2321 const struct ZuneFrameGfx *zframe;
2322 LONG depth =
2323 GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
2325 zframe =
2326 zune_zframe_get(obj,
2327 &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Drag]);
2329 img->width = _width(obj) + zframe->ileft + zframe->iright;
2330 img->height = _height(obj) + zframe->itop + zframe->ibottom;
2332 if ((img->bm =
2333 AllocBitMap(img->width, img->height, depth, BMF_MINPLANES,
2334 _screen(obj)->RastPort.BitMap)))
2336 /* Render the stuff now */
2337 struct RastPort *rp_save = muiRenderInfo(obj)->mri_RastPort;
2338 struct RastPort temprp;
2339 InitRastPort(&temprp);
2340 temprp.BitMap = img->bm;
2341 ClipBlit(_rp(obj), _left(obj), _top(obj), &temprp,
2342 zframe->ileft, zframe->itop, _width(obj), _height(obj),
2343 0xc0);
2345 muiRenderInfo(obj)->mri_RastPort = &temprp;
2346 zframe->draw(zframe->customframe, muiRenderInfo(obj), 0, 0,
2347 img->width, img->height, 0, 0, img->width, img->height);
2348 muiRenderInfo(obj)->mri_RastPort = rp_save;
2351 img->touchx = msg->touchx;
2352 img->touchy = msg->touchy;
2353 img->flags = 0;
2355 return (IPTR) img;
2358 /**************************************************************************
2359 MUIM_DeleteDragImage
2360 **************************************************************************/
2361 static IPTR Area__MUIM_DeleteDragImage(struct IClass *cl, Object *obj,
2362 struct MUIP_DeleteDragImage *msg)
2364 if (msg->di)
2366 if (msg->di->bm)
2367 FreeBitMap(msg->di->bm);
2368 FreeVec(msg->di);
2370 return 0;
2373 /**************************************************************************
2374 MUIM_DragQueryExtended
2375 **************************************************************************/
2376 static IPTR Area__MUIM_DragQueryExtended(struct IClass *cl, Object *obj,
2377 struct MUIP_DragQueryExtended *msg)
2379 struct MUI_AreaData *data = INST_DATA(cl, obj);
2380 if (data->mad_Flags & MADF_DROPABLE)
2382 if (_left(obj) <= msg->x && msg->x <= _right(obj)
2383 && _top(obj) <= msg->y && msg->y <= _bottom(obj))
2385 if (DoMethod(obj, MUIM_DragQuery,
2386 (IPTR) msg->obj) == MUIV_DragQuery_Accept)
2387 return (IPTR) obj;
2390 return 0;
2393 /**************************************************************************
2394 MUIM_DragBegin
2395 **************************************************************************/
2396 static IPTR Area__MUIM_DragBegin(struct IClass *cl, Object *obj,
2397 struct MUIP_DragBegin *msg)
2399 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2400 _zune_focus_new(obj, ZUNE_FOCUS_TYPE_DROP_OBJ);
2401 return 0;
2404 /**************************************************************************
2405 MUIM_DragFinish
2406 **************************************************************************/
2407 static IPTR Area__MUIM_DragFinish(struct IClass *cl, Object *obj,
2408 struct MUIP_DragFinish *msg)
2410 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2411 _zune_focus_destroy(obj, ZUNE_FOCUS_TYPE_DROP_OBJ);
2412 return 0;
2417 * Calculates addleft, addtop, subwidth, subheight from current settings.
2418 * If frame phantom, ignore horizontal frame components.
2419 * Depends on inner sizes and frame
2421 static void area_update_msizes(Object *obj, struct MUI_AreaData *data,
2422 const struct MUI_FrameSpec_intern *frame,
2423 const struct ZuneFrameGfx *zframe)
2426 /* if (XGET(obj, MUIA_UserData) == 42) */
2427 /* { */
2428 /* D(bug("area_update_msizes(%p) : ileft=%ld itop=%ld\n", obj, */
2429 /* zframe->ileft, zframe->itop)); */
2430 /* } */
2432 struct dt_frame_image *fi = zframe->customframe;
2434 if (fi != NULL)
2436 //UWORD w = fi->tile_left + fi->tile_right;
2437 //UWORD h = fi->tile_top + fi->tile_bottom;
2439 data->mad_addleft = data->mad_InnerLeft + zframe->ileft;
2440 data->mad_subwidth =
2441 data->mad_addleft + data->mad_InnerRight + zframe->iright;
2442 data->mad_addtop =
2443 data->mad_InnerTop + data->mad_TitleHeightAdd + zframe->itop;
2444 data->mad_subheight =
2445 data->mad_addtop + data->mad_InnerBottom + zframe->ibottom;
2447 else
2449 data->mad_addleft = data->mad_InnerLeft + zframe->ileft;
2450 data->mad_subwidth =
2451 data->mad_addleft + data->mad_InnerRight + zframe->iright;
2452 data->mad_addtop =
2453 data->mad_InnerTop + data->mad_TitleHeightAdd + zframe->itop;
2454 data->mad_subheight =
2455 data->mad_addtop + data->mad_InnerBottom + zframe->ibottom;
2458 if (data->mad_Flags & MADF_FRAMEPHANTOM)
2460 data->mad_addleft = 0;
2461 data->mad_subwidth = 0;
2464 // clamping ... maybe ?
2466 /* D(bug("area_update_msizes(%x,%d) => addleft/top=%d/%d, " */
2467 /* "subwidth/height=%d/%d\n", */
2468 /* obj, data->mad_Frame, data->mad_addleft, data->mad_addtop, */
2469 /* data->mad_subwidth, data->mad_subheight)); */
2472 /**************************************************************************
2473 MUIM_Area_UnknownDropDestination
2474 **************************************************************************/
2475 IPTR Area__MUIM_UnknownDropDestination(struct IClass *cl, Object *obj,
2476 struct MUIP_UnknownDropDestination *msg)
2478 return 0;
2481 /**************************************************************************
2482 MUIM_UpdateInnerSizes - Updates the innersizes of an object. You actually
2483 should only call this method if the dimensions of an object would not be
2484 affected, otherwise the results are unexpected
2485 **************************************************************************/
2486 static IPTR Area__MUIM_UpdateInnerSizes(struct IClass *cl, Object *obj,
2487 struct MUIP_UpdateInnerSizes *msg)
2489 struct MUI_AreaData *data = INST_DATA(cl, obj);
2490 const struct ZuneFrameGfx *zframe;
2491 const struct MUI_FrameSpec_intern *frame;
2492 struct MUI_FrameSpec_intern tempframe;
2494 if (_flags(obj) & MADF_SETUP)
2496 frame = get_intframe(obj, data, &tempframe);
2497 zframe = zune_zframe_get(obj, frame);
2498 area_update_msizes(obj, data, frame, zframe);
2500 return 1;
2503 static IPTR Area__MUIM_FindAreaObject(struct IClass *cl, Object *obj,
2504 struct MUIP_FindAreaObject *msg)
2506 if (msg->obj == obj)
2507 return (IPTR) obj;
2508 else
2509 return (IPTR) NULL;
2512 BOOPSI_DISPATCHER(IPTR, Area_Dispatcher, cl, obj, msg)
2514 switch (msg->MethodID)
2516 case OM_NEW:
2517 return Area__OM_NEW(cl, obj, (struct opSet *)msg);
2518 case OM_DISPOSE:
2519 return Area__OM_DISPOSE(cl, obj, msg);
2520 case OM_SET:
2521 return Area__OM_SET(cl, obj, (struct opSet *)msg);
2522 case OM_GET:
2523 return Area__OM_GET(cl, obj, (struct opGet *)msg);
2524 case MUIM_AskMinMax:
2525 return Area__MUIM_AskMinMax(cl, obj, (APTR) msg);
2526 case MUIM_Draw:
2527 return Area__MUIM_Draw(cl, obj, (APTR) msg);
2528 case MUIM_DrawBackground:
2529 return Area__MUIM_DrawBackground(cl, obj, (APTR) msg);
2530 case MUIM_DrawBackgroundBuffered:
2531 return Area__MUIM_DrawBackgroundBuffered(cl, obj, (APTR) msg);
2532 case MUIM_DrawParentBackground:
2533 return Area__MUIM_DrawParentBackground(cl, obj, (APTR) msg);
2534 case MUIM_Setup:
2535 return Area__MUIM_Setup(cl, obj, (APTR) msg);
2536 case MUIM_Cleanup:
2537 return Area__MUIM_Cleanup(cl, obj, (APTR) msg);
2538 case MUIM_Show:
2539 return Area__MUIM_Show(cl, obj, (APTR) msg);
2540 case MUIM_Hide:
2541 return Area__MUIM_Hide(cl, obj, (APTR) msg);
2542 case MUIM_GoActive:
2543 return Area__MUIM_GoActive(cl, obj, (APTR) msg);
2544 case MUIM_GoInactive:
2545 return Area__MUIM_GoInactive(cl, obj, (APTR) msg);
2546 case MUIM_Layout:
2547 return 1;
2548 case MUIM_CreateShortHelp:
2549 return Area__MUIM_CreateShortHelp(cl, obj, (APTR) msg);
2550 case MUIM_DeleteShortHelp:
2551 return Area__MUIM_DeleteShortHelp(cl, obj, (APTR) msg);
2552 case MUIM_CreateBubble:
2553 return Area__MUIM_CreateBubble(cl, obj, (APTR) msg);
2554 case MUIM_DeleteBubble:
2555 return Area__MUIM_DeleteBubble(cl, obj, (APTR) msg);
2556 case MUIM_HandleEvent:
2557 return Area__MUIM_HandleEvent(cl, obj, (APTR) msg);
2558 case MUIM_ContextMenuBuild:
2559 return Area__MUIM_ContextMenuBuild(cl, obj, (APTR) msg);
2560 case MUIM_ContextMenuChoice:
2561 return Area__MUIM_ContextMenuChoice(cl, obj, (APTR) msg);
2562 case MUIM_Timer:
2563 return Area__MUIM_Timer(cl, obj, msg);
2564 case MUIM_UpdateInnerSizes:
2565 return Area__MUIM_UpdateInnerSizes(cl, obj, (APTR) msg);
2566 case MUIM_DragQuery:
2567 return MUIV_DragQuery_Refuse;
2568 case MUIM_DragBegin:
2569 return Area__MUIM_DragBegin(cl, obj, (APTR) msg);
2570 case MUIM_DragDrop:
2571 return FALSE;
2572 case MUIM_UnknownDropDestination:
2573 return Area__MUIM_UnknownDropDestination(cl, obj, (APTR) msg);
2574 case MUIM_DragFinish:
2575 return Area__MUIM_DragFinish(cl, obj, (APTR) msg);
2576 case MUIM_DragReport:
2577 return MUIV_DragReport_Continue; /* or MUIV_DragReport_Abort? */
2578 case MUIM_DoDrag:
2579 return Area__MUIM_DoDrag(cl, obj, (APTR) msg);
2580 case MUIM_CreateDragImage:
2581 return Area__MUIM_CreateDragImage(cl, obj, (APTR) msg);
2582 case MUIM_DeleteDragImage:
2583 return Area__MUIM_DeleteDragImage(cl, obj, (APTR) msg);
2584 case MUIM_DragQueryExtended:
2585 return Area__MUIM_DragQueryExtended(cl, obj, (APTR) msg);
2586 case MUIM_HandleInput:
2587 return Area__MUIM_HandleInput(cl, obj, (APTR) msg);
2588 case MUIM_FindAreaObject:
2589 return Area__MUIM_FindAreaObject(cl, obj, (APTR) msg);
2591 case MUIM_Export:
2592 return Area__MUIM_Export(cl, obj, (APTR) msg);
2593 case MUIM_Import:
2594 return Area__MUIM_Import(cl, obj, (APTR) msg);
2597 return DoSuperMethodA(cl, obj, msg);
2599 BOOPSI_DISPATCHER_END
2602 * Class descriptor.
2604 const struct __MUIBuiltinClass _MUI_Area_desc =
2606 MUIC_Area,
2607 MUIC_Notify,
2608 sizeof(struct MUI_AreaData),
2609 (void *) Area_Dispatcher