Fixes to typos in comments etc.
[AROS.git] / workbench / libs / muimaster / classes / area.c
blob9477db4246edd9dc6b3183e94aca811bd5efc482
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2014, 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>
16 #include <clib/alib_protos.h>
17 #include <proto/exec.h>
18 #include <proto/intuition.h>
19 #include <proto/graphics.h>
20 #include <proto/utility.h>
21 #include <proto/muimaster.h>
23 extern struct Library *MUIMasterBase;
24 #include "muimaster_intern.h"
26 #include "mui.h"
27 #include "support.h"
28 #include "imspec.h"
29 #include "menu.h"
30 #include "prefs.h"
31 #include "font.h"
32 #include "textengine.h"
33 #include "bubbleengine.h"
34 #include "datatypescache.h"
37 // #define MYDEBUG 1
38 #include "debug.h"
41 Area.mui/MUIA_Background done
42 Area.mui/MUIA_BottomEdge done
43 Area.mui/MUIA_ContextMenu done
44 Area.mui/MUIA_ContextMenuTrigger
45 Area.mui/MUIA_ControlChar done
46 Area.mui/MUIA_CycleChain done
47 Area.mui/MUIA_Disabled done
48 Area.mui/MUIA_Draggable done
49 Area.mui/MUIA_Dropable done
50 Area.mui/MUIA_ExportID
51 Area.mui/MUIA_FillArea done
52 Area.mui/MUIA_FixHeight done
53 Area.mui/MUIA_FixHeightTxt done
54 Area.mui/MUIA_FixWidth done
55 Area.mui/MUIA_FixWidthTxt done
56 Area.mui/MUIA_Font done
57 Area.mui/MUIA_Frame done
58 Area.mui/MUIA_FramePhantomHoriz done
59 Area.mui/MUIA_FrameTitle done
60 Area.mui/MUIA_Height done
61 Area.mui/MUIA_HorizDisappear
62 Area.mui/MUIA_HorizWeight done
63 Area.mui/MUIA_InnerBottom done
64 Area.mui/MUIA_InnerLeft done
65 Area.mui/MUIA_InnerRight done
66 Area.mui/MUIA_InnerTop done
67 Area.mui/MUIA_InputMode done
68 Area.mui/MUIA_LeftEdge done
69 Area.mui/MUIA_MaxHeight done
70 Area.mui/MUIA_MaxWidth done
71 Area.mui/MUIA_Pressed done
72 Area.mui/MUIA_RightEdge done
73 Area.mui/MUIA_Selected done
74 Area.mui/MUIA_ShortHelp done
75 Area.mui/MUIA_ShowMe done
76 Area.mui/MUIA_ShowSelState done (I only)
77 Area.mui/MUIA_Timer done
78 Area.mui/MUIA_TopEdge done
79 Area.mui/MUIA_VertDisappear
80 Area.mui/MUIA_VertWeight done
81 Area.mui/MUIA_Weight done
82 Area.mui/MUIA_Width done
83 Area.mui/MUIA_Window done
84 Area.mui/MUIA_WindowObject done
86 Area.mui/MUIM_AskMinMax done
87 Area.mui/MUIM_Cleanup done
88 Area.mui/MUIM_ContextMenuBuild done
89 Area.mui/MUIM_ContextMenuChoice done
90 Area.mui/MUIM_CreateBubble done
91 Area.mui/MUIM_CreateShortHelp done
92 Area.mui/MUIM_DeleteBubble done
93 Area.mui/MUIM_DeleteShortHelp done
94 Area.mui/MUIM_DragBegin
95 Area.mui/MUIM_DragDrop done
96 Area.mui/MUIM_DragFinish
97 Area.mui/MUIM_DragQuery done
98 Area.mui/MUIM_DragReport
99 Area.mui/MUIM_Draw done
100 Area.mui/MUIM_DrawBackground done
101 Area.mui/MUIM_HandleEvent done
102 Area.mui/MUIM_HandleInput
103 Area.mui/MUIM_Hide done
104 Area.mui/MUIM_Setup done
105 Area.mui/MUIM_Show done
108 static const int __version = 1;
109 static const int __revision = 1;
111 //#ifdef DEBUG
112 //static STRPTR zune_area_to_string (Object *area);
113 //#endif
115 static const struct MUI_FrameSpec_intern *get_intframe(Object *obj,
116 struct MUI_AreaData *data, struct MUI_FrameSpec_intern *tempstore);
117 static void set_inner_sizes(Object *obj, struct MUI_AreaData *data);
118 static void set_title_sizes(Object *obj, struct MUI_AreaData *data);
120 static void area_update_msizes(Object *obj, struct MUI_AreaData *data,
121 const struct MUI_FrameSpec_intern *frame,
122 const struct ZuneFrameGfx *zframe);
123 static void setup_control_char(struct MUI_AreaData *data, Object *obj,
124 struct IClass *cl);
125 static void cleanup_control_char(struct MUI_AreaData *data, Object *obj);
127 //static void setup_cycle_chain (struct MUI_AreaData *data, Object *obj);
128 //static void cleanup_cycle_chain (struct MUI_AreaData *data, Object *obj);
130 #define ZUNE_FOCUS_TYPE_ACTIVE_OBJ 0
131 #define ZUNE_FOCUS_TYPE_DROP_OBJ 1
133 static void _zune_focus_new(Object *obj, int type)
135 Object *parent;
136 struct RastPort *rp;
137 UWORD oldDrPt;
139 //bug("_zune_focus_new 1 %p\n", obj);
141 if (NULL == obj || !(_flags(obj) & MADF_CANDRAW))
142 return;
144 parent = _parent(obj);
145 rp = _rp(obj);
146 oldDrPt = rp->LinePtrn;
148 int x1 = _left(obj);
149 int y1 = _top(obj);
150 int x2 = _left(obj) + _width(obj) - 1;
151 int y2 = _top(obj) + _height(obj) - 1;
153 if (!parent || parent == _win(obj))
154 return;
156 SetABPenDrMd(rp, _pens(obj)[MPEN_SHINE], _pens(obj)[MPEN_SHADOW], JAM2);
158 if (type == ZUNE_FOCUS_TYPE_ACTIVE_OBJ)
160 SetDrPt(rp, 0xCCCC);
161 x1--;
162 y1--;
163 x2++;
164 y2++;
166 else
168 SetDrPt(rp, 0xF0F0);
171 Move(rp, x1, y1);
172 Draw(rp, x2, y1);
173 Draw(rp, x2, y2);
174 Draw(rp, x1, y2);
175 Draw(rp, x1, y1);
176 SetDrPt(rp, oldDrPt);
179 static void _zune_focus_destroy(Object *obj, int type)
181 Object *parent;
183 //bug("_zune_focus_destroy 1 %p\n", obj);
185 if (NULL == obj || !(_flags(obj) & MADF_CANDRAW))
186 return;
188 parent = _parent(obj);
189 int x1 = _left(obj);
190 int y1 = _top(obj);
191 int x2 = _left(obj) + _width(obj) - 1;
192 int y2 = _top(obj) + _height(obj) - 1;
193 int width;
194 int height;
196 if (type == ZUNE_FOCUS_TYPE_ACTIVE_OBJ)
198 if (!parent || parent == _win(obj))
199 return;
201 x1--;
202 y1--;
203 x2++;
204 y2++;
205 width = x2 - x1 + 1;
206 height = y2 - y1 + 1;
208 DoMethod(parent, MUIM_DrawBackground, x1, y1, width, 1, x1, y1, 0);
209 DoMethod(parent, MUIM_DrawBackground, x2, y1, 1, height, x2, y1, 0);
210 DoMethod(parent, MUIM_DrawBackground, x1, y2, width, 1, x1, y2, 0);
211 DoMethod(parent, MUIM_DrawBackground, x1, y1, 1, height, x1, y1, 0);
213 else
215 struct Region *region;
216 struct Rectangle rect;
217 APTR clip = NULL;
219 region = NewRegion();
220 if (region)
222 rect.MinX = _left(obj);
223 rect.MinY = _top(obj);
224 rect.MaxX = _right(obj);
225 rect.MaxY = _top(obj);
227 OrRectRegion(region, &rect);
229 rect.MinX = _right(obj);
230 rect.MinY = _top(obj);
231 rect.MaxX = _right(obj);
232 rect.MaxY = _bottom(obj);
234 OrRectRegion(region, &rect);
236 rect.MinX = _left(obj);
237 rect.MinY = _bottom(obj);
238 rect.MaxX = _right(obj);
239 rect.MaxY = _bottom(obj);
241 OrRectRegion(region, &rect);
243 rect.MinX = _left(obj);
244 rect.MinY = _top(obj);
245 rect.MaxX = _left(obj);
246 rect.MaxY = _bottom(obj);
248 OrRectRegion(region, &rect);
250 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
254 MUI_Redraw(obj, MADF_DRAWOBJECT);
256 if (region)
258 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
264 /**************************************************************************
265 OM_NEW
266 **************************************************************************/
267 static IPTR Area__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
269 struct MUI_AreaData *data;
270 struct TagItem *tags, *tag;
272 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
273 if (!obj)
274 return FALSE;
276 /* Initial local instance data */
277 data = INST_DATA(cl, obj);
279 data->mad_Flags =
280 MADF_FILLAREA | MADF_SHOWME | MADF_SHOWSELSTATE | MADF_DROPABLE;
281 data->mad_HorizWeight = data->mad_VertWeight = 100;
282 data->mad_InputMode = MUIV_InputMode_None;
284 /* parse initial taglist */
286 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
288 switch (tag->ti_Tag)
290 case MUIA_Background:
292 data->mad_Flags |= MADF_OWNBG;
293 if (data->mad_BackgroundSpec)
295 zune_image_spec_free(data->mad_BackgroundSpec);
297 data->mad_BackgroundSpec =
298 zune_image_spec_duplicate(tag->ti_Data);
300 break;
302 case MUIA_ControlChar:
303 data->mad_ControlChar = tag->ti_Data;
304 break;
306 case MUIA_CycleChain:
307 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
308 MADF_CYCLECHAIN);
309 break;
311 case MUIA_Disabled:
312 case MUIA_NestedDisabled:
313 if (tag->ti_Data)
315 data->mad_DisableCount = 1;
317 break;
319 case MUIA_FillArea:
320 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_FILLAREA);
321 break;
323 case MUIA_Draggable:
324 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DRAGGABLE);
325 break;
327 case MUIA_Dropable:
328 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DROPABLE);
329 break;
331 case MUIA_FixHeight:
332 data->mad_Flags |= MADF_FIXHEIGHT;
333 data->mad_HardHeight = tag->ti_Data;
334 break;
336 case MUIA_FixHeightTxt:
337 data->mad_HardHeightTxt = (STRPTR) tag->ti_Data;
338 break;
340 case MUIA_FixWidth:
341 data->mad_Flags |= MADF_FIXWIDTH;
342 data->mad_HardWidth = tag->ti_Data;
343 break;
345 case MUIA_FixWidthTxt:
346 data->mad_HardWidthTxt = (STRPTR) tag->ti_Data;
347 break;
349 case MUIA_Font:
350 data->mad_FontPreset = tag->ti_Data;
351 break;
353 case MUIA_Frame:
354 data->mad_Frame = tag->ti_Data;
355 break;
357 case MUIA_FramePhantomHoriz:
358 data->mad_Flags |= MADF_FRAMEPHANTOM;
359 break;
361 case MUIA_FrameTitle:
362 data->mad_FrameTitle = (STRPTR) tag->ti_Data;
363 break;
365 case MUIA_HorizWeight:
366 data->mad_HorizWeight = tag->ti_Data;
367 break;
369 case MUIA_InnerBottom:
370 data->mad_Flags |= MADF_INNERBOTTOM;
371 data->mad_InnerBottom = CLAMP((IPTR) tag->ti_Data, 0, 32);
372 break;
374 case MUIA_InnerLeft:
375 data->mad_Flags |= MADF_INNERLEFT;
376 data->mad_InnerLeft = CLAMP((IPTR) tag->ti_Data, 0, 32);
377 break;
379 case MUIA_InnerRight:
380 data->mad_Flags |= MADF_INNERRIGHT;
381 data->mad_InnerRight = CLAMP((IPTR) tag->ti_Data, 0, 32);
382 break;
384 case MUIA_InnerTop:
385 data->mad_Flags |= MADF_INNERTOP;
386 data->mad_InnerTop = CLAMP((IPTR) tag->ti_Data, 0, 32);
387 break;
389 case MUIA_InputMode:
390 data->mad_InputMode = tag->ti_Data;
391 break;
393 case MUIA_MaxHeight:
394 data->mad_Flags |= MADF_MAXHEIGHT;
395 data->mad_HardHeight = tag->ti_Data;
396 break;
398 case MUIA_MaxWidth:
399 data->mad_Flags |= MADF_MAXWIDTH;
400 data->mad_HardWidth = tag->ti_Data;
401 break;
403 case MUIA_Selected:
404 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_SELECTED);
405 break;
407 case MUIA_ShortHelp:
408 data->mad_ShortHelp = (STRPTR) tag->ti_Data;
409 break;
411 case MUIA_ShowMe:
412 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_SHOWME);
413 break;
415 case MUIA_ShowSelState:
416 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
417 MADF_SHOWSELSTATE);
418 break;
420 case MUIA_VertWeight:
421 data->mad_VertWeight = tag->ti_Data;
422 break;
424 case MUIA_Weight:
425 data->mad_HorizWeight = data->mad_VertWeight = tag->ti_Data;
426 break;
428 case MUIA_ContextMenu:
429 data->mad_ContextMenu = (Object *) tag->ti_Data;
430 break;
434 /* In Soliton MUIA_Selected was set to MUIV_InputMode_RelVerify (=1)
435 ** for MUIA_Input_Mode MUIV_InputMode_RelVerify which is wrong of
436 ** course but MUI seems to filter this out so we have to do it also
438 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
440 if (data->mad_Flags & MADF_SELECTED)
441 D(bug("MUIA_Selected was set in OM_NEW, "
442 "although being in MUIV_InputMode_RelVerify\n"));
443 data->mad_Flags &= ~MADF_SELECTED;
446 data->mad_ehn.ehn_Events = 0; /* Will be filled on demand */
447 data->mad_ehn.ehn_Priority = -5;
449 /* Please also send mui key events to us, no idea if mui handles this
450 * like this */
451 data->mad_ehn.ehn_Flags = MUI_EHF_ALWAYSKEYS;
452 data->mad_ehn.ehn_Object = obj;
453 data->mad_ehn.ehn_Class = cl;
455 data->mad_hiehn.ehn_Events = 0;
456 data->mad_hiehn.ehn_Priority = -10;
457 data->mad_hiehn.ehn_Flags = MUI_EHF_HANDLEINPUT;
458 data->mad_hiehn.ehn_Object = obj;
459 data->mad_hiehn.ehn_Class = 0;
461 return (IPTR) obj;
464 /**************************************************************************
465 OM_DISPOSE
466 **************************************************************************/
467 static IPTR Area__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
469 struct MUI_AreaData *data = INST_DATA(cl, obj);
471 /* Safe to call this with NULL */
472 zune_image_spec_free(data->mad_BackgroundSpec);
474 return DoSuperMethodA(cl, obj, msg);
478 /**************************************************************************
479 OM_SET
480 **************************************************************************/
481 static IPTR Area__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
483 struct MUI_AreaData *data = INST_DATA(cl, obj);
484 struct TagItem *tags = msg->ops_AttrList;
485 struct TagItem *tag;
486 CONST_STRPTR old_backgroundspec;
488 int change_disable = 0; /* Has the disable state changed? */
490 while ((tag = NextTagItem(&tags)) != NULL)
492 switch (tag->ti_Tag)
494 case MUIA_Background:
495 old_backgroundspec = data->mad_BackgroundSpec;
496 data->mad_BackgroundSpec =
497 zune_image_spec_duplicate(tag->ti_Data);
498 if (!data->mad_BackgroundSpec)
500 /* Out of memory */
501 data->mad_BackgroundSpec = old_backgroundspec;
502 break;
505 data->mad_Flags |= MADF_OWNBG;
507 if (old_backgroundspec
508 && (strcmp(data->mad_BackgroundSpec,
509 old_backgroundspec) == 0))
511 /* New background does not differ from old one */
512 zune_image_spec_free(old_backgroundspec);
513 tag->ti_Tag = TAG_IGNORE;
514 break;
517 zune_image_spec_free(old_backgroundspec);
519 if (data->mad_Background)
521 if (_flags(obj) & MADF_CANDRAW)
523 zune_imspec_hide(data->mad_Background);
525 if (_flags(obj) & MADF_SETUP)
527 zune_imspec_cleanup(data->mad_Background);
528 data->mad_Background = NULL;
532 if (_flags(obj) & MADF_SETUP)
534 data->mad_Background =
535 zune_imspec_setup((IPTR) data->mad_BackgroundSpec,
536 muiRenderInfo(obj));
538 if (_flags(obj) & MADF_CANDRAW)
540 zune_imspec_show(data->mad_Background, obj);
542 MUI_Redraw(obj, MADF_DRAWOBJECT);
543 break;
545 case MUIA_FillArea:
546 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_FILLAREA);
547 break;
549 case MUIA_Frame:
550 /* this is not documented in MUI but it is possible,
551 and needed to suppress frame for external images */
552 data->mad_Frame = tag->ti_Data;
553 if (muiGlobalInfo(obj))
555 set_inner_sizes(obj, data);
556 set_title_sizes(obj, data);
558 break;
560 case MUIA_ControlChar:
561 if (_flags(obj) & MADF_SETUP)
562 cleanup_control_char(data, obj);
563 data->mad_ControlChar = tag->ti_Data;
564 if (_flags(obj) & MADF_SETUP)
565 setup_control_char(data, obj, cl);
566 break;
568 case MUIA_CycleChain:
569 // if (data->mad_InputMode == MUIV_InputMode_None)
570 // break;
572 if ((!(_flags(obj) & MADF_CYCLECHAIN) && tag->ti_Data)
573 || ((_flags(obj) & MADF_CYCLECHAIN) && !tag->ti_Data))
575 if (_flags(obj) & MADF_SETUP)
577 cleanup_control_char(data, obj);
578 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
579 MADF_CYCLECHAIN);
580 setup_control_char(data, obj, cl);
582 else
583 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
584 MADF_CYCLECHAIN);
586 break;
588 case MUIA_Disabled:
589 if (tag->ti_Data)
591 if (!data->mad_DisableCount)
593 data->mad_DisableCount = 1;
594 change_disable = 1;
597 else
599 if (data->mad_DisableCount)
601 data->mad_DisableCount = 0;
602 change_disable = 1;
605 break;
607 case MUIA_NestedDisabled:
608 if (tag->ti_Data)
610 if (!data->mad_DisableCount)
611 change_disable = 1;
612 data->mad_DisableCount++;
614 else
616 if (data->mad_DisableCount)
618 data->mad_DisableCount--;
619 if (!data->mad_DisableCount)
620 change_disable = 1;
623 break;
626 case MUIA_HorizWeight:
627 data->mad_HorizWeight = tag->ti_Data;
628 break;
630 case MUIA_Pressed:
631 if (tag->ti_Data)
632 data->mad_Flags |= MADF_PRESSED;
633 else
634 data->mad_Flags &= ~MADF_PRESSED;
635 break;
637 case MUIA_ShortHelp:
638 data->mad_ShortHelp = (STRPTR) tag->ti_Data;
639 break;
641 case MUIA_ShowMe:
643 ULONG oldflags = data->mad_Flags;
644 int recalc = 0;
646 if (tag->ti_Data)
647 data->mad_Flags |= MADF_SHOWME;
648 else
649 data->mad_Flags &= ~MADF_SHOWME;
651 if (oldflags != data->mad_Flags)
653 if (!tag->ti_Data)
655 /* Should be made invisible, so send a MUIM_Hide and
656 ** then a MUIM_Cleanup to the object if needed,
657 ** as objects with MUIA_ShowMe to false get neither
658 ** MUIM_Setup nor MUIM_Show */
659 if (_flags(obj) & MADF_CANDRAW)
661 DoHideMethod(obj);
662 recalc = 1;
664 #if 0 /* SHOWME affects only show/hide */
665 if (_flags(obj) & MADF_SETUP)
666 DoMethod(obj, MUIM_Cleanup);
667 #endif
669 else
671 Object *parent = _parent(obj);
672 /* Will be NULL if direct child of a window! */
674 if (parent)
676 #if 0 /* SHOWME affects only show/hide */
677 if (_flags(parent) & MADF_SETUP)
678 DoSetupMethod(obj, muiRenderInfo(parent));
679 #endif
680 if (_flags(parent) & MADF_CANDRAW)
682 DoShowMethod(obj);
683 recalc = 1;
686 else
688 /* Check if window is open... */
692 /* If renderinfo is NULL _win(obj) doesn't work (crash) */
693 if (recalc && muiRenderInfo(obj))
695 DoMethod(_win(obj), MUIM_Window_RecalcDisplay,
696 (IPTR) _parent(obj));
700 break;
702 case MUIA_Selected:
703 /* D(bug(" Area_Set(%p) :
704 MUIA_Selected val=%ld sss=%d\n", obj, tag->ti_Data,
705 !!(data->mad_Flags & MADF_SHOWSELSTATE)));
707 if (tag->ti_Data && !(data->mad_Flags & MADF_SELECTED))
709 data->mad_Flags |= MADF_SELECTED;
710 MUI_Redraw(obj, MADF_DRAWOBJECT);
712 else if (!tag->ti_Data && (data->mad_Flags & MADF_SELECTED))
714 data->mad_Flags &= ~MADF_SELECTED;
715 MUI_Redraw(obj, MADF_DRAWOBJECT);
717 #if 0 // CHECKME: What's the purpose of this? What superclass will care?
718 else
720 tag->ti_Tag = TAG_IGNORE;
722 #endif
723 break;
725 case MUIA_Timer:
726 data->mad_Timeval = tag->ti_Data;
727 break;
729 case MUIA_VertWeight:
730 data->mad_VertWeight = tag->ti_Data;
731 break;
733 case MUIA_Draggable:
734 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DRAGGABLE);
735 break;
737 case MUIA_Dropable:
738 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DROPABLE);
739 break;
741 case MUIA_ContextMenu:
742 data->mad_ContextMenu = (Object *) tag->ti_Data;
743 break;
745 case MUIA_Font:
746 data->mad_FontPreset = tag->ti_Data;
747 break;
749 case MUIA_InputMode:
750 data->mad_InputMode = tag->ti_Data;
751 break;
756 if (change_disable)
758 MUI_Redraw(obj, MADF_DRAWOBJECT);
761 return DoSuperMethodA(cl, obj, (Msg) msg);
765 /**************************************************************************
766 OM_GET
767 **************************************************************************/
768 static IPTR Area__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
770 #define STORE *(msg->opg_Storage)
772 struct MUI_AreaData *data = INST_DATA(cl, obj);
774 switch (msg->opg_AttrID)
776 case MUIA_Background:
777 STORE = (IPTR) data->mad_Background;
778 return TRUE;
780 case MUIA_BottomEdge:
781 STORE = (IPTR) _bottom(obj);
782 return TRUE;
784 case MUIA_ControlChar:
785 STORE = data->mad_ControlChar;
786 return TRUE;
788 case MUIA_CycleChain:
789 STORE = ((data->mad_Flags & MADF_CYCLECHAIN) != 0);
790 return TRUE;
792 case MUIA_Disabled:
793 case MUIA_NestedDisabled:
794 STORE = ! !data->mad_DisableCount; /* BOOLEAN */
795 return TRUE;
797 case MUIA_Font:
798 STORE = (IPTR) data->mad_FontPreset;
799 return TRUE;
801 case MUIA_Height:
802 STORE = (IPTR) _height(obj);
803 return TRUE;
805 case MUIA_HorizWeight:
806 STORE = (IPTR) data->mad_HorizWeight;
807 return TRUE;
809 case MUIA_InnerBottom:
810 STORE = (IPTR) data->mad_InnerBottom;
811 return TRUE;
813 case MUIA_InnerLeft:
814 STORE = (IPTR) data->mad_InnerLeft;
815 return TRUE;
817 case MUIA_InnerRight:
818 STORE = (IPTR) data->mad_InnerRight;
819 return TRUE;
821 case MUIA_InnerTop:
822 STORE = (IPTR) data->mad_InnerTop;
823 return TRUE;
825 case MUIA_LeftEdge:
826 STORE = (IPTR) _left(obj);
827 return TRUE;
829 case MUIA_Pressed:
830 STORE = ! !(data->mad_Flags & MADF_PRESSED);
831 return TRUE;
833 case MUIA_RightEdge:
834 STORE = (IPTR) _right(obj);
835 return TRUE;
837 case MUIA_Selected:
838 STORE = ! !(data->mad_Flags & MADF_SELECTED);
839 return TRUE;
841 case MUIA_ShortHelp:
842 STORE = (IPTR) data->mad_ShortHelp;
843 return TRUE;
845 case MUIA_ShowMe:
846 STORE = ! !(data->mad_Flags & MADF_SHOWME);
847 return TRUE;
849 case MUIA_Timer:
850 STORE = data->mad_Timeval;
851 return TRUE;
853 case MUIA_TopEdge:
854 STORE = (IPTR) _top(obj);
855 return TRUE;
857 case MUIA_VertWeight:
858 STORE = (IPTR) data->mad_VertWeight;
859 return TRUE;
861 case MUIA_Width:
862 STORE = (IPTR) _width(obj);
863 return TRUE;
865 case MUIA_Window:
866 if (muiAreaData(obj)->mad_RenderInfo)
867 STORE = (IPTR) _window(obj);
868 else
869 STORE = 0L;
870 return TRUE;
872 case MUIA_WindowObject:
873 if (muiAreaData(obj)->mad_RenderInfo)
874 STORE = (IPTR) _win(obj);
875 else
876 STORE = 0L;
877 return TRUE;
879 case MUIA_ContextMenu:
880 STORE = (IPTR) data->mad_ContextMenu;
881 return TRUE;
883 case MUIA_Frame:
884 STORE = (IPTR) data->mad_Frame;
885 return TRUE;
887 case MUIA_Draggable:
888 STORE = !!(data->mad_Flags & MADF_DRAGGABLE);
889 return TRUE;
891 case MUIA_Dropable:
892 STORE = !!(data->mad_Flags & MADF_DROPABLE);
893 return TRUE;
896 return (DoSuperMethodA(cl, obj, (Msg) msg));
897 #undef STORE
901 /**************************************************************************
902 MUIM_AskMinMax
903 **************************************************************************/
904 static IPTR Area__MUIM_AskMinMax(struct IClass *cl, Object *obj,
905 struct MUIP_AskMinMax *msg)
907 struct MUI_AreaData *data = INST_DATA(cl, obj);
908 const struct ZuneFrameGfx *zframe;
909 const struct MUI_FrameSpec_intern *frame;
910 struct MUI_FrameSpec_intern tempframe;
912 frame = get_intframe(obj, data, &tempframe);
913 zframe = zune_zframe_get(obj, frame);
915 area_update_msizes(obj, data, frame, zframe);
917 msg->MinMaxInfo->MinWidth = _subwidth(obj);
918 msg->MinMaxInfo->MinHeight = _subheight(obj);
920 msg->MinMaxInfo->MaxWidth = msg->MinMaxInfo->MinWidth;
921 msg->MinMaxInfo->MaxHeight = msg->MinMaxInfo->MinHeight;
922 msg->MinMaxInfo->DefWidth = msg->MinMaxInfo->MinWidth;
923 msg->MinMaxInfo->DefHeight = msg->MinMaxInfo->MinHeight;
925 /* D(bug("Area_AskMinMax 0x%lx (%s): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n",
926 obj, data->mad_FrameTitle, */
927 /* msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight, */
928 /* msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight, */
929 /* msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight)); */
931 return TRUE;
935 * Called after MUIM_AskMinMax, to handle fixed and max sizes.
937 void __area_finish_minmax(Object *obj, struct MUI_MinMax *MinMaxInfo)
939 struct MUI_AreaData *data = muiAreaData(obj);
941 if ((_flags(obj) & MADF_FIXHEIGHT) && (data->mad_HardHeight > 0))
943 int h = data->mad_HardHeight + data->mad_subheight;
945 MinMaxInfo->MinHeight =
946 MinMaxInfo->DefHeight =
947 MinMaxInfo->MaxHeight =
948 CLAMP(h, MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
950 else if (data->mad_HardHeightTxt)
952 ZText *text;
954 if ((text =
955 zune_text_new(NULL, data->mad_HardHeightTxt, ZTEXT_ARG_NONE,
956 0)))
958 zune_text_get_bounds(text, obj);
960 MinMaxInfo->MinHeight =
961 MinMaxInfo->DefHeight =
962 MinMaxInfo->MaxHeight =
963 CLAMP(text->height + data->mad_subheight,
964 MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
966 zune_text_destroy(text);
970 else if (_flags(obj) & MADF_MAXHEIGHT)
972 MinMaxInfo->MaxHeight =
973 CLAMP(data->mad_HardHeight + data->mad_subheight,
974 MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
977 if ((_flags(obj) & MADF_FIXWIDTH) && (data->mad_HardWidth > 0))
979 int w = data->mad_HardWidth + data->mad_subwidth;
981 MinMaxInfo->MinWidth =
982 MinMaxInfo->DefWidth =
983 MinMaxInfo->MaxWidth =
984 CLAMP(w, MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
986 else if (data->mad_HardWidthTxt)
988 ZText *text;
990 if ((text =
991 zune_text_new(NULL, data->mad_HardWidthTxt, ZTEXT_ARG_NONE,
992 0)))
994 zune_text_get_bounds(text, obj);
996 MinMaxInfo->MinWidth =
997 MinMaxInfo->DefWidth =
998 MinMaxInfo->MaxWidth =
999 CLAMP(text->width + data->mad_subwidth,
1000 MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
1002 zune_text_destroy(text);
1006 else if (_flags(obj) & MADF_MAXWIDTH)
1008 MinMaxInfo->MaxWidth =
1009 CLAMP(data->mad_HardWidth + data->mad_subwidth,
1010 MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
1013 /* Set minmax */
1014 _minwidth(obj) = MinMaxInfo->MinWidth;
1015 _minheight(obj) = MinMaxInfo->MinHeight;
1016 _maxwidth(obj) = MinMaxInfo->MaxWidth;
1017 _maxheight(obj) = MinMaxInfo->MaxHeight;
1018 _defwidth(obj) = MinMaxInfo->DefWidth;
1019 _defheight(obj) = MinMaxInfo->DefHeight;
1022 /* <-- _top(obj) (frame title position depends of _top(obj))
1023 * ==== Title === <-- frame_top (depends of title, if centered/above)
1024 * | | <-- bgtop (depends of frame, bg always begins under frame)
1025 * | |
1026 * | |
1027 * ============== <-- "bgbottom" and "frame_bottom" (frame overwrites bg (1))
1029 * (1) : needed for phantom frame objects, where no frame overwrites bg, thus bg
1030 * must go as far as theoretical bottom frame border.
1034 * draw object background if MADF_FILLAREA.
1036 static void Area_Draw_handle_background(Object *obj,
1037 struct MUI_AreaData *data, ULONG flags,
1038 const struct ZuneFrameGfx *zframe)
1040 struct MUI_ImageSpec_intern *background;
1041 struct Rectangle r, r2, rects[4];
1042 int i, bgtop, bgleft, bgw, bgh, numrects;
1044 if (!(data->mad_Flags & MADF_SELECTED)
1045 || !(data->mad_Flags & MADF_SHOWSELSTATE))
1046 background = data->mad_Background;
1047 else
1048 background = data->mad_SelBack;
1050 if (zframe->customframe)
1052 bgtop = _top(obj) + data->mad_TitleHeightAbove;
1054 else
1056 bgtop = _top(obj) + data->mad_TitleHeightAbove + zframe->itop;
1059 bgleft = _left(obj);
1060 bgw = _width(obj);
1061 bgh = _height(obj) - bgtop + _top(obj);
1063 r.MinX = bgleft;
1064 r.MinY = bgtop;
1065 r.MaxX = bgleft + bgw - 1;
1066 r.MaxY = bgtop + bgh - 1;
1068 if (data->mad_Flags & MADF_FILLAREA)
1070 rects[0] = r;
1071 numrects = 1;
1073 else
1075 /* MADF_FILLAREA not set. Only draw frame outside of
1076 innerbox (_mleft, _mtop, _mright, _mbottom):
1078 .............
1079 .***********.
1080 .*#########*.
1081 .*#########*.
1082 .***********.
1083 .............
1085 # = innerbox
1086 * = frame outside of innerbox
1087 . = object frame
1090 r2.MinX = _mleft(obj);
1091 r2.MinY = _mtop(obj);
1092 r2.MaxX = _mright(obj);
1093 r2.MaxY = _mbottom(obj);
1095 numrects = SubtractRectFromRect(&r, &r2, rects);
1098 for (i = 0; i < numrects; i++)
1100 if (!background)
1102 /* This will do the rest, TODO: on MADF_DRAWALL we not really
1103 * need to draw this */
1104 /* D(bug(" Area_Draw(%p):%ld: MUIM_DrawBackground\n", obj,
1105 __LINE__)); */
1106 /* ATTENTION: This draws the clipped away regions of the area.
1107 * Comment out and check the result to see what I mean. */
1108 DoMethod(obj, MUIM_DrawBackground,
1109 rects[i].MinX, rects[i].MinY,
1110 rects[i].MaxX - rects[i].MinX + 1,
1111 rects[i].MaxY - rects[i].MinY + 1, rects[i].MinX,
1112 rects[i].MinY, data->mad_Flags);
1114 else
1116 /* D(bug(" Area_Draw(%p):%ld: zune_imspec_draw\n", obj,
1117 __LINE__)); */
1118 zune_imspec_draw(background, data->mad_RenderInfo,
1119 rects[i].MinX, rects[i].MinY,
1120 rects[i].MaxX - rects[i].MinX + 1,
1121 rects[i].MaxY - rects[i].MinY + 1, rects[i].MinX,
1122 rects[i].MinY, 0);
1126 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
1127 WINDOW_REDRAW_WITHOUT_CLEAR)
1129 if (bgtop > _top(obj) && !(flags & MADF_DRAWALL))
1131 /* Fill in the gap produced by the title with the background
1132 * of the parent object but only if
1133 * the upper object hasn't drawn it already
1134 * (which is the case if MADF_DRAWALL is setted) */
1135 DoMethod(obj, MUIM_DrawParentBackground, bgleft, _top(obj), bgw,
1136 bgtop - _top(obj), bgleft, _top(obj), data->mad_Flags);
1143 * draw object frame + title if not MADF_FRAMEPHANTOM.
1145 static void Area_Draw_handle_frame(Object *obj, struct MUI_AreaData *data,
1146 const struct ZuneFrameGfx *zframe)
1148 APTR textdrawclip = (APTR) - 1;
1149 struct Region *region;
1150 int tx;
1151 int tw, frame_height, frame_top;
1152 int addtw;
1153 struct TextExtent te;
1154 int nchars;
1155 int maxtxtwidth;
1157 /* no frametitle, just draw frame and return */
1158 if (!data->mad_FrameTitle)
1160 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1161 _top(obj), _width(obj), _height(obj), _left(obj), _top(obj),
1162 _width(obj), _height(obj));
1163 return;
1166 /* set clipping so that frame is not drawn behind title */
1168 switch (muiGlobalInfo(obj)->mgi_Prefs->group_title_color)
1170 case GROUP_TITLE_COLOR_OUTLINE:
1171 addtw = 2;
1172 break;
1173 case GROUP_TITLE_COLOR_3D:
1174 addtw = 1;
1175 break;
1176 default:
1177 addtw = 0;
1180 maxtxtwidth =
1181 _width(obj) - zframe->ileft - zframe->iright - 2 * 5 - addtw;
1183 nchars = TextFit(_rp(obj), data->mad_FrameTitle,
1184 strlen(data->mad_FrameTitle),
1185 &te, NULL, 1, maxtxtwidth, _font(obj)->tf_YSize);
1187 tw = te.te_Width + addtw;
1188 tx = _left(obj) + (_width(obj) - tw) / 2;
1190 frame_top = _top(obj) + data->mad_TitleHeightAbove;
1191 frame_height = _height(obj) - frame_top + _top(obj);
1193 if ((region = NewRegion()))
1195 struct Rectangle rect;
1196 int hspace = _font(obj)->tf_YSize / 8;
1198 rect.MinX = tx - hspace;
1199 rect.MinY = _top(obj);
1200 rect.MaxX = tx + tw - 1 + hspace;
1201 rect.MaxY = _top(obj) + _font(obj)->tf_YSize - 1;
1202 // frame is not thick enough anyway
1203 OrRectRegion(region, &rect);
1205 rect.MinX = _left(obj);
1206 rect.MinY = _top(obj);
1207 rect.MaxX = _right(obj);
1208 rect.MaxY = _bottom(obj);
1209 XorRectRegion(region, &rect);
1211 textdrawclip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1214 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1215 frame_top, _width(obj), frame_height, _left(obj), frame_top,
1216 _width(obj), frame_height);
1218 if (region && textdrawclip != (APTR) - 1)
1220 MUI_RemoveClipRegion(muiRenderInfo(obj), textdrawclip);
1221 /* DisposeRegion(region);*/ /* sba: DisposeRegion happens in MUI_RemoveClipRegion, this seems wrong to me */
1224 /* Title text drawing */
1225 SetDrMd(_rp(obj), JAM1);
1226 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
1227 if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1228 GROUP_TITLE_COLOR_3D)
1230 Move(_rp(obj), tx + 1, _top(obj) + _font(obj)->tf_Baseline + 1);
1231 Text(_rp(obj), data->mad_FrameTitle, nchars);
1232 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1233 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1234 Text(_rp(obj), data->mad_FrameTitle, nchars);
1236 else if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1237 GROUP_TITLE_COLOR_OUTLINE)
1239 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1241 tx += addtw / 2;
1242 Move(_rp(obj), tx + 1, _top(obj) + _font(obj)->tf_Baseline);
1243 Text(_rp(obj), data->mad_FrameTitle, nchars);
1244 Move(_rp(obj), tx - 1, _top(obj) + _font(obj)->tf_Baseline);
1245 Text(_rp(obj), data->mad_FrameTitle, nchars);
1246 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline + 1);
1247 Text(_rp(obj), data->mad_FrameTitle, nchars);
1248 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline - 1);
1249 Text(_rp(obj), data->mad_FrameTitle, nchars);
1251 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
1252 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1253 Text(_rp(obj), data->mad_FrameTitle, nchars);
1255 else
1257 if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1258 GROUP_TITLE_COLOR_HILITE)
1260 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1262 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1263 Text(_rp(obj), data->mad_FrameTitle, nchars);
1267 /**************************************************************************
1268 MUIM_Draw
1269 **************************************************************************/
1270 static IPTR Area__MUIM_Draw(struct IClass *cl, Object *obj,
1271 struct MUIP_Draw *msg)
1273 struct MUI_AreaData *data = INST_DATA(cl, obj);
1274 const struct ZuneFrameGfx *zframe;
1275 struct TextFont *obj_font = NULL;
1276 ULONG flags = data->mad_Flags & MADF_DRAWFLAGS;
1278 //APTR areaclip;
1280 /* D(bug("Area_Draw(0x%lx) %ldx%ldx%ldx%ld\n", obj, _left(obj),
1281 _top(obj),_right(obj),_bottom(obj))); */
1282 /* D(bug(" Area_Draw(%p) msg=0x%08lx flags=0x%08lx\n", obj, msg->flags,
1283 _flags(obj))); */
1285 if (flags & MADF_DRAWALL)
1286 flags |= MADF_DRAWOBJECT;
1288 msg->flags = flags;
1289 data->mad_Flags &= ~MADF_DRAWFLAGS;
1291 if (!(flags & MADF_DRAWOBJECT))
1293 /* dont draw bg/frame, let subclass redraw content only
1295 return 0;
1299 /* Background can't be drawn without knowing anything about frame, thus some
1300 * calculations are made before background and frame drawing.
1303 /* on selected state, will get the opposite frame */
1304 const struct MUI_FrameSpec_intern *frame;
1305 struct MUI_FrameSpec_intern tempframe;
1306 int state;
1308 frame = get_intframe(obj, data, &tempframe);
1309 state = frame->state;
1310 if ((data->mad_Flags & MADF_SELECTED)
1311 && (data->mad_Flags & MADF_SHOWSELSTATE))
1312 state ^= 1;
1314 zframe = zune_zframe_get_with_state(obj, frame, state);
1316 /* update innersizes as there are frames which have different inner
1317 * spacings in selected state */
1318 area_update_msizes(obj, data, frame, zframe);
1321 /* Background drawing */
1322 Area_Draw_handle_background(obj, data, msg->flags, zframe);
1324 obj_font = _font(obj);
1325 _font(obj) = zune_font_get(obj, MUIV_Font_Title);
1326 SetFont(_rp(obj), _font(obj));
1328 /* Frame and frametitle drawing */
1329 if (!(data->mad_Flags & MADF_FRAMEPHANTOM))
1331 Area_Draw_handle_frame(obj, data, zframe);
1334 _font(obj) = obj_font;
1335 SetFont(_rp(obj), _font(obj));
1337 /* MUI_RemoveClipping(muiRenderInfo(obj), areaclip);*/
1339 return TRUE;
1342 /**************************************************************************
1343 MUIM_DrawParentBackground
1344 **************************************************************************/
1345 static IPTR Area__MUIM_DrawParentBackground(struct IClass *cl, Object *obj,
1346 struct MUIP_DrawParentBackground *msg)
1348 struct MUI_AreaData *data = INST_DATA(cl, obj);
1349 Object *parent = NULL;
1351 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1352 return FALSE;
1354 get(obj, MUIA_Parent, &parent);
1355 if (parent)
1357 DoMethod(parent, MUIM_DrawBackground, msg->left, msg->top,
1358 msg->width, msg->height, msg->xoffset, msg->yoffset,
1359 msg->flags);
1361 else
1363 D(bug
1364 ("Area_DrawParentBackground(%p) : MUIM_Window_DrawBackground\n",
1365 obj));
1366 DoMethod(_win(obj), MUIM_Window_DrawBackground, msg->left, msg->top,
1367 msg->width, msg->height, msg->xoffset, msg->yoffset,
1368 msg->flags);
1370 return TRUE;
1373 /**************************************************************************
1374 MUIM_DrawBackground
1375 **************************************************************************/
1376 static IPTR Area__MUIM_DrawBackground(struct IClass *cl, Object *obj,
1377 struct MUIP_DrawBackground *msg)
1379 struct MUI_AreaData *data = INST_DATA(cl, obj);
1380 struct MUI_ImageSpec_intern *bg;
1381 LONG state;
1383 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1384 return FALSE;
1386 if ((msg->flags & MADF_SELECTED) && (msg->flags & MADF_SHOWSELSTATE)
1387 && data->mad_SelBack)
1389 /* D(bug("Area_DrawBackground(%p): selected bg\n", obj)); */
1390 bg = data->mad_SelBack;
1391 state = IDS_SELECTED;
1393 else
1395 /* D(bug("Area_DrawBackground(%p): normal bg\n", obj)); */
1396 bg = data->mad_Background;
1397 state = IDS_NORMAL;
1400 const struct ZuneFrameGfx *zframe;
1401 const struct MUI_FrameSpec_intern *frame;
1402 struct MUI_FrameSpec_intern tempframe;
1404 if (!bg)
1406 D(bug("Area_DrawBackground(%p) : MUIM_DrawParentBackground\n",
1407 obj));
1409 return DoMethod(obj, MUIM_DrawParentBackground, msg->left, msg->top,
1410 msg->width, msg->height, msg->xoffset, msg->yoffset,
1411 msg->flags);
1414 frame = get_intframe(obj, data, &tempframe);
1416 int xstate = frame->state;
1417 if ((data->mad_Flags & MADF_SELECTED)
1418 && (data->mad_Flags & MADF_SHOWSELSTATE))
1419 xstate ^= 1;
1421 zframe = zune_zframe_get_with_state(obj, frame, xstate);
1423 if (zframe->customframe == NULL)
1425 /* D(bug("Area_DrawBackground(%p): draw bg\n", obj)); */
1426 zune_imspec_draw(bg, data->mad_RenderInfo,
1427 msg->left, msg->top, msg->width, msg->height,
1428 msg->xoffset, msg->yoffset, state);
1430 // if (!data->mad_FrameTitle)
1431 // {
1434 else
1436 if (zframe->noalpha == FALSE)
1438 zune_imspec_draw(bg, data->mad_RenderInfo,
1439 msg->left, msg->top, msg->width, msg->height,
1440 msg->xoffset, msg->yoffset, state);
1445 if (zframe->customframe)
1447 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1448 _top(obj), _width(obj), _height(obj), msg->left, msg->top,
1449 msg->width, msg->height);
1452 return TRUE;
1455 static IPTR Area__MUIM_DrawBackgroundBuffered(struct IClass *cl,
1456 Object *obj, struct MUIP_DrawBackgroundBuffered *msg)
1458 struct MUI_AreaData *data = INST_DATA(cl, obj);
1459 struct MUI_ImageSpec_intern *bg;
1460 LONG state = 0;
1462 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1463 return FALSE;
1465 bg = data->mad_Background;
1467 /* D(bug("Area_DrawBackground(%p): draw bg\n", obj)); */
1468 zune_imspec_drawbuffered(bg, msg->rp, data->mad_RenderInfo,
1469 msg->left, msg->top, msg->width, msg->height,
1470 msg->xoffset + msg->left, msg->yoffset + msg->top, state, msg->left,
1471 msg->top, 1, _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj));
1473 return TRUE;
1476 /* Perverting the EventHandlerNode structure to specify a shortcut.
1478 static void setup_control_char(struct MUI_AreaData *data, Object *obj,
1479 struct IClass *cl)
1481 if (data->mad_ControlChar != 0 || data->mad_Flags & MADF_CYCLECHAIN)
1483 data->mad_ccn.ehn_Events = data->mad_ControlChar;
1484 switch (data->mad_InputMode)
1486 case MUIV_InputMode_RelVerify:
1487 data->mad_ccn.ehn_Flags = MUIKEY_PRESS;
1488 break;
1489 case MUIV_InputMode_Toggle:
1490 data->mad_ccn.ehn_Flags = MUIKEY_TOGGLE;
1491 break;
1492 case MUIV_InputMode_Immediate:
1493 data->mad_ccn.ehn_Flags = MUIKEY_PRESS;
1494 break;
1496 data->mad_ccn.ehn_Priority = 0;
1497 data->mad_ccn.ehn_Object = obj;
1498 data->mad_ccn.ehn_Class = cl;
1499 DoMethod(_win(obj), MUIM_Window_AddControlCharHandler,
1500 (IPTR) & data->mad_ccn);
1505 static void cleanup_control_char(struct MUI_AreaData *data, Object *obj)
1507 if (data->mad_ControlChar != 0 || data->mad_Flags & MADF_CYCLECHAIN)
1509 DoMethod(_win(obj),
1510 MUIM_Window_RemControlCharHandler, (IPTR) & data->mad_ccn);
1514 static const struct MUI_FrameSpec_intern *get_intframe(Object *obj,
1515 struct MUI_AreaData *data, struct MUI_FrameSpec_intern *tempstore)
1517 if (data->mad_Frame > 100)
1519 /* Frame is spec in string format. Store it in tempstore and return
1520 a pointer to it. The caller should have such a temp variable on
1521 the stack. Don't want to add it to MUI_AreaData as that will
1522 increase mem usage of every object. */
1524 if (zune_frame_spec_to_intern((CONST_STRPTR) data->mad_Frame,
1525 tempstore))
1527 return tempstore;
1529 else
1531 return &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_None];
1534 else
1536 /* Frame is MUIV_Frame_<something> */
1537 return &muiGlobalInfo(obj)->mgi_Prefs->frames[data->mad_Frame];
1541 static void set_inner_sizes(Object *obj, struct MUI_AreaData *data)
1543 const struct MUI_FrameSpec_intern *frame;
1544 struct MUI_FrameSpec_intern tempframe;
1546 frame = get_intframe(obj, data, &tempframe);
1547 // Use frame inner spacing when not hardcoded
1548 if (!(data->mad_Flags & MADF_INNERLEFT))
1549 data->mad_InnerLeft = frame->innerLeft;
1550 if (!(data->mad_Flags & MADF_INNERTOP))
1551 data->mad_InnerTop = frame->innerTop;
1552 if (!(data->mad_Flags & MADF_INNERRIGHT))
1553 data->mad_InnerRight = frame->innerRight;
1554 if (!(data->mad_Flags & MADF_INNERBOTTOM))
1555 data->mad_InnerBottom = frame->innerBottom;
1559 static void set_title_sizes(Object *obj, struct MUI_AreaData *data)
1561 if (data->mad_FrameTitle)
1563 const struct ZuneFrameGfx *zframe;
1564 const struct MUI_FrameSpec_intern *frame;
1565 struct MUI_FrameSpec_intern tempframe;
1567 frame = get_intframe(obj, data, &tempframe);
1568 zframe = zune_zframe_get(obj, frame);
1570 _font(obj) = zune_font_get(obj, MUIV_Font_Title);
1572 switch (muiGlobalInfo(obj)->mgi_Prefs->group_title_position)
1574 case GROUP_TITLE_POSITION_ABOVE:
1575 data->mad_TitleHeightAbove = _font(obj)->tf_Baseline;
1576 break;
1577 case GROUP_TITLE_POSITION_CENTERED:
1578 data->mad_TitleHeightAbove = _font(obj)->tf_YSize / 2;
1579 break;
1582 data->mad_TitleHeightAdd =
1583 _font(obj)->tf_YSize - data->mad_InnerTop - zframe->itop;
1584 data->mad_TitleHeightBelow =
1585 data->mad_TitleHeightAdd - data->mad_TitleHeightAbove;
1590 /**************************************************************************
1591 First method to be called after an OM_NEW, it is the place
1592 for all initializations depending on the environment, but not
1593 on the gadget size/position. Matched by MUIM_Cleanup.
1594 **************************************************************************/
1595 static IPTR Area__MUIM_Setup(struct IClass *cl, Object *obj,
1596 struct MUIP_Setup *msg)
1598 struct MUI_AreaData *data = INST_DATA(cl, obj);
1599 const struct ZuneFrameGfx *zframe;
1600 const struct MUI_FrameSpec_intern *frame;
1601 struct MUI_FrameSpec_intern tempframe;
1603 muiRenderInfo(obj) = msg->RenderInfo;
1605 if (data->mad_Frame)
1607 /* no frame allowed for root object (see Area.doc) */
1608 Object *rootobj = NULL;
1609 get(_win(obj), MUIA_Window_RootObject, &rootobj);
1610 if (rootobj == obj)
1612 data->mad_Frame = MUIV_Frame_None;
1613 data->mad_FrameTitle = NULL;
1617 set_inner_sizes(obj, data);
1618 set_title_sizes(obj, data);
1620 frame = get_intframe(obj, data, &tempframe);
1621 zframe = zune_zframe_get(obj, frame);
1623 area_update_msizes(obj, data, frame, zframe);
1625 if (data->mad_Flags & MADF_OWNBG)
1627 data->mad_Background =
1628 zune_imspec_setup((IPTR) data->mad_BackgroundSpec,
1629 muiRenderInfo(obj));
1632 if ((data->mad_Flags & MADF_SHOWSELSTATE) &&
1633 (data->mad_InputMode != MUIV_InputMode_None))
1635 data->mad_SelBack =
1636 zune_imspec_setup(MUII_SelectedBack, muiRenderInfo(obj));
1639 if (data->mad_InputMode != MUIV_InputMode_None || data->mad_ContextMenu)
1641 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1642 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1643 (IPTR) & data->mad_ehn);
1646 /* Those are filled by RequestIDCMP() */
1647 if (data->mad_hiehn.ehn_Events)
1648 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1649 (IPTR) & data->mad_hiehn);
1651 setup_control_char(data, obj, cl);
1652 // setup_cycle_chain (data, obj);
1654 if (data->mad_FontPreset == MUIV_Font_Inherit)
1656 if (_parent(obj) != NULL && _parent(obj) != _win(obj))
1657 data->mad_Font = _font(_parent(obj));
1658 else
1660 D(bug("Area_Setup %p: getting normal font\n", obj));
1661 data->mad_Font = zune_font_get(obj, MUIV_Font_Normal);
1662 D(bug("Area_Setup %p: got normal font %p\n", obj,
1663 data->mad_Font));
1666 else
1668 data->mad_Font = zune_font_get(obj, data->mad_FontPreset);
1671 _flags(obj) |= MADF_SETUP;
1673 data->mad_Timer.ihn_Flags = MUIIHNF_TIMER;
1674 data->mad_Timer.ihn_Method = MUIM_Timer;
1675 data->mad_Timer.ihn_Object = obj;
1677 return TRUE;
1681 /**************************************************************************
1682 Called to match a MUIM_Setup, when environment is no more available.
1683 **************************************************************************/
1684 static IPTR Area__MUIM_Cleanup(struct IClass *cl, Object *obj,
1685 struct MUIP_Cleanup *msg)
1687 struct MUI_AreaData *data = INST_DATA(cl, obj);
1689 _flags(obj) &= ~MADF_SETUP;
1691 // cleanup_cycle_chain (data, obj);
1692 cleanup_control_char(data, obj);
1694 if (data->mad_Timer.ihn_Millis)
1696 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
1697 (IPTR) & data->mad_Timer);
1698 data->mad_Timer.ihn_Millis = 0;
1701 /* Remove the handler if it is added */
1702 if (data->mad_hiehn.ehn_Events)
1703 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1704 (IPTR) & data->mad_hiehn);
1706 /* Remove the event handler if it has been added */
1707 if (data->mad_ehn.ehn_Events)
1708 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1709 (IPTR) & data->mad_ehn);
1711 D(bug("Area cleanup %p active=%p\n", obj,
1712 (Object *) XGET(_win(obj), MUIA_Window_ActiveObject)));
1713 if (obj == (Object *) XGET(_win(obj), MUIA_Window_ActiveObject))
1715 D(bug("we are active, unset us\n"));
1716 set(_win(obj), MUIA_Window_ActiveObject,
1717 MUIV_Window_ActiveObject_None);
1720 /* It's safe to call the following function with NULL */
1721 if ((data->mad_Flags & MADF_SHOWSELSTATE) &&
1722 (data->mad_InputMode != MUIV_InputMode_None))
1724 zune_imspec_cleanup(data->mad_SelBack);
1725 data->mad_SelBack = NULL;
1727 if (data->mad_Flags & MADF_OWNBG)
1729 zune_imspec_cleanup(data->mad_Background);
1730 data->mad_Background = NULL;
1733 muiRenderInfo(obj) = NULL;
1735 return TRUE;
1739 /**************************************************************************
1740 Called after the window is open and the area layouted, but before
1741 any drawing. Matched by one MUIM_Hide.
1742 Good place to init things depending on gadget size/position.
1743 **************************************************************************/
1744 static IPTR Area__MUIM_Show(struct IClass *cl, Object *obj,
1745 struct MUIP_Show *msg)
1747 struct MUI_AreaData *data = INST_DATA(cl, obj);
1749 zune_imspec_show(data->mad_Background, obj);
1751 if (data->mad_Flags & MADF_SHOWSELSTATE
1752 && data->mad_InputMode != MUIV_InputMode_None)
1754 zune_imspec_show(data->mad_SelBack, obj);
1757 return TRUE;
1760 /**************************************************************************
1761 Called when the window is about to be closed, to match MUIM_Show.
1762 **************************************************************************/
1763 static IPTR Area__MUIM_Hide(struct IClass *cl, Object *obj,
1764 struct MUIP_Hide *msg)
1766 struct MUI_AreaData *data = INST_DATA(cl, obj);
1768 zune_imspec_hide(data->mad_Background);
1769 if (data->mad_Flags & MADF_SHOWSELSTATE
1770 && data->mad_InputMode != MUIV_InputMode_None)
1772 zune_imspec_hide(data->mad_SelBack);
1775 if (data->mad_ContextZMenu)
1777 zune_close_menu(data->mad_ContextZMenu);
1778 data->mad_ContextZMenu = NULL;
1781 return TRUE;
1784 /**************************************************************************
1785 Called when gadget activated
1786 **************************************************************************/
1787 static IPTR Area__MUIM_GoActive(struct IClass *cl, Object *obj, Msg msg)
1789 //bug("Area_GoActive %p\n", obj);
1790 if (_flags(obj) & MADF_CANDRAW)
1791 _zune_focus_new(obj, ZUNE_FOCUS_TYPE_ACTIVE_OBJ);
1792 return TRUE;
1795 /**************************************************************************
1796 Called when gadget deactivated
1797 **************************************************************************/
1798 static IPTR Area__MUIM_GoInactive(struct IClass *cl, Object *obj, Msg msg)
1800 //bug("Area_GoInactive %p\n", obj);
1801 if (_flags(obj) & MADF_CANDRAW)
1802 _zune_focus_destroy(obj, ZUNE_FOCUS_TYPE_ACTIVE_OBJ);
1803 return TRUE;
1806 /**************************************************************************
1807 This one or derived methods won't be called if short help is
1808 not set in area instdata. So set this to a dummy val if overriding
1809 **************************************************************************/
1810 static IPTR Area__MUIM_CreateShortHelp(struct IClass *cl, Object *obj,
1811 struct MUIP_CreateShortHelp *msg)
1813 struct MUI_AreaData *data = INST_DATA(cl, obj);
1815 return (IPTR) data->mad_ShortHelp;
1818 /**************************************************************************
1820 **************************************************************************/
1821 static IPTR Area__MUIM_DeleteShortHelp(struct IClass *cl, Object *obj,
1822 struct MUIP_DeleteShortHelp *msg)
1824 return TRUE;
1827 /**************************************************************************
1829 **************************************************************************/
1830 static IPTR Area__MUIM_CreateBubble(struct IClass *cl, Object *obj,
1831 struct MUIP_CreateBubble *msg)
1833 return (IPTR) zune_bubble_create(obj, msg->x, msg->y, msg->txt,
1834 msg->flags);
1837 /**************************************************************************
1839 **************************************************************************/
1840 static IPTR Area__MUIM_DeleteBubble(struct IClass *cl, Object *obj,
1841 struct MUIP_DeleteBubble *msg)
1843 zune_bubble_delete(obj, msg->bubble);
1845 return TRUE;
1848 /* either lmb or press key */
1849 static void handle_press(struct IClass *cl, Object *obj)
1851 struct MUI_AreaData *data = INST_DATA(cl, obj);
1853 switch (data->mad_InputMode)
1855 case MUIV_InputMode_RelVerify:
1856 set(obj, MUIA_Timer, ++muiAreaData(obj)->mad_Timeval);
1857 if (!data->mad_Timer.ihn_Millis)
1859 data->mad_Timer.ihn_Millis = 300;
1860 DoMethod(_app(obj), MUIM_Application_AddInputHandler,
1861 (IPTR) & data->mad_Timer);
1863 SetAttrs(obj, MUIA_Selected, TRUE, MUIA_Pressed, TRUE, TAG_DONE);
1864 break;
1866 case MUIV_InputMode_Immediate:
1868 IPTR selected = FALSE;
1870 get(obj, MUIA_Selected, &selected);
1871 if (selected)
1873 /* D(bug("handle_press(%p) : nnset MUIA_Selected FALSE\n", obj)); */
1874 nnset(obj, MUIA_Selected, FALSE);
1876 /* D(bug("handle_press(%p) : set MUIA_Selected TRUE\n", obj)); */
1877 set(obj, MUIA_Selected, TRUE);
1878 /* D(bug("handle_press(%p) : done\n", obj)); */
1879 break;
1881 case MUIV_InputMode_Toggle:
1882 // although undocumented, MUI sets MUIA_Pressed too
1883 SetAttrs(obj, MUIA_Selected, !(data->mad_Flags & MADF_SELECTED),
1884 MUIA_Pressed, !(data->mad_Flags & MADF_PRESSED), TAG_DONE);
1885 break;
1889 /* either lmb or release key */
1890 static void handle_release(struct IClass *cl, Object *obj, int cancel)
1892 struct MUI_AreaData *data = INST_DATA(cl, obj);
1894 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
1896 if (data->mad_Flags & MADF_SELECTED)
1898 if (cancel)
1899 nnset(obj, MUIA_Pressed, FALSE);
1900 else
1901 set(obj, MUIA_Pressed, FALSE);
1903 set(obj, MUIA_Selected, FALSE);
1907 if (data->mad_Timer.ihn_Millis)
1909 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
1910 (IPTR) & data->mad_Timer);
1911 data->mad_Timer.ihn_Millis = 0;
1916 static IPTR event_button(Class *cl, Object *obj,
1917 struct IntuiMessage *imsg)
1919 struct MUI_AreaData *data = INST_DATA(cl, obj);
1920 BOOL in = _between(_left(obj), imsg->MouseX, _right(obj))
1921 && _between(_top(obj), imsg->MouseY, _bottom(obj));
1923 switch (imsg->Code)
1925 case SELECTDOWN:
1926 if (data->mad_InputMode == MUIV_InputMode_None)
1927 break;
1929 if (in)
1931 // set(_win(obj), MUIA_Window_ActiveObject, obj);
1932 data->mad_ClickX = imsg->MouseX;
1933 data->mad_ClickY = imsg->MouseY;
1935 if ((data->mad_InputMode != MUIV_InputMode_Toggle)
1936 && (data->mad_Flags & MADF_SELECTED))
1937 break;
1938 nnset(obj, MUIA_Timer, 0);
1939 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
1941 if (data->mad_ehn.ehn_Events)
1942 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1943 (IPTR) &data->mad_ehn);
1944 data->mad_ehn.ehn_Events |= IDCMP_MOUSEMOVE | IDCMP_RAWKEY;
1945 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1946 (IPTR) &data->mad_ehn);
1948 handle_press(cl, obj);
1949 return MUI_EventHandlerRC_Eat;
1951 break;
1953 case SELECTUP:
1954 if (data->mad_InputMode == MUIV_InputMode_None)
1955 break;
1957 if (data->mad_ehn.ehn_Events != IDCMP_MOUSEBUTTONS)
1959 /* Extra events must have been added by SELECTDOWN case above,
1960 so this object is waiting to be unclicked (RelVerify) */
1961 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1962 (IPTR) &data->mad_ehn);
1963 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1964 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1965 (IPTR) &data->mad_ehn);
1966 if (!in)
1967 nnset(obj, MUIA_Pressed, FALSE);
1968 handle_release(cl, obj, FALSE /* cancel */ );
1969 return MUI_EventHandlerRC_Eat;
1971 break;
1973 case MENUDOWN:
1974 if (in && data->mad_ContextMenu)
1976 Object *menuobj =
1977 (Object *) DoMethod(obj, MUIM_ContextMenuBuild,
1978 imsg->MouseX, imsg->MouseY);
1979 if (menuobj)
1981 struct NewMenu *newmenu = NULL;
1983 /* stegerg: HACKME, CHECKME! The menu/menu item objs should
1984 automatically be connected (parentobject setup) without
1985 need for this, but they aren't. Because of how family
1986 class is and is used by other classes, I think!? */
1987 DoMethod(menuobj, MUIM_ConnectParent, obj);
1989 get(menuobj, MUIA_Menuitem_NewMenu, &newmenu);
1990 if (newmenu)
1992 if (data->mad_ContextZMenu)
1993 zune_close_menu(data->mad_ContextZMenu);
1994 data->mad_ContextZMenu =
1995 zune_open_menu(_window(obj), newmenu);
1998 if (data->mad_ehn.ehn_Events)
1999 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2000 (IPTR) &data->mad_ehn);
2001 data->mad_ehn.ehn_Events |= IDCMP_MOUSEMOVE;
2002 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2003 (IPTR) &data->mad_ehn);
2005 return MUI_EventHandlerRC_Eat;
2007 break;
2009 case MENUUP:
2010 if (data->mad_ContextZMenu)
2012 struct MenuItem *item = zune_leave_menu(data->mad_ContextZMenu);
2014 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2015 (IPTR) &data->mad_ehn);
2016 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2017 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2018 (IPTR) &data->mad_ehn);
2020 if (item)
2022 Object *itemobj = (Object *) GTMENUITEM_USERDATA(item);
2024 /* CHECKME: MUIA_MenuItem_Trigger should probably be set inside
2025 MUIM_ContextMenuChoice!? But there I only know about
2026 itemobj, not MenuItem itself! */
2027 if (item->Flags & CHECKIT)
2029 set(itemobj, MUIA_Menuitem_Checked,
2030 ! !(item->Flags & CHECKED));
2034 set(itemobj, MUIA_Menuitem_Trigger, item);
2036 DoMethod(obj, MUIM_ContextMenuChoice, itemobj);
2040 zune_close_menu(data->mad_ContextZMenu);
2041 data->mad_ContextZMenu = NULL;
2043 return MUI_EventHandlerRC_Eat;
2046 break;
2049 return 0;
2052 static IPTR event_motion(Class *cl, Object *obj,
2053 struct IntuiMessage *imsg)
2055 struct MUI_AreaData *data = INST_DATA(cl, obj);
2057 if ((imsg->Qualifier & IEQUALIFIER_RBUTTON) && data->mad_ContextZMenu)
2059 zune_mouse_update(data->mad_ContextZMenu, 0);
2060 return MUI_EventHandlerRC_Eat;
2063 if (imsg->Qualifier & IEQUALIFIER_LEFTBUTTON)
2065 BOOL in = _between(_left(obj), imsg->MouseX, _right(obj))
2066 && _between(_top(obj), imsg->MouseY, _bottom(obj));
2068 if (in)
2070 if ((data->mad_Flags & MADF_DRAGGABLE)
2071 && ((abs(data->mad_ClickX - imsg->MouseX) >= 3)
2072 || (abs(data->mad_ClickY - imsg->MouseY) >= 3)))
2073 /* should be user configurable */
2075 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
2076 set(obj, MUIA_Selected, FALSE);
2077 nnset(obj, MUIA_Pressed, FALSE);
2079 if (data->mad_ehn.ehn_Events)
2080 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2081 (IPTR) &data->mad_ehn);
2082 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2083 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2084 (IPTR) &data->mad_ehn);
2085 if (data->mad_Timer.ihn_Millis)
2087 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
2088 (IPTR) & data->mad_Timer);
2089 data->mad_Timer.ihn_Millis = 0;
2092 DoMethod(obj, MUIM_DoDrag, data->mad_ClickX - _left(obj),
2093 data->mad_ClickY - _top(obj), 0);
2094 return MUI_EventHandlerRC_Eat;
2098 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
2100 if (!in && (data->mad_Flags & MADF_SELECTED)) /* going out */
2102 set(obj, MUIA_Selected, FALSE);
2104 else if (in && !(data->mad_Flags & MADF_SELECTED)) /* going in */
2106 set(obj, MUIA_Selected, TRUE);
2110 return MUI_EventHandlerRC_Eat;
2113 /**************************************************************************
2115 **************************************************************************/
2116 static IPTR Area__MUIM_HandleEvent(struct IClass *cl, Object *obj,
2117 struct MUIP_HandleEvent *msg)
2119 struct MUI_AreaData *data = INST_DATA(cl, obj);
2121 if (data->mad_DisableCount)
2122 return 0;
2123 if (data->mad_InputMode == MUIV_InputMode_None
2124 && !data->mad_ContextMenu)
2125 return 0;
2127 if (msg->muikey != MUIKEY_NONE)
2129 switch (msg->muikey)
2131 case MUIKEY_PRESS:
2132 if (data->mad_Flags & MADF_SELECTED)
2133 break;
2134 if (data->mad_ehn.ehn_Events)
2135 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2136 (IPTR) &data->mad_ehn);
2137 data->mad_ehn.ehn_Events |= IDCMP_RAWKEY;
2138 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2139 (IPTR) &data->mad_ehn);
2140 handle_press(cl, obj);
2141 return MUI_EventHandlerRC_Eat;
2143 case MUIKEY_TOGGLE:
2144 if (data->mad_InputMode == MUIV_InputMode_Toggle)
2145 set(obj, MUIA_Selected, !(data->mad_Flags & MADF_SELECTED));
2146 return MUI_EventHandlerRC_Eat;
2148 case MUIKEY_RELEASE:
2149 if (data->mad_ehn.ehn_Events)
2150 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2151 (IPTR) &data->mad_ehn);
2152 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2153 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2154 (IPTR) &data->mad_ehn);
2155 handle_release(cl, obj, FALSE /* cancel */ );
2156 return MUI_EventHandlerRC_Eat;
2158 return 0;
2161 if (msg->imsg)
2163 switch (msg->imsg->Class)
2165 case IDCMP_MOUSEBUTTONS:
2166 return event_button(cl, obj, msg->imsg);
2167 case IDCMP_MOUSEMOVE:
2168 return event_motion(cl, obj, msg->imsg);
2169 case IDCMP_RAWKEY:
2171 unsigned char code;
2172 UWORD msg_code;
2173 /* Remove the up prefix as convert key does not convert an
2174 * upkey event */
2175 msg_code = msg->imsg->Code;
2176 msg->imsg->Code &= ~IECODE_UP_PREFIX;
2177 code = ConvertKey(msg->imsg);
2178 msg->imsg->Code = msg_code;
2180 if (code != 0 && code == data->mad_ControlChar)
2182 if (msg->imsg->Code & IECODE_UP_PREFIX)
2184 msg->muikey = MUIKEY_RELEASE;
2186 else
2188 msg->muikey = MUIKEY_PRESS;
2190 msg->imsg = NULL;
2191 return Area__MUIM_HandleEvent(cl, obj, msg);
2194 if (msg->imsg->
2195 Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
2197 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2198 (IPTR) &data->mad_ehn);
2199 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2200 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2201 (IPTR) &data->mad_ehn);
2202 handle_release(cl, obj, TRUE /* cancel */ );
2204 return MUI_EventHandlerRC_Eat;
2206 break;
2209 return 0;
2212 /**************************************************************************
2214 **************************************************************************/
2215 static IPTR Area__MUIM_HandleInput(struct IClass *cl, Object *obj,
2216 struct MUIP_HandleInput *msg)
2218 /* Actually a dummy, but real MUI does handle here the input stuff which
2219 * Zune has in Area_HandleEvent. For compatibility we should do this too */
2220 //bug("Area_HandleEvent [%p] imsg=%p muikey=%ld\b", obj, msg->imsg,
2221 // msg->muikey);
2222 return 0;
2225 /**************************************************************************
2226 Trivial; custom classes may override this to get dynamic menus.
2227 **************************************************************************/
2228 static IPTR Area__MUIM_ContextMenuBuild(struct IClass *cl, Object *obj,
2229 struct MUIP_ContextMenuBuild *msg)
2231 struct MUI_AreaData *data = INST_DATA(cl, obj);
2232 return (IPTR) data->mad_ContextMenu; /* a Menustrip object */
2235 /**************************************************************************/
2236 static IPTR Area__MUIM_ContextMenuChoice(struct IClass *cl, Object *obj,
2237 struct MUIP_ContextMenuChoice *msg)
2239 set(obj, MUIA_ContextMenuTrigger, msg->item);
2240 return 0;
2244 /**************************************************************************
2245 MUIM_Export : to export an object's "contents" to a dataspace object.
2246 **************************************************************************/
2247 static IPTR Area__MUIM_Export(struct IClass *cl, Object *obj,
2248 struct MUIP_Export *msg)
2250 struct MUI_AreaData *data = INST_DATA(cl, obj);
2251 ULONG id;
2253 if ((id = muiNotifyData(obj)->mnd_ObjectID))
2255 char selected = (data->mad_Flags & MADF_SELECTED) ? 1 : 0;
2256 DoMethod(msg->dataspace, MUIM_Dataspace_Add, (IPTR) & selected,
2257 sizeof(char), (IPTR) id);
2259 return 0;
2263 /**************************************************************************
2264 MUIM_Import : to import an object's "contents" from a dataspace object.
2265 **************************************************************************/
2266 static IPTR Area__MUIM_Import(struct IClass *cl, Object *obj,
2267 struct MUIP_Import *msg)
2269 ULONG id;
2271 if ((id = muiNotifyData(obj)->mnd_ObjectID))
2273 char *selected =
2274 (char *)DoMethod(msg->dataspace, MUIM_Dataspace_Find,
2275 (IPTR) id);
2277 if (selected)
2278 set(obj, MUIA_Selected, *selected);
2280 return 0;
2283 /**************************************************************************
2284 MUIM_Timer
2285 **************************************************************************/
2286 static IPTR Area__MUIM_Timer(struct IClass *cl, Object *obj, Msg msg)
2288 struct MUI_AreaData *data = INST_DATA(cl, obj);
2289 if (data->mad_Timer.ihn_Millis)
2290 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
2291 (IPTR) & data->mad_Timer);
2292 data->mad_Timer.ihn_Millis = 50;
2293 DoMethod(_app(obj), MUIM_Application_AddInputHandler,
2294 (IPTR) & data->mad_Timer);
2296 if (data->mad_Flags & MADF_SELECTED)
2297 set(obj, MUIA_Timer, ++muiAreaData(obj)->mad_Timeval);
2298 return 0;
2301 /**************************************************************************
2302 MUIM_DoDrag
2303 **************************************************************************/
2304 static IPTR Area__MUIM_DoDrag(struct IClass *cl, Object *obj,
2305 struct MUIP_DoDrag *msg)
2307 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2308 DoMethod(_win(obj), MUIM_Window_DragObject, (IPTR) obj, msg->touchx,
2309 msg->touchy, msg->flags);
2310 return 0;
2313 /**************************************************************************
2314 MUIM_CreateDragImage
2315 **************************************************************************/
2316 static IPTR Area__MUIM_CreateDragImage(struct IClass *cl, Object *obj,
2317 struct MUIP_CreateDragImage *msg)
2319 struct MUI_DragImage *img = (struct MUI_DragImage *)
2320 AllocVec(sizeof(struct MUI_DragImage), MEMF_CLEAR);
2321 if (img)
2323 const struct ZuneFrameGfx *zframe;
2324 LONG depth =
2325 GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
2327 zframe =
2328 zune_zframe_get(obj,
2329 &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Drag]);
2331 img->width = _width(obj) + zframe->ileft + zframe->iright;
2332 img->height = _height(obj) + zframe->itop + zframe->ibottom;
2334 if ((img->bm =
2335 AllocBitMap(img->width, img->height, depth, BMF_MINPLANES,
2336 _screen(obj)->RastPort.BitMap)))
2338 /* Render the stuff now */
2339 struct RastPort *rp_save = muiRenderInfo(obj)->mri_RastPort;
2340 struct RastPort temprp;
2341 InitRastPort(&temprp);
2342 temprp.BitMap = img->bm;
2343 ClipBlit(_rp(obj), _left(obj), _top(obj), &temprp,
2344 zframe->ileft, zframe->itop, _width(obj), _height(obj),
2345 0xc0);
2347 muiRenderInfo(obj)->mri_RastPort = &temprp;
2348 zframe->draw(zframe->customframe, muiRenderInfo(obj), 0, 0,
2349 img->width, img->height, 0, 0, img->width, img->height);
2350 muiRenderInfo(obj)->mri_RastPort = rp_save;
2353 img->touchx = msg->touchx;
2354 img->touchy = msg->touchy;
2355 img->flags = 0;
2357 return (IPTR) img;
2360 /**************************************************************************
2361 MUIM_DeleteDragImage
2362 **************************************************************************/
2363 static IPTR Area__MUIM_DeleteDragImage(struct IClass *cl, Object *obj,
2364 struct MUIP_DeleteDragImage *msg)
2366 if (msg->di)
2368 if (msg->di->bm)
2369 FreeBitMap(msg->di->bm);
2370 FreeVec(msg->di);
2372 return 0;
2375 /**************************************************************************
2376 MUIM_DragQueryExtended
2377 **************************************************************************/
2378 static IPTR Area__MUIM_DragQueryExtended(struct IClass *cl, Object *obj,
2379 struct MUIP_DragQueryExtended *msg)
2381 struct MUI_AreaData *data = INST_DATA(cl, obj);
2382 if (data->mad_Flags & MADF_DROPABLE)
2384 if (_left(obj) <= msg->x && msg->x <= _right(obj)
2385 && _top(obj) <= msg->y && msg->y <= _bottom(obj))
2387 if (DoMethod(obj, MUIM_DragQuery,
2388 (IPTR) msg->obj) == MUIV_DragQuery_Accept)
2389 return (IPTR) obj;
2392 return 0;
2395 /**************************************************************************
2396 MUIM_DragBegin
2397 **************************************************************************/
2398 static IPTR Area__MUIM_DragBegin(struct IClass *cl, Object *obj,
2399 struct MUIP_DragBegin *msg)
2401 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2402 _zune_focus_new(obj, ZUNE_FOCUS_TYPE_DROP_OBJ);
2403 return 0;
2406 /**************************************************************************
2407 MUIM_DragFinish
2408 **************************************************************************/
2409 static IPTR Area__MUIM_DragFinish(struct IClass *cl, Object *obj,
2410 struct MUIP_DragFinish *msg)
2412 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2413 _zune_focus_destroy(obj, ZUNE_FOCUS_TYPE_DROP_OBJ);
2414 return 0;
2419 * Calculates addleft, addtop, subwidth, subheight from current settings.
2420 * If frame phantom, ignore horizontal frame components.
2421 * Depends on inner sizes and frame
2423 static void area_update_msizes(Object *obj, struct MUI_AreaData *data,
2424 const struct MUI_FrameSpec_intern *frame,
2425 const struct ZuneFrameGfx *zframe)
2428 /* if (XGET(obj, MUIA_UserData) == 42) */
2429 /* { */
2430 /* D(bug("area_update_msizes(%p) : ileft=%ld itop=%ld\n", obj, */
2431 /* zframe->ileft, zframe->itop)); */
2432 /* } */
2434 struct dt_frame_image *fi = zframe->customframe;
2436 if (fi != NULL)
2438 //UWORD w = fi->tile_left + fi->tile_right;
2439 //UWORD h = fi->tile_top + fi->tile_bottom;
2441 data->mad_addleft = data->mad_InnerLeft + zframe->ileft;
2442 data->mad_subwidth =
2443 data->mad_addleft + data->mad_InnerRight + zframe->iright;
2444 data->mad_addtop =
2445 data->mad_InnerTop + data->mad_TitleHeightAdd + zframe->itop;
2446 data->mad_subheight =
2447 data->mad_addtop + data->mad_InnerBottom + zframe->ibottom;
2449 else
2451 data->mad_addleft = data->mad_InnerLeft + zframe->ileft;
2452 data->mad_subwidth =
2453 data->mad_addleft + data->mad_InnerRight + zframe->iright;
2454 data->mad_addtop =
2455 data->mad_InnerTop + data->mad_TitleHeightAdd + zframe->itop;
2456 data->mad_subheight =
2457 data->mad_addtop + data->mad_InnerBottom + zframe->ibottom;
2460 if (data->mad_Flags & MADF_FRAMEPHANTOM)
2462 data->mad_addleft = 0;
2463 data->mad_subwidth = 0;
2466 // clamping ... maybe ?
2468 /* D(bug("area_update_msizes(%x,%d) => addleft/top=%d/%d, " */
2469 /* "subwidth/height=%d/%d\n", */
2470 /* obj, data->mad_Frame, data->mad_addleft, data->mad_addtop, */
2471 /* data->mad_subwidth, data->mad_subheight)); */
2474 /**************************************************************************
2475 MUIM_Area_UnknownDropDestination
2476 **************************************************************************/
2477 IPTR Area__MUIM_UnknownDropDestination(struct IClass *cl, Object *obj,
2478 struct MUIP_UnknownDropDestination *msg)
2480 return 0;
2483 /**************************************************************************
2484 MUIM_UpdateInnerSizes - Updates the innersizes of an object. You actually
2485 should only call this method if the dimensions of an object would not be
2486 affected, otherwise the results are unexpected
2487 **************************************************************************/
2488 static IPTR Area__MUIM_UpdateInnerSizes(struct IClass *cl, Object *obj,
2489 struct MUIP_UpdateInnerSizes *msg)
2491 struct MUI_AreaData *data = INST_DATA(cl, obj);
2492 const struct ZuneFrameGfx *zframe;
2493 const struct MUI_FrameSpec_intern *frame;
2494 struct MUI_FrameSpec_intern tempframe;
2496 if (_flags(obj) & MADF_SETUP)
2498 frame = get_intframe(obj, data, &tempframe);
2499 zframe = zune_zframe_get(obj, frame);
2500 area_update_msizes(obj, data, frame, zframe);
2502 return 1;
2505 static IPTR Area__MUIM_FindAreaObject(struct IClass *cl, Object *obj,
2506 struct MUIP_FindAreaObject *msg)
2508 if (msg->obj == obj)
2509 return (IPTR) obj;
2510 else
2511 return (IPTR) NULL;
2514 BOOPSI_DISPATCHER(IPTR, Area_Dispatcher, cl, obj, msg)
2516 switch (msg->MethodID)
2518 case OM_NEW:
2519 return Area__OM_NEW(cl, obj, (struct opSet *)msg);
2520 case OM_DISPOSE:
2521 return Area__OM_DISPOSE(cl, obj, msg);
2522 case OM_SET:
2523 return Area__OM_SET(cl, obj, (struct opSet *)msg);
2524 case OM_GET:
2525 return Area__OM_GET(cl, obj, (struct opGet *)msg);
2526 case MUIM_AskMinMax:
2527 return Area__MUIM_AskMinMax(cl, obj, (APTR) msg);
2528 case MUIM_Draw:
2529 return Area__MUIM_Draw(cl, obj, (APTR) msg);
2530 case MUIM_DrawBackground:
2531 return Area__MUIM_DrawBackground(cl, obj, (APTR) msg);
2532 case MUIM_DrawBackgroundBuffered:
2533 return Area__MUIM_DrawBackgroundBuffered(cl, obj, (APTR) msg);
2534 case MUIM_DrawParentBackground:
2535 return Area__MUIM_DrawParentBackground(cl, obj, (APTR) msg);
2536 case MUIM_Setup:
2537 return Area__MUIM_Setup(cl, obj, (APTR) msg);
2538 case MUIM_Cleanup:
2539 return Area__MUIM_Cleanup(cl, obj, (APTR) msg);
2540 case MUIM_Show:
2541 return Area__MUIM_Show(cl, obj, (APTR) msg);
2542 case MUIM_Hide:
2543 return Area__MUIM_Hide(cl, obj, (APTR) msg);
2544 case MUIM_GoActive:
2545 return Area__MUIM_GoActive(cl, obj, (APTR) msg);
2546 case MUIM_GoInactive:
2547 return Area__MUIM_GoInactive(cl, obj, (APTR) msg);
2548 case MUIM_Layout:
2549 return 1;
2550 case MUIM_CreateShortHelp:
2551 return Area__MUIM_CreateShortHelp(cl, obj, (APTR) msg);
2552 case MUIM_DeleteShortHelp:
2553 return Area__MUIM_DeleteShortHelp(cl, obj, (APTR) msg);
2554 case MUIM_CreateBubble:
2555 return Area__MUIM_CreateBubble(cl, obj, (APTR) msg);
2556 case MUIM_DeleteBubble:
2557 return Area__MUIM_DeleteBubble(cl, obj, (APTR) msg);
2558 case MUIM_HandleEvent:
2559 return Area__MUIM_HandleEvent(cl, obj, (APTR) msg);
2560 case MUIM_ContextMenuBuild:
2561 return Area__MUIM_ContextMenuBuild(cl, obj, (APTR) msg);
2562 case MUIM_ContextMenuChoice:
2563 return Area__MUIM_ContextMenuChoice(cl, obj, (APTR) msg);
2564 case MUIM_Timer:
2565 return Area__MUIM_Timer(cl, obj, msg);
2566 case MUIM_UpdateInnerSizes:
2567 return Area__MUIM_UpdateInnerSizes(cl, obj, (APTR) msg);
2568 case MUIM_DragQuery:
2569 return MUIV_DragQuery_Refuse;
2570 case MUIM_DragBegin:
2571 return Area__MUIM_DragBegin(cl, obj, (APTR) msg);
2572 case MUIM_DragDrop:
2573 return FALSE;
2574 case MUIM_UnknownDropDestination:
2575 return Area__MUIM_UnknownDropDestination(cl, obj, (APTR) msg);
2576 case MUIM_DragFinish:
2577 return Area__MUIM_DragFinish(cl, obj, (APTR) msg);
2578 case MUIM_DragReport:
2579 return MUIV_DragReport_Continue; /* or MUIV_DragReport_Abort? */
2580 case MUIM_DoDrag:
2581 return Area__MUIM_DoDrag(cl, obj, (APTR) msg);
2582 case MUIM_CreateDragImage:
2583 return Area__MUIM_CreateDragImage(cl, obj, (APTR) msg);
2584 case MUIM_DeleteDragImage:
2585 return Area__MUIM_DeleteDragImage(cl, obj, (APTR) msg);
2586 case MUIM_DragQueryExtended:
2587 return Area__MUIM_DragQueryExtended(cl, obj, (APTR) msg);
2588 case MUIM_HandleInput:
2589 return Area__MUIM_HandleInput(cl, obj, (APTR) msg);
2590 case MUIM_FindAreaObject:
2591 return Area__MUIM_FindAreaObject(cl, obj, (APTR) msg);
2593 case MUIM_Export:
2594 return Area__MUIM_Export(cl, obj, (APTR) msg);
2595 case MUIM_Import:
2596 return Area__MUIM_Import(cl, obj, (APTR) msg);
2599 return DoSuperMethodA(cl, obj, msg);
2601 BOOPSI_DISPATCHER_END
2604 * Class descriptor.
2606 const struct __MUIBuiltinClass _MUI_Area_desc =
2608 MUIC_Area,
2609 MUIC_Notify,
2610 sizeof(struct MUI_AreaData),
2611 (void *) Area_Dispatcher