muimaster.library: Area class will not eat wheel movement messages
[AROS.git] / workbench / libs / muimaster / classes / area.c
blob10d138b49e0c18a9f1cb640ea36dedca07722d02
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>
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);
121 static void area_update_msizes(Object *obj, struct MUI_AreaData *data,
122 const struct MUI_FrameSpec_intern *frame,
123 const struct ZuneFrameGfx *zframe);
124 static void setup_control_char(struct MUI_AreaData *data, Object *obj,
125 struct IClass *cl);
126 static void cleanup_control_char(struct MUI_AreaData *data, Object *obj);
128 //static void setup_cycle_chain (struct MUI_AreaData *data, Object *obj);
129 //static void cleanup_cycle_chain (struct MUI_AreaData *data, Object *obj);
131 #define ZUNE_FOCUS_TYPE_ACTIVE_OBJ 0
132 #define ZUNE_FOCUS_TYPE_DROP_OBJ 1
134 static void _zune_focus_new(Object *obj, int type)
136 Object *parent;
137 struct RastPort *rp;
138 UWORD oldDrPt;
140 //bug("_zune_focus_new 1 %p\n", obj);
142 if (NULL == obj || !(_flags(obj) & MADF_CANDRAW))
143 return;
145 parent = _parent(obj);
146 rp = _rp(obj);
147 oldDrPt = rp->LinePtrn;
149 int x1 = _left(obj);
150 int y1 = _top(obj);
151 int x2 = _left(obj) + _width(obj) - 1;
152 int y2 = _top(obj) + _height(obj) - 1;
154 if (!parent || parent == _win(obj))
155 return;
157 SetABPenDrMd(rp, _pens(obj)[MPEN_SHINE], _pens(obj)[MPEN_SHADOW], JAM2);
159 if (type == ZUNE_FOCUS_TYPE_ACTIVE_OBJ)
161 SetDrPt(rp, 0xCCCC);
162 x1--;
163 y1--;
164 x2++;
165 y2++;
167 else
169 SetDrPt(rp, 0xF0F0);
172 Move(rp, x1, y1);
173 Draw(rp, x2, y1);
174 Draw(rp, x2, y2);
175 Draw(rp, x1, y2);
176 Draw(rp, x1, y1);
177 SetDrPt(rp, oldDrPt);
180 static void _zune_focus_destroy(Object *obj, int type)
182 Object *parent;
184 //bug("_zune_focus_destroy 1 %p\n", obj);
186 if (NULL == obj || !(_flags(obj) & MADF_CANDRAW))
187 return;
189 parent = _parent(obj);
190 int x1 = _left(obj);
191 int y1 = _top(obj);
192 int x2 = _left(obj) + _width(obj) - 1;
193 int y2 = _top(obj) + _height(obj) - 1;
194 int width;
195 int height;
197 if (type == ZUNE_FOCUS_TYPE_ACTIVE_OBJ)
199 if (!parent || parent == _win(obj))
200 return;
202 x1--;
203 y1--;
204 x2++;
205 y2++;
206 width = x2 - x1 + 1;
207 height = y2 - y1 + 1;
209 DoMethod(parent, MUIM_DrawBackground, x1, y1, width, 1, x1, y1, 0);
210 DoMethod(parent, MUIM_DrawBackground, x2, y1, 1, height, x2, y1, 0);
211 DoMethod(parent, MUIM_DrawBackground, x1, y2, width, 1, x1, y2, 0);
212 DoMethod(parent, MUIM_DrawBackground, x1, y1, 1, height, x1, y1, 0);
214 else
216 struct Region *region;
217 struct Rectangle rect;
218 APTR clip = NULL;
220 region = NewRegion();
221 if (region)
223 rect.MinX = _left(obj);
224 rect.MinY = _top(obj);
225 rect.MaxX = _right(obj);
226 rect.MaxY = _top(obj);
228 OrRectRegion(region, &rect);
230 rect.MinX = _right(obj);
231 rect.MinY = _top(obj);
232 rect.MaxX = _right(obj);
233 rect.MaxY = _bottom(obj);
235 OrRectRegion(region, &rect);
237 rect.MinX = _left(obj);
238 rect.MinY = _bottom(obj);
239 rect.MaxX = _right(obj);
240 rect.MaxY = _bottom(obj);
242 OrRectRegion(region, &rect);
244 rect.MinX = _left(obj);
245 rect.MinY = _top(obj);
246 rect.MaxX = _left(obj);
247 rect.MaxY = _bottom(obj);
249 OrRectRegion(region, &rect);
251 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
255 MUI_Redraw(obj, MADF_DRAWOBJECT);
257 if (region)
259 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
265 /**************************************************************************
266 OM_NEW
267 **************************************************************************/
268 static IPTR Area__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
270 struct MUI_AreaData *data;
271 struct TagItem *tags, *tag;
273 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
274 if (!obj)
275 return FALSE;
277 /* Initial local instance data */
278 data = INST_DATA(cl, obj);
280 data->mad_Flags =
281 MADF_FILLAREA | MADF_SHOWME | MADF_SHOWSELSTATE | MADF_DROPABLE;
282 data->mad_HorizWeight = data->mad_VertWeight = 100;
283 data->mad_InputMode = MUIV_InputMode_None;
285 /* parse initial taglist */
287 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
289 switch (tag->ti_Tag)
291 case MUIA_Background:
293 data->mad_Flags |= MADF_OWNBG;
294 if (data->mad_BackgroundSpec)
296 zune_image_spec_free(data->mad_BackgroundSpec);
298 data->mad_BackgroundSpec =
299 zune_image_spec_duplicate(tag->ti_Data);
301 break;
303 case MUIA_ControlChar:
304 data->mad_ControlChar = tag->ti_Data;
305 break;
307 case MUIA_CycleChain:
308 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
309 MADF_CYCLECHAIN);
310 break;
312 case MUIA_Disabled:
313 case MUIA_NestedDisabled:
314 if (tag->ti_Data)
316 data->mad_DisableCount = 1;
318 break;
320 case MUIA_FillArea:
321 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_FILLAREA);
322 break;
324 case MUIA_Draggable:
325 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DRAGGABLE);
326 break;
328 case MUIA_Dropable:
329 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DROPABLE);
330 break;
332 case MUIA_FixHeight:
333 data->mad_Flags |= MADF_FIXHEIGHT;
334 data->mad_HardHeight = tag->ti_Data;
335 break;
337 case MUIA_FixHeightTxt:
338 data->mad_HardHeightTxt = (STRPTR) tag->ti_Data;
339 break;
341 case MUIA_FixWidth:
342 data->mad_Flags |= MADF_FIXWIDTH;
343 data->mad_HardWidth = tag->ti_Data;
344 break;
346 case MUIA_FixWidthTxt:
347 data->mad_HardWidthTxt = (STRPTR) tag->ti_Data;
348 break;
350 case MUIA_Font:
351 data->mad_FontPreset = tag->ti_Data;
352 break;
354 case MUIA_Frame:
355 data->mad_Frame = tag->ti_Data;
356 break;
358 case MUIA_FramePhantomHoriz:
359 data->mad_Flags |= MADF_FRAMEPHANTOM;
360 break;
362 case MUIA_FrameTitle:
363 data->mad_FrameTitle = (STRPTR) tag->ti_Data;
364 break;
366 case MUIA_HorizWeight:
367 data->mad_HorizWeight = tag->ti_Data;
368 break;
370 case MUIA_InnerBottom:
371 data->mad_Flags |= MADF_INNERBOTTOM;
372 data->mad_InnerBottom = CLAMP((IPTR) tag->ti_Data, 0, 32);
373 break;
375 case MUIA_InnerLeft:
376 data->mad_Flags |= MADF_INNERLEFT;
377 data->mad_InnerLeft = CLAMP((IPTR) tag->ti_Data, 0, 32);
378 break;
380 case MUIA_InnerRight:
381 data->mad_Flags |= MADF_INNERRIGHT;
382 data->mad_InnerRight = CLAMP((IPTR) tag->ti_Data, 0, 32);
383 break;
385 case MUIA_InnerTop:
386 data->mad_Flags |= MADF_INNERTOP;
387 data->mad_InnerTop = CLAMP((IPTR) tag->ti_Data, 0, 32);
388 break;
390 case MUIA_InputMode:
391 data->mad_InputMode = tag->ti_Data;
392 break;
394 case MUIA_MaxHeight:
395 data->mad_Flags |= MADF_MAXHEIGHT;
396 data->mad_HardHeight = tag->ti_Data;
397 break;
399 case MUIA_MaxWidth:
400 data->mad_Flags |= MADF_MAXWIDTH;
401 data->mad_HardWidth = tag->ti_Data;
402 break;
404 case MUIA_Selected:
405 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_SELECTED);
406 break;
408 case MUIA_ShortHelp:
409 data->mad_ShortHelp = (STRPTR) tag->ti_Data;
410 break;
412 case MUIA_ShowMe:
413 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_SHOWME);
414 break;
416 case MUIA_ShowSelState:
417 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
418 MADF_SHOWSELSTATE);
419 break;
421 case MUIA_VertWeight:
422 data->mad_VertWeight = tag->ti_Data;
423 break;
425 case MUIA_Weight:
426 data->mad_HorizWeight = data->mad_VertWeight = tag->ti_Data;
427 break;
429 case MUIA_ContextMenu:
430 data->mad_ContextMenu = (Object *) tag->ti_Data;
431 break;
435 /* In Soliton MUIA_Selected was set to MUIV_InputMode_RelVerify (=1)
436 ** for MUIA_Input_Mode MUIV_InputMode_RelVerify which is wrong of
437 ** course but MUI seems to filter this out so we have to do it also
439 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
441 if (data->mad_Flags & MADF_SELECTED)
442 D(bug("MUIA_Selected was set in OM_NEW, "
443 "although being in MUIV_InputMode_RelVerify\n"));
444 data->mad_Flags &= ~MADF_SELECTED;
447 data->mad_ehn.ehn_Events = 0; /* Will be filled on demand */
448 data->mad_ehn.ehn_Priority = -5;
450 /* Please also send mui key events to us, no idea if mui handles this
451 * like this */
452 data->mad_ehn.ehn_Flags = MUI_EHF_ALWAYSKEYS;
453 data->mad_ehn.ehn_Object = obj;
454 data->mad_ehn.ehn_Class = cl;
456 data->mad_hiehn.ehn_Events = 0;
457 data->mad_hiehn.ehn_Priority = -10;
458 data->mad_hiehn.ehn_Flags = MUI_EHF_HANDLEINPUT;
459 data->mad_hiehn.ehn_Object = obj;
460 data->mad_hiehn.ehn_Class = 0;
462 return (IPTR) obj;
465 /**************************************************************************
466 OM_DISPOSE
467 **************************************************************************/
468 static IPTR Area__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
470 struct MUI_AreaData *data = INST_DATA(cl, obj);
472 /* Safe to call this with NULL */
473 zune_image_spec_free(data->mad_BackgroundSpec);
475 return DoSuperMethodA(cl, obj, msg);
479 /**************************************************************************
480 OM_SET
481 **************************************************************************/
482 static IPTR Area__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
484 struct MUI_AreaData *data = INST_DATA(cl, obj);
485 struct TagItem *tags = msg->ops_AttrList;
486 struct TagItem *tag;
487 CONST_STRPTR old_backgroundspec;
489 int change_disable = 0; /* Has the disable state changed? */
491 while ((tag = NextTagItem(&tags)) != NULL)
493 switch (tag->ti_Tag)
495 case MUIA_Background:
496 old_backgroundspec = data->mad_BackgroundSpec;
497 data->mad_BackgroundSpec =
498 zune_image_spec_duplicate(tag->ti_Data);
499 if (!data->mad_BackgroundSpec)
501 /* Out of memory */
502 data->mad_BackgroundSpec = old_backgroundspec;
503 break;
506 data->mad_Flags |= MADF_OWNBG;
508 if (old_backgroundspec
509 && (strcmp(data->mad_BackgroundSpec,
510 old_backgroundspec) == 0))
512 /* New background does not differ from old one */
513 zune_image_spec_free(old_backgroundspec);
514 tag->ti_Tag = TAG_IGNORE;
515 break;
518 zune_image_spec_free(old_backgroundspec);
520 if (data->mad_Background)
522 if (_flags(obj) & MADF_CANDRAW)
524 zune_imspec_hide(data->mad_Background);
526 if (_flags(obj) & MADF_SETUP)
528 zune_imspec_cleanup(data->mad_Background);
529 data->mad_Background = NULL;
533 if (_flags(obj) & MADF_SETUP)
535 data->mad_Background =
536 zune_imspec_setup((IPTR) data->mad_BackgroundSpec,
537 muiRenderInfo(obj));
539 if (_flags(obj) & MADF_CANDRAW)
541 zune_imspec_show(data->mad_Background, obj);
543 MUI_Redraw(obj, MADF_DRAWOBJECT);
544 break;
546 case MUIA_FillArea:
547 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_FILLAREA);
548 break;
550 case MUIA_Frame:
551 /* this is not documented in MUI but it is possible,
552 and needed to suppress frame for external images */
553 data->mad_Frame = tag->ti_Data;
554 if (muiGlobalInfo(obj))
556 set_inner_sizes(obj, data);
557 set_title_sizes(obj, data);
559 break;
561 case MUIA_ControlChar:
562 if (_flags(obj) & MADF_SETUP)
563 cleanup_control_char(data, obj);
564 data->mad_ControlChar = tag->ti_Data;
565 if (_flags(obj) & MADF_SETUP)
566 setup_control_char(data, obj, cl);
567 break;
569 case MUIA_CycleChain:
570 // if (data->mad_InputMode == MUIV_InputMode_None)
571 // break;
573 if ((!(_flags(obj) & MADF_CYCLECHAIN) && tag->ti_Data)
574 || ((_flags(obj) & MADF_CYCLECHAIN) && !tag->ti_Data))
576 if (_flags(obj) & MADF_SETUP)
578 cleanup_control_char(data, obj);
579 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
580 MADF_CYCLECHAIN);
581 setup_control_char(data, obj, cl);
583 else
584 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
585 MADF_CYCLECHAIN);
587 break;
589 case MUIA_Disabled:
590 if (tag->ti_Data)
592 if (!data->mad_DisableCount)
594 data->mad_DisableCount = 1;
595 change_disable = 1;
598 else
600 if (data->mad_DisableCount)
602 data->mad_DisableCount = 0;
603 change_disable = 1;
606 break;
608 case MUIA_NestedDisabled:
609 if (tag->ti_Data)
611 if (!data->mad_DisableCount)
612 change_disable = 1;
613 data->mad_DisableCount++;
615 else
617 if (data->mad_DisableCount)
619 data->mad_DisableCount--;
620 if (!data->mad_DisableCount)
621 change_disable = 1;
624 break;
627 case MUIA_HorizWeight:
628 data->mad_HorizWeight = tag->ti_Data;
629 break;
631 case MUIA_Pressed:
632 if (tag->ti_Data)
633 data->mad_Flags |= MADF_PRESSED;
634 else
635 data->mad_Flags &= ~MADF_PRESSED;
636 break;
638 case MUIA_ShortHelp:
639 data->mad_ShortHelp = (STRPTR) tag->ti_Data;
640 break;
642 case MUIA_ShowMe:
644 ULONG oldflags = data->mad_Flags;
645 int recalc = 0;
647 if (tag->ti_Data)
648 data->mad_Flags |= MADF_SHOWME;
649 else
650 data->mad_Flags &= ~MADF_SHOWME;
652 if (oldflags != data->mad_Flags)
654 if (!tag->ti_Data)
656 /* Should be made invisible, so send a MUIM_Hide and
657 ** then a MUIM_Cleanup to the object if needed,
658 ** as objects with MUIA_ShowMe to false get neither
659 ** MUIM_Setup nor MUIM_Show */
660 if (_flags(obj) & MADF_CANDRAW)
662 DoHideMethod(obj);
663 recalc = 1;
665 #if 0 /* SHOWME affects only show/hide */
666 if (_flags(obj) & MADF_SETUP)
667 DoMethod(obj, MUIM_Cleanup);
668 #endif
670 else
672 Object *parent = _parent(obj);
673 /* Will be NULL if direct child of a window! */
675 if (parent)
677 #if 0 /* SHOWME affects only show/hide */
678 if (_flags(parent) & MADF_SETUP)
679 DoSetupMethod(obj, muiRenderInfo(parent));
680 #endif
681 if (_flags(parent) & MADF_CANDRAW)
683 DoShowMethod(obj);
684 recalc = 1;
687 else
689 /* Check if window is open... */
693 /* If renderinfo is NULL _win(obj) doesn't work (crash) */
694 if (recalc && muiRenderInfo(obj))
696 DoMethod(_win(obj), MUIM_Window_RecalcDisplay,
697 (IPTR) _parent(obj));
701 break;
703 case MUIA_Selected:
704 /* D(bug(" Area_Set(%p) :
705 MUIA_Selected val=%ld sss=%d\n", obj, tag->ti_Data,
706 !!(data->mad_Flags & MADF_SHOWSELSTATE)));
708 if (tag->ti_Data && !(data->mad_Flags & MADF_SELECTED))
710 data->mad_Flags |= MADF_SELECTED;
711 MUI_Redraw(obj, MADF_DRAWOBJECT);
713 else if (!tag->ti_Data && (data->mad_Flags & MADF_SELECTED))
715 data->mad_Flags &= ~MADF_SELECTED;
716 MUI_Redraw(obj, MADF_DRAWOBJECT);
718 #if 0 // CHECKME: What's the purpose of this? What superclass will care?
719 else
721 tag->ti_Tag = TAG_IGNORE;
723 #endif
724 break;
726 case MUIA_Timer:
727 data->mad_Timeval = tag->ti_Data;
728 break;
730 case MUIA_VertWeight:
731 data->mad_VertWeight = tag->ti_Data;
732 break;
734 case MUIA_Draggable:
735 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DRAGGABLE);
736 break;
738 case MUIA_Dropable:
739 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DROPABLE);
740 break;
742 case MUIA_ContextMenu:
743 data->mad_ContextMenu = (Object *) tag->ti_Data;
744 break;
746 case MUIA_Font:
747 data->mad_FontPreset = tag->ti_Data;
748 break;
750 case MUIA_InputMode:
751 data->mad_InputMode = tag->ti_Data;
752 break;
757 if (change_disable)
759 MUI_Redraw(obj, MADF_DRAWOBJECT);
762 return DoSuperMethodA(cl, obj, (Msg) msg);
766 /**************************************************************************
767 OM_GET
768 **************************************************************************/
769 static IPTR Area__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
771 #define STORE *(msg->opg_Storage)
773 struct MUI_AreaData *data = INST_DATA(cl, obj);
775 switch (msg->opg_AttrID)
777 case MUIA_Background:
778 STORE = (IPTR) data->mad_Background;
779 return TRUE;
781 case MUIA_BottomEdge:
782 STORE = (IPTR) _bottom(obj);
783 return TRUE;
785 case MUIA_ControlChar:
786 STORE = data->mad_ControlChar;
787 return TRUE;
789 case MUIA_CycleChain:
790 STORE = ((data->mad_Flags & MADF_CYCLECHAIN) != 0);
791 return TRUE;
793 case MUIA_Disabled:
794 case MUIA_NestedDisabled:
795 STORE = ! !data->mad_DisableCount; /* BOOLEAN */
796 return TRUE;
798 case MUIA_Font:
799 STORE = (IPTR) data->mad_FontPreset;
800 return TRUE;
802 case MUIA_Height:
803 STORE = (IPTR) _height(obj);
804 return TRUE;
806 case MUIA_HorizWeight:
807 STORE = (IPTR) data->mad_HorizWeight;
808 return TRUE;
810 case MUIA_InnerBottom:
811 STORE = (IPTR) data->mad_InnerBottom;
812 return TRUE;
814 case MUIA_InnerLeft:
815 STORE = (IPTR) data->mad_InnerLeft;
816 return TRUE;
818 case MUIA_InnerRight:
819 STORE = (IPTR) data->mad_InnerRight;
820 return TRUE;
822 case MUIA_InnerTop:
823 STORE = (IPTR) data->mad_InnerTop;
824 return TRUE;
826 case MUIA_LeftEdge:
827 STORE = (IPTR) _left(obj);
828 return TRUE;
830 case MUIA_Pressed:
831 STORE = ! !(data->mad_Flags & MADF_PRESSED);
832 return TRUE;
834 case MUIA_RightEdge:
835 STORE = (IPTR) _right(obj);
836 return TRUE;
838 case MUIA_Selected:
839 STORE = ! !(data->mad_Flags & MADF_SELECTED);
840 return TRUE;
842 case MUIA_ShortHelp:
843 STORE = (IPTR) data->mad_ShortHelp;
844 return TRUE;
846 case MUIA_ShowMe:
847 STORE = ! !(data->mad_Flags & MADF_SHOWME);
848 return TRUE;
850 case MUIA_Timer:
851 STORE = data->mad_Timeval;
852 return TRUE;
854 case MUIA_TopEdge:
855 STORE = (IPTR) _top(obj);
856 return TRUE;
858 case MUIA_VertWeight:
859 STORE = (IPTR) data->mad_VertWeight;
860 return TRUE;
862 case MUIA_Width:
863 STORE = (IPTR) _width(obj);
864 return TRUE;
866 case MUIA_Window:
867 if (muiAreaData(obj)->mad_RenderInfo)
868 STORE = (IPTR) _window(obj);
869 else
870 STORE = 0L;
871 return TRUE;
873 case MUIA_WindowObject:
874 if (muiAreaData(obj)->mad_RenderInfo)
875 STORE = (IPTR) _win(obj);
876 else
877 STORE = 0L;
878 return TRUE;
880 case MUIA_ContextMenu:
881 STORE = (IPTR) data->mad_ContextMenu;
882 return TRUE;
884 case MUIA_Frame:
885 STORE = (IPTR) data->mad_Frame;
886 return TRUE;
888 case MUIA_Draggable:
889 STORE = !!(data->mad_Flags & MADF_DRAGGABLE);
890 return TRUE;
892 case MUIA_Dropable:
893 STORE = !!(data->mad_Flags & MADF_DROPABLE);
894 return TRUE;
897 return (DoSuperMethodA(cl, obj, (Msg) msg));
898 #undef STORE
902 /**************************************************************************
903 MUIM_AskMinMax
904 **************************************************************************/
905 static IPTR Area__MUIM_AskMinMax(struct IClass *cl, Object *obj,
906 struct MUIP_AskMinMax *msg)
908 struct MUI_AreaData *data = INST_DATA(cl, obj);
909 const struct ZuneFrameGfx *zframe;
910 const struct MUI_FrameSpec_intern *frame;
911 struct MUI_FrameSpec_intern tempframe;
913 frame = get_intframe(obj, data, &tempframe);
914 zframe = zune_zframe_get(obj, frame);
916 area_update_msizes(obj, data, frame, zframe);
918 msg->MinMaxInfo->MinWidth = _subwidth(obj);
919 msg->MinMaxInfo->MinHeight = _subheight(obj);
921 msg->MinMaxInfo->MaxWidth = msg->MinMaxInfo->MinWidth;
922 msg->MinMaxInfo->MaxHeight = msg->MinMaxInfo->MinHeight;
923 msg->MinMaxInfo->DefWidth = msg->MinMaxInfo->MinWidth;
924 msg->MinMaxInfo->DefHeight = msg->MinMaxInfo->MinHeight;
926 /* D(bug("Area_AskMinMax 0x%lx (%s): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n",
927 obj, data->mad_FrameTitle, */
928 /* msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight, */
929 /* msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight, */
930 /* msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight)); */
932 return TRUE;
936 * Called after MUIM_AskMinMax, to handle fixed and max sizes.
938 void __area_finish_minmax(Object *obj, struct MUI_MinMax *MinMaxInfo)
940 struct MUI_AreaData *data = muiAreaData(obj);
942 if ((_flags(obj) & MADF_FIXHEIGHT) && (data->mad_HardHeight > 0))
944 int h = data->mad_HardHeight + data->mad_subheight;
946 MinMaxInfo->MinHeight =
947 MinMaxInfo->DefHeight =
948 MinMaxInfo->MaxHeight =
949 CLAMP(h, MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
951 else if (data->mad_HardHeightTxt)
953 ZText *text;
955 if ((text =
956 zune_text_new(NULL, data->mad_HardHeightTxt, ZTEXT_ARG_NONE,
957 0)))
959 zune_text_get_bounds(text, obj);
961 MinMaxInfo->MinHeight =
962 MinMaxInfo->DefHeight =
963 MinMaxInfo->MaxHeight =
964 CLAMP(text->height + data->mad_subheight,
965 MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
967 zune_text_destroy(text);
971 else if (_flags(obj) & MADF_MAXHEIGHT)
973 MinMaxInfo->MaxHeight =
974 CLAMP(data->mad_HardHeight + data->mad_subheight,
975 MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
978 if ((_flags(obj) & MADF_FIXWIDTH) && (data->mad_HardWidth > 0))
980 int w = data->mad_HardWidth + data->mad_subwidth;
982 MinMaxInfo->MinWidth =
983 MinMaxInfo->DefWidth =
984 MinMaxInfo->MaxWidth =
985 CLAMP(w, MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
987 else if (data->mad_HardWidthTxt)
989 ZText *text;
991 if ((text =
992 zune_text_new(NULL, data->mad_HardWidthTxt, ZTEXT_ARG_NONE,
993 0)))
995 zune_text_get_bounds(text, obj);
997 MinMaxInfo->MinWidth =
998 MinMaxInfo->DefWidth =
999 MinMaxInfo->MaxWidth =
1000 CLAMP(text->width + data->mad_subwidth,
1001 MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
1003 zune_text_destroy(text);
1007 else if (_flags(obj) & MADF_MAXWIDTH)
1009 MinMaxInfo->MaxWidth =
1010 CLAMP(data->mad_HardWidth + data->mad_subwidth,
1011 MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
1014 /* Set minmax */
1015 _minwidth(obj) = MinMaxInfo->MinWidth;
1016 _minheight(obj) = MinMaxInfo->MinHeight;
1017 _maxwidth(obj) = MinMaxInfo->MaxWidth;
1018 _maxheight(obj) = MinMaxInfo->MaxHeight;
1019 _defwidth(obj) = MinMaxInfo->DefWidth;
1020 _defheight(obj) = MinMaxInfo->DefHeight;
1023 /* <-- _top(obj) (frame title position depends of _top(obj))
1024 * ==== Title === <-- frame_top (depends of title, if centered/above)
1025 * | | <-- bgtop (depends of frame, bg always begins under frame)
1026 * | |
1027 * | |
1028 * ============== <-- "bgbottom" and "frame_bottom" (frame overwrites bg (1))
1030 * (1) : needed for phantom frame objects, where no frame overwrites bg, thus bg
1031 * must go as far as theoretical bottom frame border.
1035 * draw object background if MADF_FILLAREA.
1037 static void Area_Draw_handle_background(Object *obj,
1038 struct MUI_AreaData *data, ULONG flags,
1039 const struct ZuneFrameGfx *zframe)
1041 struct MUI_ImageSpec_intern *background;
1042 struct Rectangle r, r2, rects[4];
1043 int i, bgtop, bgleft, bgw, bgh, numrects;
1045 if (!(data->mad_Flags & MADF_SELECTED)
1046 || !(data->mad_Flags & MADF_SHOWSELSTATE))
1047 background = data->mad_Background;
1048 else
1049 background = data->mad_SelBack;
1051 if (zframe->customframe)
1053 bgtop = _top(obj) + data->mad_TitleHeightAbove;
1055 else
1057 bgtop = _top(obj) + data->mad_TitleHeightAbove + zframe->itop;
1060 bgleft = _left(obj);
1061 bgw = _width(obj);
1062 bgh = _height(obj) - bgtop + _top(obj);
1064 r.MinX = bgleft;
1065 r.MinY = bgtop;
1066 r.MaxX = bgleft + bgw - 1;
1067 r.MaxY = bgtop + bgh - 1;
1069 if (data->mad_Flags & MADF_FILLAREA)
1071 rects[0] = r;
1072 numrects = 1;
1074 else
1076 /* MADF_FILLAREA not set. Only draw frame outside of
1077 innerbox (_mleft, _mtop, _mright, _mbottom):
1079 .............
1080 .***********.
1081 .*#########*.
1082 .*#########*.
1083 .***********.
1084 .............
1086 # = innerbox
1087 * = frame outside of innerbox
1088 . = object frame
1091 r2.MinX = _mleft(obj);
1092 r2.MinY = _mtop(obj);
1093 r2.MaxX = _mright(obj);
1094 r2.MaxY = _mbottom(obj);
1096 numrects = SubtractRectFromRect(&r, &r2, rects);
1099 for (i = 0; i < numrects; i++)
1101 if (!background)
1103 /* This will do the rest, TODO: on MADF_DRAWALL we not really
1104 * need to draw this */
1105 /* D(bug(" Area_Draw(%p):%ld: MUIM_DrawBackground\n", obj,
1106 __LINE__)); */
1107 /* ATTENTION: This draws the clipped away regions of the area.
1108 * Comment out and check the result to see what I mean. */
1109 DoMethod(obj, MUIM_DrawBackground,
1110 rects[i].MinX, rects[i].MinY,
1111 rects[i].MaxX - rects[i].MinX + 1,
1112 rects[i].MaxY - rects[i].MinY + 1, rects[i].MinX,
1113 rects[i].MinY, data->mad_Flags);
1115 else
1117 /* D(bug(" Area_Draw(%p):%ld: zune_imspec_draw\n", obj,
1118 __LINE__)); */
1119 zune_imspec_draw(background, data->mad_RenderInfo,
1120 rects[i].MinX, rects[i].MinY,
1121 rects[i].MaxX - rects[i].MinX + 1,
1122 rects[i].MaxY - rects[i].MinY + 1, rects[i].MinX,
1123 rects[i].MinY, 0);
1127 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
1128 WINDOW_REDRAW_WITHOUT_CLEAR)
1130 if (bgtop > _top(obj) && !(flags & MADF_DRAWALL))
1132 /* Fill in the gap produced by the title with the background
1133 * of the parent object but only if
1134 * the upper object hasn't drawn it already
1135 * (which is the case if MADF_DRAWALL is setted) */
1136 DoMethod(obj, MUIM_DrawParentBackground, bgleft, _top(obj), bgw,
1137 bgtop - _top(obj), bgleft, _top(obj), data->mad_Flags);
1144 * draw object frame + title if not MADF_FRAMEPHANTOM.
1146 static void Area_Draw_handle_frame(Object *obj, struct MUI_AreaData *data,
1147 const struct ZuneFrameGfx *zframe)
1149 APTR textdrawclip = (APTR) - 1;
1150 struct Region *region;
1151 int tx;
1152 int tw, frame_height, frame_top;
1153 int addtw;
1154 struct TextExtent te;
1155 int nchars;
1156 int maxtxtwidth;
1158 /* no frametitle, just draw frame and return */
1159 if (!data->mad_FrameTitle)
1161 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1162 _top(obj), _width(obj), _height(obj), _left(obj), _top(obj),
1163 _width(obj), _height(obj));
1164 return;
1167 /* set clipping so that frame is not drawn behind title */
1169 switch (muiGlobalInfo(obj)->mgi_Prefs->group_title_color)
1171 case GROUP_TITLE_COLOR_OUTLINE:
1172 addtw = 2;
1173 break;
1174 case GROUP_TITLE_COLOR_3D:
1175 addtw = 1;
1176 break;
1177 default:
1178 addtw = 0;
1181 maxtxtwidth =
1182 _width(obj) - zframe->ileft - zframe->iright - 2 * 5 - addtw;
1184 nchars = TextFit(_rp(obj), data->mad_FrameTitle,
1185 strlen(data->mad_FrameTitle),
1186 &te, NULL, 1, maxtxtwidth, _font(obj)->tf_YSize);
1188 tw = te.te_Width + addtw;
1189 tx = _left(obj) + (_width(obj) - tw) / 2;
1191 frame_top = _top(obj) + data->mad_TitleHeightAbove;
1192 frame_height = _height(obj) - frame_top + _top(obj);
1194 if ((region = NewRegion()))
1196 struct Rectangle rect;
1197 int hspace = _font(obj)->tf_YSize / 8;
1199 rect.MinX = tx - hspace;
1200 rect.MinY = _top(obj);
1201 rect.MaxX = tx + tw - 1 + hspace;
1202 rect.MaxY = _top(obj) + _font(obj)->tf_YSize - 1;
1203 // frame is not thick enough anyway
1204 OrRectRegion(region, &rect);
1206 rect.MinX = _left(obj);
1207 rect.MinY = _top(obj);
1208 rect.MaxX = _right(obj);
1209 rect.MaxY = _bottom(obj);
1210 XorRectRegion(region, &rect);
1212 textdrawclip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1215 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1216 frame_top, _width(obj), frame_height, _left(obj), frame_top,
1217 _width(obj), frame_height);
1219 if (region && textdrawclip != (APTR) - 1)
1221 MUI_RemoveClipRegion(muiRenderInfo(obj), textdrawclip);
1222 /* DisposeRegion(region);*/ /* sba: DisposeRegion happens in MUI_RemoveClipRegion, this seems wrong to me */
1225 /* Title text drawing */
1226 SetDrMd(_rp(obj), JAM1);
1227 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
1228 if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1229 GROUP_TITLE_COLOR_3D)
1231 Move(_rp(obj), tx + 1, _top(obj) + _font(obj)->tf_Baseline + 1);
1232 Text(_rp(obj), data->mad_FrameTitle, nchars);
1233 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1234 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1235 Text(_rp(obj), data->mad_FrameTitle, nchars);
1237 else if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1238 GROUP_TITLE_COLOR_OUTLINE)
1240 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1242 tx += addtw / 2;
1243 Move(_rp(obj), tx + 1, _top(obj) + _font(obj)->tf_Baseline);
1244 Text(_rp(obj), data->mad_FrameTitle, nchars);
1245 Move(_rp(obj), tx - 1, _top(obj) + _font(obj)->tf_Baseline);
1246 Text(_rp(obj), data->mad_FrameTitle, nchars);
1247 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline + 1);
1248 Text(_rp(obj), data->mad_FrameTitle, nchars);
1249 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline - 1);
1250 Text(_rp(obj), data->mad_FrameTitle, nchars);
1252 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
1253 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1254 Text(_rp(obj), data->mad_FrameTitle, nchars);
1256 else
1258 if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1259 GROUP_TITLE_COLOR_HILITE)
1261 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1263 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1264 Text(_rp(obj), data->mad_FrameTitle, nchars);
1268 /**************************************************************************
1269 MUIM_Draw
1270 **************************************************************************/
1271 static IPTR Area__MUIM_Draw(struct IClass *cl, Object *obj,
1272 struct MUIP_Draw *msg)
1274 struct MUI_AreaData *data = INST_DATA(cl, obj);
1275 const struct ZuneFrameGfx *zframe;
1276 struct TextFont *obj_font = NULL;
1277 ULONG flags = data->mad_Flags & MADF_DRAWFLAGS;
1279 //APTR areaclip;
1281 /* D(bug("Area_Draw(0x%lx) %ldx%ldx%ldx%ld\n", obj, _left(obj),
1282 _top(obj),_right(obj),_bottom(obj))); */
1283 /* D(bug(" Area_Draw(%p) msg=0x%08lx flags=0x%08lx\n", obj, msg->flags,
1284 _flags(obj))); */
1286 if (flags & MADF_DRAWALL)
1287 flags |= MADF_DRAWOBJECT;
1289 msg->flags = flags;
1290 data->mad_Flags &= ~MADF_DRAWFLAGS;
1292 if (!(flags & MADF_DRAWOBJECT))
1294 /* dont draw bg/frame, let subclass redraw content only
1296 return 0;
1300 /* Background can't be drawn without knowing anything about frame, thus some
1301 * calculations are made before background and frame drawing.
1304 /* on selected state, will get the opposite frame */
1305 const struct MUI_FrameSpec_intern *frame;
1306 struct MUI_FrameSpec_intern tempframe;
1307 int state;
1309 frame = get_intframe(obj, data, &tempframe);
1310 state = frame->state;
1311 if ((data->mad_Flags & MADF_SELECTED)
1312 && (data->mad_Flags & MADF_SHOWSELSTATE))
1313 state ^= 1;
1315 zframe = zune_zframe_get_with_state(obj, frame, state);
1317 /* update innersizes as there are frames which have different inner
1318 * spacings in selected state */
1319 area_update_msizes(obj, data, frame, zframe);
1322 /* Background drawing */
1323 Area_Draw_handle_background(obj, data, msg->flags, zframe);
1325 obj_font = _font(obj);
1326 _font(obj) = zune_font_get(obj, MUIV_Font_Title);
1327 SetFont(_rp(obj), _font(obj));
1329 /* Frame and frametitle drawing */
1330 if (!(data->mad_Flags & MADF_FRAMEPHANTOM))
1332 Area_Draw_handle_frame(obj, data, zframe);
1335 _font(obj) = obj_font;
1336 SetFont(_rp(obj), _font(obj));
1338 /* MUI_RemoveClipping(muiRenderInfo(obj), areaclip);*/
1340 return TRUE;
1343 /**************************************************************************
1344 MUIM_DrawParentBackground
1345 **************************************************************************/
1346 static IPTR Area__MUIM_DrawParentBackground(struct IClass *cl, Object *obj,
1347 struct MUIP_DrawParentBackground *msg)
1349 struct MUI_AreaData *data = INST_DATA(cl, obj);
1350 Object *parent = NULL;
1352 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1353 return FALSE;
1355 get(obj, MUIA_Parent, &parent);
1356 if (parent)
1358 DoMethod(parent, MUIM_DrawBackground, msg->left, msg->top,
1359 msg->width, msg->height, msg->xoffset, msg->yoffset,
1360 msg->flags);
1362 else
1364 D(bug
1365 ("Area_DrawParentBackground(%p) : MUIM_Window_DrawBackground\n",
1366 obj));
1367 DoMethod(_win(obj), MUIM_Window_DrawBackground, msg->left, msg->top,
1368 msg->width, msg->height, msg->xoffset, msg->yoffset,
1369 msg->flags);
1371 return TRUE;
1374 /**************************************************************************
1375 MUIM_DrawBackground
1376 **************************************************************************/
1377 static IPTR Area__MUIM_DrawBackground(struct IClass *cl, Object *obj,
1378 struct MUIP_DrawBackground *msg)
1380 struct MUI_AreaData *data = INST_DATA(cl, obj);
1381 struct MUI_ImageSpec_intern *bg;
1382 LONG state;
1384 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1385 return FALSE;
1387 if ((msg->flags & MADF_SELECTED) && (msg->flags & MADF_SHOWSELSTATE)
1388 && data->mad_SelBack)
1390 /* D(bug("Area_DrawBackground(%p): selected bg\n", obj)); */
1391 bg = data->mad_SelBack;
1392 state = IDS_SELECTED;
1394 else
1396 /* D(bug("Area_DrawBackground(%p): normal bg\n", obj)); */
1397 bg = data->mad_Background;
1398 state = IDS_NORMAL;
1401 const struct ZuneFrameGfx *zframe;
1402 const struct MUI_FrameSpec_intern *frame;
1403 struct MUI_FrameSpec_intern tempframe;
1405 if (!bg)
1407 D(bug("Area_DrawBackground(%p) : MUIM_DrawParentBackground\n",
1408 obj));
1410 return DoMethod(obj, MUIM_DrawParentBackground, msg->left, msg->top,
1411 msg->width, msg->height, msg->xoffset, msg->yoffset,
1412 msg->flags);
1415 frame = get_intframe(obj, data, &tempframe);
1417 int xstate = frame->state;
1418 if ((data->mad_Flags & MADF_SELECTED)
1419 && (data->mad_Flags & MADF_SHOWSELSTATE))
1420 xstate ^= 1;
1422 zframe = zune_zframe_get_with_state(obj, frame, xstate);
1424 if (zframe->customframe == NULL)
1426 /* D(bug("Area_DrawBackground(%p): draw bg\n", obj)); */
1427 zune_imspec_draw(bg, data->mad_RenderInfo,
1428 msg->left, msg->top, msg->width, msg->height,
1429 msg->xoffset, msg->yoffset, state);
1431 // if (!data->mad_FrameTitle)
1432 // {
1435 else
1437 if (zframe->noalpha == FALSE)
1439 zune_imspec_draw(bg, data->mad_RenderInfo,
1440 msg->left, msg->top, msg->width, msg->height,
1441 msg->xoffset, msg->yoffset, state);
1446 if (zframe->customframe)
1448 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1449 _top(obj), _width(obj), _height(obj), msg->left, msg->top,
1450 msg->width, msg->height);
1453 return TRUE;
1456 static IPTR Area__MUIM_DrawBackgroundBuffered(struct IClass *cl,
1457 Object *obj, struct MUIP_DrawBackgroundBuffered *msg)
1459 struct MUI_AreaData *data = INST_DATA(cl, obj);
1460 struct MUI_ImageSpec_intern *bg;
1461 LONG state = 0;
1463 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1464 return FALSE;
1466 bg = data->mad_Background;
1468 /* D(bug("Area_DrawBackground(%p): draw bg\n", obj)); */
1469 zune_imspec_drawbuffered(bg, msg->rp, data->mad_RenderInfo,
1470 msg->left, msg->top, msg->width, msg->height,
1471 msg->xoffset + msg->left, msg->yoffset + msg->top, state, msg->left,
1472 msg->top, 1, _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj));
1474 return TRUE;
1477 /* Perverting the EventHandlerNode structure to specify a shortcut.
1479 static void setup_control_char(struct MUI_AreaData *data, Object *obj,
1480 struct IClass *cl)
1482 if (data->mad_ControlChar != 0 || data->mad_Flags & MADF_CYCLECHAIN)
1484 data->mad_ccn.ehn_Events = data->mad_ControlChar;
1485 switch (data->mad_InputMode)
1487 case MUIV_InputMode_RelVerify:
1488 data->mad_ccn.ehn_Flags = MUIKEY_PRESS;
1489 break;
1490 case MUIV_InputMode_Toggle:
1491 data->mad_ccn.ehn_Flags = MUIKEY_TOGGLE;
1492 break;
1493 case MUIV_InputMode_Immediate:
1494 data->mad_ccn.ehn_Flags = MUIKEY_PRESS;
1495 break;
1497 data->mad_ccn.ehn_Priority = 0;
1498 data->mad_ccn.ehn_Object = obj;
1499 data->mad_ccn.ehn_Class = cl;
1500 DoMethod(_win(obj), MUIM_Window_AddControlCharHandler,
1501 (IPTR) & data->mad_ccn);
1506 static void cleanup_control_char(struct MUI_AreaData *data, Object *obj)
1508 if (data->mad_ControlChar != 0 || data->mad_Flags & MADF_CYCLECHAIN)
1510 DoMethod(_win(obj),
1511 MUIM_Window_RemControlCharHandler, (IPTR) & data->mad_ccn);
1515 static const struct MUI_FrameSpec_intern *get_intframe(Object *obj,
1516 struct MUI_AreaData *data, struct MUI_FrameSpec_intern *tempstore)
1518 if (data->mad_Frame > 100)
1520 /* Frame is spec in string format. Store it in tempstore and return
1521 a pointer to it. The caller should have such a temp variable on
1522 the stack. Don't want to add it to MUI_AreaData as that will
1523 increase mem usage of every object. */
1525 if (zune_frame_spec_to_intern((CONST_STRPTR) data->mad_Frame,
1526 tempstore))
1528 return tempstore;
1530 else
1532 return &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_None];
1535 else
1537 /* Frame is MUIV_Frame_<something> */
1538 return &muiGlobalInfo(obj)->mgi_Prefs->frames[data->mad_Frame];
1542 static void set_inner_sizes(Object *obj, struct MUI_AreaData *data)
1544 const struct MUI_FrameSpec_intern *frame;
1545 struct MUI_FrameSpec_intern tempframe;
1547 frame = get_intframe(obj, data, &tempframe);
1548 // Use frame inner spacing when not hardcoded
1549 if (!(data->mad_Flags & MADF_INNERLEFT))
1550 data->mad_InnerLeft = frame->innerLeft;
1551 if (!(data->mad_Flags & MADF_INNERTOP))
1552 data->mad_InnerTop = frame->innerTop;
1553 if (!(data->mad_Flags & MADF_INNERRIGHT))
1554 data->mad_InnerRight = frame->innerRight;
1555 if (!(data->mad_Flags & MADF_INNERBOTTOM))
1556 data->mad_InnerBottom = frame->innerBottom;
1560 static void set_title_sizes(Object *obj, struct MUI_AreaData *data)
1562 if (data->mad_FrameTitle)
1564 const struct ZuneFrameGfx *zframe;
1565 const struct MUI_FrameSpec_intern *frame;
1566 struct MUI_FrameSpec_intern tempframe;
1568 frame = get_intframe(obj, data, &tempframe);
1569 zframe = zune_zframe_get(obj, frame);
1571 _font(obj) = zune_font_get(obj, MUIV_Font_Title);
1573 switch (muiGlobalInfo(obj)->mgi_Prefs->group_title_position)
1575 case GROUP_TITLE_POSITION_ABOVE:
1576 data->mad_TitleHeightAbove = _font(obj)->tf_Baseline;
1577 break;
1578 case GROUP_TITLE_POSITION_CENTERED:
1579 data->mad_TitleHeightAbove = _font(obj)->tf_YSize / 2;
1580 break;
1583 data->mad_TitleHeightAdd =
1584 _font(obj)->tf_YSize - data->mad_InnerTop - zframe->itop;
1585 data->mad_TitleHeightBelow =
1586 data->mad_TitleHeightAdd - data->mad_TitleHeightAbove;
1591 /**************************************************************************
1592 First method to be called after an OM_NEW, it is the place
1593 for all initializations depending on the environment, but not
1594 on the gadget size/position. Matched by MUIM_Cleanup.
1595 **************************************************************************/
1596 static IPTR Area__MUIM_Setup(struct IClass *cl, Object *obj,
1597 struct MUIP_Setup *msg)
1599 struct MUI_AreaData *data = INST_DATA(cl, obj);
1600 const struct ZuneFrameGfx *zframe;
1601 const struct MUI_FrameSpec_intern *frame;
1602 struct MUI_FrameSpec_intern tempframe;
1604 muiRenderInfo(obj) = msg->RenderInfo;
1606 if (data->mad_Frame)
1608 /* no frame allowed for root object (see Area.doc) */
1609 Object *rootobj = NULL;
1610 get(_win(obj), MUIA_Window_RootObject, &rootobj);
1611 if (rootobj == obj)
1613 data->mad_Frame = MUIV_Frame_None;
1614 data->mad_FrameTitle = NULL;
1618 set_inner_sizes(obj, data);
1619 set_title_sizes(obj, data);
1621 frame = get_intframe(obj, data, &tempframe);
1622 zframe = zune_zframe_get(obj, frame);
1624 area_update_msizes(obj, data, frame, zframe);
1626 if (data->mad_Flags & MADF_OWNBG)
1628 data->mad_Background =
1629 zune_imspec_setup((IPTR) data->mad_BackgroundSpec,
1630 muiRenderInfo(obj));
1633 if ((data->mad_Flags & MADF_SHOWSELSTATE) &&
1634 (data->mad_InputMode != MUIV_InputMode_None))
1636 data->mad_SelBack =
1637 zune_imspec_setup(MUII_SelectedBack, muiRenderInfo(obj));
1640 if (data->mad_InputMode != MUIV_InputMode_None || data->mad_ContextMenu)
1642 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1643 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1644 (IPTR) & data->mad_ehn);
1647 /* Those are filled by RequestIDCMP() */
1648 if (data->mad_hiehn.ehn_Events)
1649 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1650 (IPTR) & data->mad_hiehn);
1652 setup_control_char(data, obj, cl);
1653 // setup_cycle_chain (data, obj);
1655 if (data->mad_FontPreset == MUIV_Font_Inherit)
1657 if (_parent(obj) != NULL && _parent(obj) != _win(obj))
1658 data->mad_Font = _font(_parent(obj));
1659 else
1661 D(bug("Area_Setup %p: getting normal font\n", obj));
1662 data->mad_Font = zune_font_get(obj, MUIV_Font_Normal);
1663 D(bug("Area_Setup %p: got normal font %p\n", obj,
1664 data->mad_Font));
1667 else
1669 data->mad_Font = zune_font_get(obj, data->mad_FontPreset);
1672 _flags(obj) |= MADF_SETUP;
1674 data->mad_Timer.ihn_Flags = MUIIHNF_TIMER;
1675 data->mad_Timer.ihn_Method = MUIM_Timer;
1676 data->mad_Timer.ihn_Object = obj;
1678 return TRUE;
1682 /**************************************************************************
1683 Called to match a MUIM_Setup, when environment is no more available.
1684 **************************************************************************/
1685 static IPTR Area__MUIM_Cleanup(struct IClass *cl, Object *obj,
1686 struct MUIP_Cleanup *msg)
1688 struct MUI_AreaData *data = INST_DATA(cl, obj);
1690 _flags(obj) &= ~MADF_SETUP;
1692 // cleanup_cycle_chain (data, obj);
1693 cleanup_control_char(data, obj);
1695 if (data->mad_Timer.ihn_Millis)
1697 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
1698 (IPTR) & data->mad_Timer);
1699 data->mad_Timer.ihn_Millis = 0;
1702 /* Remove the handler if it is added */
1703 if (data->mad_hiehn.ehn_Events)
1704 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1705 (IPTR) & data->mad_hiehn);
1707 /* Remove the event handler if it has been added */
1708 if (data->mad_ehn.ehn_Events)
1709 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1710 (IPTR) & data->mad_ehn);
1712 D(bug("Area cleanup %p active=%p\n", obj,
1713 (Object *) XGET(_win(obj), MUIA_Window_ActiveObject)));
1714 if (obj == (Object *) XGET(_win(obj), MUIA_Window_ActiveObject))
1716 D(bug("we are active, unset us\n"));
1717 set(_win(obj), MUIA_Window_ActiveObject,
1718 MUIV_Window_ActiveObject_None);
1721 /* It's safe to call the following function with NULL */
1722 if ((data->mad_Flags & MADF_SHOWSELSTATE) &&
1723 (data->mad_InputMode != MUIV_InputMode_None))
1725 zune_imspec_cleanup(data->mad_SelBack);
1726 data->mad_SelBack = NULL;
1728 if (data->mad_Flags & MADF_OWNBG)
1730 zune_imspec_cleanup(data->mad_Background);
1731 data->mad_Background = NULL;
1734 muiRenderInfo(obj) = NULL;
1736 return TRUE;
1740 /**************************************************************************
1741 Called after the window is open and the area layouted, but before
1742 any drawing. Matched by one MUIM_Hide.
1743 Good place to init things depending on gadget size/position.
1744 **************************************************************************/
1745 static IPTR Area__MUIM_Show(struct IClass *cl, Object *obj,
1746 struct MUIP_Show *msg)
1748 struct MUI_AreaData *data = INST_DATA(cl, obj);
1750 zune_imspec_show(data->mad_Background, obj);
1752 if (data->mad_Flags & MADF_SHOWSELSTATE
1753 && data->mad_InputMode != MUIV_InputMode_None)
1755 zune_imspec_show(data->mad_SelBack, obj);
1758 return TRUE;
1761 /**************************************************************************
1762 Called when the window is about to be closed, to match MUIM_Show.
1763 **************************************************************************/
1764 static IPTR Area__MUIM_Hide(struct IClass *cl, Object *obj,
1765 struct MUIP_Hide *msg)
1767 struct MUI_AreaData *data = INST_DATA(cl, obj);
1769 zune_imspec_hide(data->mad_Background);
1770 if (data->mad_Flags & MADF_SHOWSELSTATE
1771 && data->mad_InputMode != MUIV_InputMode_None)
1773 zune_imspec_hide(data->mad_SelBack);
1776 if (data->mad_ContextZMenu)
1778 zune_close_menu(data->mad_ContextZMenu);
1779 data->mad_ContextZMenu = NULL;
1782 return TRUE;
1785 /**************************************************************************
1786 Called when gadget activated
1787 **************************************************************************/
1788 static IPTR Area__MUIM_GoActive(struct IClass *cl, Object *obj, Msg msg)
1790 //bug("Area_GoActive %p\n", obj);
1791 if (_flags(obj) & MADF_CANDRAW)
1792 _zune_focus_new(obj, ZUNE_FOCUS_TYPE_ACTIVE_OBJ);
1793 return TRUE;
1796 /**************************************************************************
1797 Called when gadget deactivated
1798 **************************************************************************/
1799 static IPTR Area__MUIM_GoInactive(struct IClass *cl, Object *obj, Msg msg)
1801 //bug("Area_GoInactive %p\n", obj);
1802 if (_flags(obj) & MADF_CANDRAW)
1803 _zune_focus_destroy(obj, ZUNE_FOCUS_TYPE_ACTIVE_OBJ);
1804 return TRUE;
1807 /**************************************************************************
1808 This one or derived methods won't be called if short help is
1809 not set in area instdata. So set this to a dummy val if overriding
1810 **************************************************************************/
1811 static IPTR Area__MUIM_CreateShortHelp(struct IClass *cl, Object *obj,
1812 struct MUIP_CreateShortHelp *msg)
1814 struct MUI_AreaData *data = INST_DATA(cl, obj);
1816 return (IPTR) data->mad_ShortHelp;
1819 /**************************************************************************
1821 **************************************************************************/
1822 static IPTR Area__MUIM_DeleteShortHelp(struct IClass *cl, Object *obj,
1823 struct MUIP_DeleteShortHelp *msg)
1825 return TRUE;
1828 /**************************************************************************
1830 **************************************************************************/
1831 static IPTR Area__MUIM_CreateBubble(struct IClass *cl, Object *obj,
1832 struct MUIP_CreateBubble *msg)
1834 return (IPTR) zune_bubble_create(obj, msg->x, msg->y, msg->txt,
1835 msg->flags);
1838 /**************************************************************************
1840 **************************************************************************/
1841 static IPTR Area__MUIM_DeleteBubble(struct IClass *cl, Object *obj,
1842 struct MUIP_DeleteBubble *msg)
1844 zune_bubble_delete(obj, msg->bubble);
1846 return TRUE;
1849 /* either lmb or press key */
1850 static void handle_press(struct IClass *cl, Object *obj)
1852 struct MUI_AreaData *data = INST_DATA(cl, obj);
1854 switch (data->mad_InputMode)
1856 case MUIV_InputMode_RelVerify:
1857 set(obj, MUIA_Timer, ++muiAreaData(obj)->mad_Timeval);
1858 if (!data->mad_Timer.ihn_Millis)
1860 data->mad_Timer.ihn_Millis = 300;
1861 DoMethod(_app(obj), MUIM_Application_AddInputHandler,
1862 (IPTR) & data->mad_Timer);
1864 SetAttrs(obj, MUIA_Selected, TRUE, MUIA_Pressed, TRUE, TAG_DONE);
1865 break;
1867 case MUIV_InputMode_Immediate:
1869 IPTR selected = FALSE;
1871 get(obj, MUIA_Selected, &selected);
1872 if (selected)
1874 /* D(bug("handle_press(%p) : nnset MUIA_Selected FALSE\n", obj)); */
1875 nnset(obj, MUIA_Selected, FALSE);
1877 /* D(bug("handle_press(%p) : set MUIA_Selected TRUE\n", obj)); */
1878 set(obj, MUIA_Selected, TRUE);
1879 /* D(bug("handle_press(%p) : done\n", obj)); */
1880 break;
1882 case MUIV_InputMode_Toggle:
1883 // although undocumented, MUI sets MUIA_Pressed too
1884 SetAttrs(obj, MUIA_Selected, !(data->mad_Flags & MADF_SELECTED),
1885 MUIA_Pressed, !(data->mad_Flags & MADF_PRESSED), TAG_DONE);
1886 break;
1890 /* either lmb or release key */
1891 static void handle_release(struct IClass *cl, Object *obj, int cancel)
1893 struct MUI_AreaData *data = INST_DATA(cl, obj);
1895 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
1897 if (data->mad_Flags & MADF_SELECTED)
1899 if (cancel)
1900 nnset(obj, MUIA_Pressed, FALSE);
1901 else
1902 set(obj, MUIA_Pressed, FALSE);
1904 set(obj, MUIA_Selected, FALSE);
1908 if (data->mad_Timer.ihn_Millis)
1910 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
1911 (IPTR) & data->mad_Timer);
1912 data->mad_Timer.ihn_Millis = 0;
1917 static IPTR event_button(Class *cl, Object *obj,
1918 struct IntuiMessage *imsg)
1920 struct MUI_AreaData *data = INST_DATA(cl, obj);
1921 BOOL in = _between(_left(obj), imsg->MouseX, _right(obj))
1922 && _between(_top(obj), imsg->MouseY, _bottom(obj));
1924 switch (imsg->Code)
1926 case SELECTDOWN:
1927 if (data->mad_InputMode == MUIV_InputMode_None)
1928 break;
1930 if (in)
1932 // set(_win(obj), MUIA_Window_ActiveObject, obj);
1933 data->mad_ClickX = imsg->MouseX;
1934 data->mad_ClickY = imsg->MouseY;
1936 if ((data->mad_InputMode != MUIV_InputMode_Toggle)
1937 && (data->mad_Flags & MADF_SELECTED))
1938 break;
1939 nnset(obj, MUIA_Timer, 0);
1940 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
1942 if (data->mad_ehn.ehn_Events)
1943 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1944 (IPTR) &data->mad_ehn);
1945 data->mad_ehn.ehn_Events |= IDCMP_MOUSEMOVE | IDCMP_RAWKEY;
1946 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1947 (IPTR) &data->mad_ehn);
1949 handle_press(cl, obj);
1950 return MUI_EventHandlerRC_Eat;
1952 break;
1954 case SELECTUP:
1955 if (data->mad_InputMode == MUIV_InputMode_None)
1956 break;
1958 if (data->mad_ehn.ehn_Events != IDCMP_MOUSEBUTTONS)
1960 /* Extra events must have been added by SELECTDOWN case above,
1961 so this object is waiting to be unclicked (RelVerify) */
1962 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1963 (IPTR) &data->mad_ehn);
1964 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1965 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1966 (IPTR) &data->mad_ehn);
1967 if (!in)
1968 nnset(obj, MUIA_Pressed, FALSE);
1969 handle_release(cl, obj, FALSE /* cancel */ );
1970 return MUI_EventHandlerRC_Eat;
1972 break;
1974 case MENUDOWN:
1975 if (in && data->mad_ContextMenu)
1977 Object *menuobj =
1978 (Object *) DoMethod(obj, MUIM_ContextMenuBuild,
1979 imsg->MouseX, imsg->MouseY);
1980 if (menuobj)
1982 struct NewMenu *newmenu = NULL;
1984 /* stegerg: HACKME, CHECKME! The menu/menu item objs should
1985 automatically be connected (parentobject setup) without
1986 need for this, but they aren't. Because of how family
1987 class is and is used by other classes, I think!? */
1988 DoMethod(menuobj, MUIM_ConnectParent, obj);
1990 get(menuobj, MUIA_Menuitem_NewMenu, &newmenu);
1991 if (newmenu)
1993 if (data->mad_ContextZMenu)
1994 zune_close_menu(data->mad_ContextZMenu);
1995 data->mad_ContextZMenu =
1996 zune_open_menu(_window(obj), newmenu);
1999 if (data->mad_ehn.ehn_Events)
2000 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2001 (IPTR) &data->mad_ehn);
2002 data->mad_ehn.ehn_Events |= IDCMP_MOUSEMOVE;
2003 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2004 (IPTR) &data->mad_ehn);
2006 return MUI_EventHandlerRC_Eat;
2008 break;
2010 case MENUUP:
2011 if (data->mad_ContextZMenu)
2013 struct MenuItem *item = zune_leave_menu(data->mad_ContextZMenu);
2015 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2016 (IPTR) &data->mad_ehn);
2017 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2018 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2019 (IPTR) &data->mad_ehn);
2021 if (item)
2023 Object *itemobj = (Object *) GTMENUITEM_USERDATA(item);
2025 /* CHECKME: MUIA_MenuItem_Trigger should probably be set inside
2026 MUIM_ContextMenuChoice!? But there I only know about
2027 itemobj, not MenuItem itself! */
2028 if (item->Flags & CHECKIT)
2030 set(itemobj, MUIA_Menuitem_Checked,
2031 ! !(item->Flags & CHECKED));
2035 set(itemobj, MUIA_Menuitem_Trigger, item);
2037 DoMethod(obj, MUIM_ContextMenuChoice, itemobj);
2041 zune_close_menu(data->mad_ContextZMenu);
2042 data->mad_ContextZMenu = NULL;
2044 return MUI_EventHandlerRC_Eat;
2047 break;
2050 return 0;
2053 static IPTR event_motion(Class *cl, Object *obj,
2054 struct IntuiMessage *imsg)
2056 struct MUI_AreaData *data = INST_DATA(cl, obj);
2058 if ((imsg->Qualifier & IEQUALIFIER_RBUTTON) && data->mad_ContextZMenu)
2060 zune_mouse_update(data->mad_ContextZMenu, 0);
2061 return MUI_EventHandlerRC_Eat;
2064 if (imsg->Qualifier & IEQUALIFIER_LEFTBUTTON)
2066 BOOL in = _between(_left(obj), imsg->MouseX, _right(obj))
2067 && _between(_top(obj), imsg->MouseY, _bottom(obj));
2069 if (in)
2071 if ((data->mad_Flags & MADF_DRAGGABLE)
2072 && ((abs(data->mad_ClickX - imsg->MouseX) >= 3)
2073 || (abs(data->mad_ClickY - imsg->MouseY) >= 3)))
2074 /* should be user configurable */
2076 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
2077 set(obj, MUIA_Selected, FALSE);
2078 nnset(obj, MUIA_Pressed, FALSE);
2080 if (data->mad_ehn.ehn_Events)
2081 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2082 (IPTR) &data->mad_ehn);
2083 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2084 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2085 (IPTR) &data->mad_ehn);
2086 if (data->mad_Timer.ihn_Millis)
2088 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
2089 (IPTR) & data->mad_Timer);
2090 data->mad_Timer.ihn_Millis = 0;
2093 DoMethod(obj, MUIM_DoDrag, data->mad_ClickX - _left(obj),
2094 data->mad_ClickY - _top(obj), 0);
2095 return MUI_EventHandlerRC_Eat;
2099 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
2101 if (!in && (data->mad_Flags & MADF_SELECTED)) /* going out */
2103 set(obj, MUIA_Selected, FALSE);
2105 else if (in && !(data->mad_Flags & MADF_SELECTED)) /* going in */
2107 set(obj, MUIA_Selected, TRUE);
2111 return MUI_EventHandlerRC_Eat;
2114 /**************************************************************************
2116 **************************************************************************/
2117 static IPTR Area__MUIM_HandleEvent(struct IClass *cl, Object *obj,
2118 struct MUIP_HandleEvent *msg)
2120 struct MUI_AreaData *data = INST_DATA(cl, obj);
2122 if (data->mad_DisableCount)
2123 return 0;
2124 if (data->mad_InputMode == MUIV_InputMode_None
2125 && !data->mad_ContextMenu)
2126 return 0;
2128 if (msg->muikey != MUIKEY_NONE)
2130 switch (msg->muikey)
2132 case MUIKEY_PRESS:
2133 if (data->mad_Flags & MADF_SELECTED)
2134 break;
2135 if (data->mad_ehn.ehn_Events)
2136 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2137 (IPTR) &data->mad_ehn);
2138 data->mad_ehn.ehn_Events |= IDCMP_RAWKEY;
2139 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2140 (IPTR) &data->mad_ehn);
2141 handle_press(cl, obj);
2142 return MUI_EventHandlerRC_Eat;
2144 case MUIKEY_TOGGLE:
2145 if (data->mad_InputMode == MUIV_InputMode_Toggle)
2146 set(obj, MUIA_Selected, !(data->mad_Flags & MADF_SELECTED));
2147 return MUI_EventHandlerRC_Eat;
2149 case MUIKEY_RELEASE:
2150 if (data->mad_ehn.ehn_Events)
2151 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2152 (IPTR) &data->mad_ehn);
2153 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2154 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2155 (IPTR) &data->mad_ehn);
2156 handle_release(cl, obj, FALSE /* cancel */ );
2157 return MUI_EventHandlerRC_Eat;
2159 return 0;
2162 if (msg->imsg)
2164 switch (msg->imsg->Class)
2166 case IDCMP_MOUSEBUTTONS:
2167 return event_button(cl, obj, msg->imsg);
2168 case IDCMP_MOUSEMOVE:
2169 return event_motion(cl, obj, msg->imsg);
2170 case IDCMP_RAWKEY:
2172 unsigned char code;
2173 UWORD msg_code;
2174 /* Remove the up prefix as convert key does not convert an
2175 * upkey event */
2176 msg_code = msg->imsg->Code;
2177 msg->imsg->Code &= ~IECODE_UP_PREFIX;
2178 code = ConvertKey(msg->imsg);
2179 msg->imsg->Code = msg_code;
2181 if (code != 0 && code == data->mad_ControlChar)
2183 if (msg->imsg->Code & IECODE_UP_PREFIX)
2185 msg->muikey = MUIKEY_RELEASE;
2187 else
2189 msg->muikey = MUIKEY_PRESS;
2191 msg->imsg = NULL;
2192 return Area__MUIM_HandleEvent(cl, obj, msg);
2195 if (msg->imsg->
2196 Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
2198 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2199 (IPTR) &data->mad_ehn);
2200 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2201 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2202 (IPTR) &data->mad_ehn);
2203 handle_release(cl, obj, TRUE /* cancel */ );
2206 /* Do not eat wheel movement events */
2207 if ((msg->imsg->Code == RAWKEY_NM_WHEEL_UP) || (msg->imsg->Code == RAWKEY_NM_WHEEL_DOWN))
2208 return 0;
2210 return MUI_EventHandlerRC_Eat;
2212 break;
2215 return 0;
2218 /**************************************************************************
2220 **************************************************************************/
2221 static IPTR Area__MUIM_HandleInput(struct IClass *cl, Object *obj,
2222 struct MUIP_HandleInput *msg)
2224 /* Actually a dummy, but real MUI does handle here the input stuff which
2225 * Zune has in Area_HandleEvent. For compatibility we should do this too */
2226 //bug("Area_HandleEvent [%p] imsg=%p muikey=%ld\b", obj, msg->imsg,
2227 // msg->muikey);
2228 return 0;
2231 /**************************************************************************
2232 Trivial; custom classes may override this to get dynamic menus.
2233 **************************************************************************/
2234 static IPTR Area__MUIM_ContextMenuBuild(struct IClass *cl, Object *obj,
2235 struct MUIP_ContextMenuBuild *msg)
2237 struct MUI_AreaData *data = INST_DATA(cl, obj);
2238 return (IPTR) data->mad_ContextMenu; /* a Menustrip object */
2241 /**************************************************************************/
2242 static IPTR Area__MUIM_ContextMenuChoice(struct IClass *cl, Object *obj,
2243 struct MUIP_ContextMenuChoice *msg)
2245 set(obj, MUIA_ContextMenuTrigger, msg->item);
2246 return 0;
2250 /**************************************************************************
2251 MUIM_Export : to export an object's "contents" to a dataspace object.
2252 **************************************************************************/
2253 static IPTR Area__MUIM_Export(struct IClass *cl, Object *obj,
2254 struct MUIP_Export *msg)
2256 struct MUI_AreaData *data = INST_DATA(cl, obj);
2257 ULONG id;
2259 if ((id = muiNotifyData(obj)->mnd_ObjectID))
2261 char selected = (data->mad_Flags & MADF_SELECTED) ? 1 : 0;
2262 DoMethod(msg->dataspace, MUIM_Dataspace_Add, (IPTR) & selected,
2263 sizeof(char), (IPTR) id);
2265 return 0;
2269 /**************************************************************************
2270 MUIM_Import : to import an object's "contents" from a dataspace object.
2271 **************************************************************************/
2272 static IPTR Area__MUIM_Import(struct IClass *cl, Object *obj,
2273 struct MUIP_Import *msg)
2275 ULONG id;
2277 if ((id = muiNotifyData(obj)->mnd_ObjectID))
2279 char *selected =
2280 (char *)DoMethod(msg->dataspace, MUIM_Dataspace_Find,
2281 (IPTR) id);
2283 if (selected)
2284 set(obj, MUIA_Selected, *selected);
2286 return 0;
2289 /**************************************************************************
2290 MUIM_Timer
2291 **************************************************************************/
2292 static IPTR Area__MUIM_Timer(struct IClass *cl, Object *obj, Msg msg)
2294 struct MUI_AreaData *data = INST_DATA(cl, obj);
2295 if (data->mad_Timer.ihn_Millis)
2296 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
2297 (IPTR) & data->mad_Timer);
2298 data->mad_Timer.ihn_Millis = 50;
2299 DoMethod(_app(obj), MUIM_Application_AddInputHandler,
2300 (IPTR) & data->mad_Timer);
2302 if (data->mad_Flags & MADF_SELECTED)
2303 set(obj, MUIA_Timer, ++muiAreaData(obj)->mad_Timeval);
2304 return 0;
2307 /**************************************************************************
2308 MUIM_DoDrag
2309 **************************************************************************/
2310 static IPTR Area__MUIM_DoDrag(struct IClass *cl, Object *obj,
2311 struct MUIP_DoDrag *msg)
2313 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2314 DoMethod(_win(obj), MUIM_Window_DragObject, (IPTR) obj, msg->touchx,
2315 msg->touchy, msg->flags);
2316 return 0;
2319 /**************************************************************************
2320 MUIM_CreateDragImage
2321 **************************************************************************/
2322 static IPTR Area__MUIM_CreateDragImage(struct IClass *cl, Object *obj,
2323 struct MUIP_CreateDragImage *msg)
2325 struct MUI_DragImage *img = (struct MUI_DragImage *)
2326 AllocVec(sizeof(struct MUI_DragImage), MEMF_CLEAR);
2327 if (img)
2329 const struct ZuneFrameGfx *zframe;
2330 LONG depth =
2331 GetBitMapAttr(_screen(obj)->RastPort.BitMap, BMA_DEPTH);
2333 zframe =
2334 zune_zframe_get(obj,
2335 &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_Drag]);
2337 img->width = _width(obj) + zframe->ileft + zframe->iright;
2338 img->height = _height(obj) + zframe->itop + zframe->ibottom;
2340 if ((img->bm =
2341 AllocBitMap(img->width, img->height, depth, BMF_MINPLANES,
2342 _screen(obj)->RastPort.BitMap)))
2344 /* Render the stuff now */
2345 struct RastPort *rp_save = muiRenderInfo(obj)->mri_RastPort;
2346 struct RastPort temprp;
2347 InitRastPort(&temprp);
2348 temprp.BitMap = img->bm;
2349 ClipBlit(_rp(obj), _left(obj), _top(obj), &temprp,
2350 zframe->ileft, zframe->itop, _width(obj), _height(obj),
2351 0xc0);
2353 muiRenderInfo(obj)->mri_RastPort = &temprp;
2354 zframe->draw(zframe->customframe, muiRenderInfo(obj), 0, 0,
2355 img->width, img->height, 0, 0, img->width, img->height);
2356 muiRenderInfo(obj)->mri_RastPort = rp_save;
2359 img->touchx = msg->touchx;
2360 img->touchy = msg->touchy;
2361 img->flags = 0;
2363 return (IPTR) img;
2366 /**************************************************************************
2367 MUIM_DeleteDragImage
2368 **************************************************************************/
2369 static IPTR Area__MUIM_DeleteDragImage(struct IClass *cl, Object *obj,
2370 struct MUIP_DeleteDragImage *msg)
2372 if (msg->di)
2374 if (msg->di->bm)
2375 FreeBitMap(msg->di->bm);
2376 FreeVec(msg->di);
2378 return 0;
2381 /**************************************************************************
2382 MUIM_DragQueryExtended
2383 **************************************************************************/
2384 static IPTR Area__MUIM_DragQueryExtended(struct IClass *cl, Object *obj,
2385 struct MUIP_DragQueryExtended *msg)
2387 struct MUI_AreaData *data = INST_DATA(cl, obj);
2388 if (data->mad_Flags & MADF_DROPABLE)
2390 if (_left(obj) <= msg->x && msg->x <= _right(obj)
2391 && _top(obj) <= msg->y && msg->y <= _bottom(obj))
2393 if (DoMethod(obj, MUIM_DragQuery,
2394 (IPTR) msg->obj) == MUIV_DragQuery_Accept)
2395 return (IPTR) obj;
2398 return 0;
2401 /**************************************************************************
2402 MUIM_DragBegin
2403 **************************************************************************/
2404 static IPTR Area__MUIM_DragBegin(struct IClass *cl, Object *obj,
2405 struct MUIP_DragBegin *msg)
2407 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2408 _zune_focus_new(obj, ZUNE_FOCUS_TYPE_DROP_OBJ);
2409 return 0;
2412 /**************************************************************************
2413 MUIM_DragFinish
2414 **************************************************************************/
2415 static IPTR Area__MUIM_DragFinish(struct IClass *cl, Object *obj,
2416 struct MUIP_DragFinish *msg)
2418 //struct MUI_AreaData *data = INST_DATA(cl, obj);
2419 _zune_focus_destroy(obj, ZUNE_FOCUS_TYPE_DROP_OBJ);
2420 return 0;
2425 * Calculates addleft, addtop, subwidth, subheight from current settings.
2426 * If frame phantom, ignore horizontal frame components.
2427 * Depends on inner sizes and frame
2429 static void area_update_msizes(Object *obj, struct MUI_AreaData *data,
2430 const struct MUI_FrameSpec_intern *frame,
2431 const struct ZuneFrameGfx *zframe)
2434 /* if (XGET(obj, MUIA_UserData) == 42) */
2435 /* { */
2436 /* D(bug("area_update_msizes(%p) : ileft=%ld itop=%ld\n", obj, */
2437 /* zframe->ileft, zframe->itop)); */
2438 /* } */
2440 struct dt_frame_image *fi = zframe->customframe;
2442 if (fi != NULL)
2444 //UWORD w = fi->tile_left + fi->tile_right;
2445 //UWORD h = fi->tile_top + fi->tile_bottom;
2447 data->mad_addleft = data->mad_InnerLeft + zframe->ileft;
2448 data->mad_subwidth =
2449 data->mad_addleft + data->mad_InnerRight + zframe->iright;
2450 data->mad_addtop =
2451 data->mad_InnerTop + data->mad_TitleHeightAdd + zframe->itop;
2452 data->mad_subheight =
2453 data->mad_addtop + data->mad_InnerBottom + zframe->ibottom;
2455 else
2457 data->mad_addleft = data->mad_InnerLeft + zframe->ileft;
2458 data->mad_subwidth =
2459 data->mad_addleft + data->mad_InnerRight + zframe->iright;
2460 data->mad_addtop =
2461 data->mad_InnerTop + data->mad_TitleHeightAdd + zframe->itop;
2462 data->mad_subheight =
2463 data->mad_addtop + data->mad_InnerBottom + zframe->ibottom;
2466 if (data->mad_Flags & MADF_FRAMEPHANTOM)
2468 data->mad_addleft = 0;
2469 data->mad_subwidth = 0;
2472 // clamping ... maybe ?
2474 /* D(bug("area_update_msizes(%x,%d) => addleft/top=%d/%d, " */
2475 /* "subwidth/height=%d/%d\n", */
2476 /* obj, data->mad_Frame, data->mad_addleft, data->mad_addtop, */
2477 /* data->mad_subwidth, data->mad_subheight)); */
2480 /**************************************************************************
2481 MUIM_Area_UnknownDropDestination
2482 **************************************************************************/
2483 IPTR Area__MUIM_UnknownDropDestination(struct IClass *cl, Object *obj,
2484 struct MUIP_UnknownDropDestination *msg)
2486 return 0;
2489 /**************************************************************************
2490 MUIM_UpdateInnerSizes - Updates the innersizes of an object. You actually
2491 should only call this method if the dimensions of an object would not be
2492 affected, otherwise the results are unexpected
2493 **************************************************************************/
2494 static IPTR Area__MUIM_UpdateInnerSizes(struct IClass *cl, Object *obj,
2495 struct MUIP_UpdateInnerSizes *msg)
2497 struct MUI_AreaData *data = INST_DATA(cl, obj);
2498 const struct ZuneFrameGfx *zframe;
2499 const struct MUI_FrameSpec_intern *frame;
2500 struct MUI_FrameSpec_intern tempframe;
2502 if (_flags(obj) & MADF_SETUP)
2504 frame = get_intframe(obj, data, &tempframe);
2505 zframe = zune_zframe_get(obj, frame);
2506 area_update_msizes(obj, data, frame, zframe);
2508 return 1;
2511 static IPTR Area__MUIM_FindAreaObject(struct IClass *cl, Object *obj,
2512 struct MUIP_FindAreaObject *msg)
2514 if (msg->obj == obj)
2515 return (IPTR) obj;
2516 else
2517 return (IPTR) NULL;
2520 BOOPSI_DISPATCHER(IPTR, Area_Dispatcher, cl, obj, msg)
2522 switch (msg->MethodID)
2524 case OM_NEW:
2525 return Area__OM_NEW(cl, obj, (struct opSet *)msg);
2526 case OM_DISPOSE:
2527 return Area__OM_DISPOSE(cl, obj, msg);
2528 case OM_SET:
2529 return Area__OM_SET(cl, obj, (struct opSet *)msg);
2530 case OM_GET:
2531 return Area__OM_GET(cl, obj, (struct opGet *)msg);
2532 case MUIM_AskMinMax:
2533 return Area__MUIM_AskMinMax(cl, obj, (APTR) msg);
2534 case MUIM_Draw:
2535 return Area__MUIM_Draw(cl, obj, (APTR) msg);
2536 case MUIM_DrawBackground:
2537 return Area__MUIM_DrawBackground(cl, obj, (APTR) msg);
2538 case MUIM_DrawBackgroundBuffered:
2539 return Area__MUIM_DrawBackgroundBuffered(cl, obj, (APTR) msg);
2540 case MUIM_DrawParentBackground:
2541 return Area__MUIM_DrawParentBackground(cl, obj, (APTR) msg);
2542 case MUIM_Setup:
2543 return Area__MUIM_Setup(cl, obj, (APTR) msg);
2544 case MUIM_Cleanup:
2545 return Area__MUIM_Cleanup(cl, obj, (APTR) msg);
2546 case MUIM_Show:
2547 return Area__MUIM_Show(cl, obj, (APTR) msg);
2548 case MUIM_Hide:
2549 return Area__MUIM_Hide(cl, obj, (APTR) msg);
2550 case MUIM_GoActive:
2551 return Area__MUIM_GoActive(cl, obj, (APTR) msg);
2552 case MUIM_GoInactive:
2553 return Area__MUIM_GoInactive(cl, obj, (APTR) msg);
2554 case MUIM_Layout:
2555 return 1;
2556 case MUIM_CreateShortHelp:
2557 return Area__MUIM_CreateShortHelp(cl, obj, (APTR) msg);
2558 case MUIM_DeleteShortHelp:
2559 return Area__MUIM_DeleteShortHelp(cl, obj, (APTR) msg);
2560 case MUIM_CreateBubble:
2561 return Area__MUIM_CreateBubble(cl, obj, (APTR) msg);
2562 case MUIM_DeleteBubble:
2563 return Area__MUIM_DeleteBubble(cl, obj, (APTR) msg);
2564 case MUIM_HandleEvent:
2565 return Area__MUIM_HandleEvent(cl, obj, (APTR) msg);
2566 case MUIM_ContextMenuBuild:
2567 return Area__MUIM_ContextMenuBuild(cl, obj, (APTR) msg);
2568 case MUIM_ContextMenuChoice:
2569 return Area__MUIM_ContextMenuChoice(cl, obj, (APTR) msg);
2570 case MUIM_Timer:
2571 return Area__MUIM_Timer(cl, obj, msg);
2572 case MUIM_UpdateInnerSizes:
2573 return Area__MUIM_UpdateInnerSizes(cl, obj, (APTR) msg);
2574 case MUIM_DragQuery:
2575 return MUIV_DragQuery_Refuse;
2576 case MUIM_DragBegin:
2577 return Area__MUIM_DragBegin(cl, obj, (APTR) msg);
2578 case MUIM_DragDrop:
2579 return FALSE;
2580 case MUIM_UnknownDropDestination:
2581 return Area__MUIM_UnknownDropDestination(cl, obj, (APTR) msg);
2582 case MUIM_DragFinish:
2583 return Area__MUIM_DragFinish(cl, obj, (APTR) msg);
2584 case MUIM_DragReport:
2585 return MUIV_DragReport_Continue; /* or MUIV_DragReport_Abort? */
2586 case MUIM_DoDrag:
2587 return Area__MUIM_DoDrag(cl, obj, (APTR) msg);
2588 case MUIM_CreateDragImage:
2589 return Area__MUIM_CreateDragImage(cl, obj, (APTR) msg);
2590 case MUIM_DeleteDragImage:
2591 return Area__MUIM_DeleteDragImage(cl, obj, (APTR) msg);
2592 case MUIM_DragQueryExtended:
2593 return Area__MUIM_DragQueryExtended(cl, obj, (APTR) msg);
2594 case MUIM_HandleInput:
2595 return Area__MUIM_HandleInput(cl, obj, (APTR) msg);
2596 case MUIM_FindAreaObject:
2597 return Area__MUIM_FindAreaObject(cl, obj, (APTR) msg);
2599 case MUIM_Export:
2600 return Area__MUIM_Export(cl, obj, (APTR) msg);
2601 case MUIM_Import:
2602 return Area__MUIM_Import(cl, obj, (APTR) msg);
2605 return DoSuperMethodA(cl, obj, msg);
2607 BOOPSI_DISPATCHER_END
2610 * Class descriptor.
2612 const struct __MUIBuiltinClass _MUI_Area_desc =
2614 MUIC_Area,
2615 MUIC_Notify,
2616 sizeof(struct MUI_AreaData),
2617 (void *) Area_Dispatcher