Fixed MUIA_List_AdjustWidth and MUIA_List_AdjustHeight. As well as the
[AROS.git] / workbench / libs / muimaster / classes / area.c
blob51f04dba28990d3d95f0347e75cfb84e42725f86
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2016, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
9 #include <stdlib.h>
10 #include <string.h>
11 #include <exec/types.h>
12 #include <graphics/gfxmacros.h>
13 #include <intuition/imageclass.h>
14 #include <libraries/gadtools.h>
15 #include <devices/rawkeycodes.h>
17 #include <clib/alib_protos.h>
18 #include <proto/exec.h>
19 #include <proto/intuition.h>
20 #include <proto/graphics.h>
21 #include <proto/utility.h>
22 #include <proto/muimaster.h>
24 extern struct Library *MUIMasterBase;
25 #include "muimaster_intern.h"
27 #include "mui.h"
28 #include "support.h"
29 #include "imspec.h"
30 #include "menu.h"
31 #include "prefs.h"
32 #include "font.h"
33 #include "textengine.h"
34 #include "bubbleengine.h"
35 #include "datatypescache.h"
38 // #define MYDEBUG 1
39 #include "debug.h"
42 Area.mui/MUIA_Background done
43 Area.mui/MUIA_BottomEdge done
44 Area.mui/MUIA_ContextMenu done
45 Area.mui/MUIA_ContextMenuTrigger
46 Area.mui/MUIA_ControlChar done
47 Area.mui/MUIA_CycleChain done
48 Area.mui/MUIA_Disabled done
49 Area.mui/MUIA_Draggable done
50 Area.mui/MUIA_Dropable done
51 Area.mui/MUIA_ExportID
52 Area.mui/MUIA_FillArea done
53 Area.mui/MUIA_FixHeight done
54 Area.mui/MUIA_FixHeightTxt done
55 Area.mui/MUIA_FixWidth done
56 Area.mui/MUIA_FixWidthTxt done
57 Area.mui/MUIA_Font done
58 Area.mui/MUIA_Frame done
59 Area.mui/MUIA_FramePhantomHoriz done
60 Area.mui/MUIA_FrameTitle done
61 Area.mui/MUIA_Height done
62 Area.mui/MUIA_HorizDisappear
63 Area.mui/MUIA_HorizWeight done
64 Area.mui/MUIA_InnerBottom done
65 Area.mui/MUIA_InnerLeft done
66 Area.mui/MUIA_InnerRight done
67 Area.mui/MUIA_InnerTop done
68 Area.mui/MUIA_InputMode done
69 Area.mui/MUIA_LeftEdge done
70 Area.mui/MUIA_MaxHeight done
71 Area.mui/MUIA_MaxWidth done
72 Area.mui/MUIA_Pressed done
73 Area.mui/MUIA_RightEdge done
74 Area.mui/MUIA_Selected done
75 Area.mui/MUIA_ShortHelp done
76 Area.mui/MUIA_ShowMe done
77 Area.mui/MUIA_ShowSelState done (I only)
78 Area.mui/MUIA_Timer done
79 Area.mui/MUIA_TopEdge done
80 Area.mui/MUIA_VertDisappear
81 Area.mui/MUIA_VertWeight done
82 Area.mui/MUIA_Weight done
83 Area.mui/MUIA_Width done
84 Area.mui/MUIA_Window done
85 Area.mui/MUIA_WindowObject done
87 Area.mui/MUIM_AskMinMax done
88 Area.mui/MUIM_Cleanup done
89 Area.mui/MUIM_ContextMenuBuild done
90 Area.mui/MUIM_ContextMenuChoice done
91 Area.mui/MUIM_CreateBubble done
92 Area.mui/MUIM_CreateShortHelp done
93 Area.mui/MUIM_DeleteBubble done
94 Area.mui/MUIM_DeleteShortHelp done
95 Area.mui/MUIM_DragBegin
96 Area.mui/MUIM_DragDrop done
97 Area.mui/MUIM_DragFinish
98 Area.mui/MUIM_DragQuery done
99 Area.mui/MUIM_DragReport
100 Area.mui/MUIM_Draw done
101 Area.mui/MUIM_DrawBackground done
102 Area.mui/MUIM_HandleEvent done
103 Area.mui/MUIM_HandleInput
104 Area.mui/MUIM_Hide done
105 Area.mui/MUIM_Setup done
106 Area.mui/MUIM_Show done
109 #if (0)
110 static const int __version = 1;
111 static const int __revision = 1;
113 #ifdef DEBUG
114 static STRPTR zune_area_to_string (Object *area);
115 #endif
116 #endif
118 static const struct MUI_FrameSpec_intern *get_intframe(Object *obj,
119 struct MUI_AreaData *data, struct MUI_FrameSpec_intern *tempstore);
120 static void set_inner_sizes(Object *obj, struct MUI_AreaData *data);
121 static void set_title_sizes(Object *obj, struct MUI_AreaData *data);
122 static void handle_release(struct IClass *cl, Object *obj, int cancel);
124 static void area_update_msizes(Object *obj, struct MUI_AreaData *data,
125 const struct MUI_FrameSpec_intern *frame,
126 const struct ZuneFrameGfx *zframe);
127 static void setup_control_char(struct MUI_AreaData *data, Object *obj,
128 struct IClass *cl);
129 static void cleanup_control_char(struct MUI_AreaData *data, Object *obj);
131 //static void setup_cycle_chain (struct MUI_AreaData *data, Object *obj);
132 //static void cleanup_cycle_chain (struct MUI_AreaData *data, Object *obj);
134 #define ZUNE_FOCUS_TYPE_ACTIVE_OBJ 0
135 #define ZUNE_FOCUS_TYPE_DROP_OBJ 1
137 static void _zune_focus_new(Object *obj, int type)
139 Object *parent;
140 struct RastPort *rp;
141 UWORD oldDrPt;
143 //bug("_zune_focus_new 1 %p\n", obj);
145 if (NULL == obj || !(_flags(obj) & MADF_CANDRAW))
146 return;
148 parent = _parent(obj);
149 rp = _rp(obj);
150 oldDrPt = rp->LinePtrn;
152 int x1 = _left(obj);
153 int y1 = _top(obj);
154 int x2 = _left(obj) + _width(obj) - 1;
155 int y2 = _top(obj) + _height(obj) - 1;
157 if (!parent || parent == _win(obj))
158 return;
160 SetABPenDrMd(rp, _pens(obj)[MPEN_SHINE], _pens(obj)[MPEN_SHADOW], JAM2);
162 if (type == ZUNE_FOCUS_TYPE_ACTIVE_OBJ)
164 SetDrPt(rp, 0xCCCC);
165 x1--;
166 y1--;
167 x2++;
168 y2++;
170 else
172 SetDrPt(rp, 0xF0F0);
175 Move(rp, x1, y1);
176 Draw(rp, x2, y1);
177 Draw(rp, x2, y2);
178 Draw(rp, x1, y2);
179 Draw(rp, x1, y1);
180 SetDrPt(rp, oldDrPt);
183 static void _zune_focus_destroy(Object *obj, int type)
185 Object *parent;
187 //bug("_zune_focus_destroy 1 %p\n", obj);
189 if (NULL == obj || !(_flags(obj) & MADF_CANDRAW))
190 return;
192 parent = _parent(obj);
193 int x1 = _left(obj);
194 int y1 = _top(obj);
195 int x2 = _left(obj) + _width(obj) - 1;
196 int y2 = _top(obj) + _height(obj) - 1;
197 int width;
198 int height;
200 if (type == ZUNE_FOCUS_TYPE_ACTIVE_OBJ)
202 if (!parent || parent == _win(obj))
203 return;
205 x1--;
206 y1--;
207 x2++;
208 y2++;
209 width = x2 - x1 + 1;
210 height = y2 - y1 + 1;
212 DoMethod(parent, MUIM_DrawBackground, x1, y1, width, 1, x1, y1, 0);
213 DoMethod(parent, MUIM_DrawBackground, x2, y1, 1, height, x2, y1, 0);
214 DoMethod(parent, MUIM_DrawBackground, x1, y2, width, 1, x1, y2, 0);
215 DoMethod(parent, MUIM_DrawBackground, x1, y1, 1, height, x1, y1, 0);
217 else
219 struct Region *region;
220 struct Rectangle rect;
221 APTR clip = NULL;
223 region = NewRegion();
224 if (region)
226 rect.MinX = _left(obj);
227 rect.MinY = _top(obj);
228 rect.MaxX = _right(obj);
229 rect.MaxY = _top(obj);
231 OrRectRegion(region, &rect);
233 rect.MinX = _right(obj);
234 rect.MinY = _top(obj);
235 rect.MaxX = _right(obj);
236 rect.MaxY = _bottom(obj);
238 OrRectRegion(region, &rect);
240 rect.MinX = _left(obj);
241 rect.MinY = _bottom(obj);
242 rect.MaxX = _right(obj);
243 rect.MaxY = _bottom(obj);
245 OrRectRegion(region, &rect);
247 rect.MinX = _left(obj);
248 rect.MinY = _top(obj);
249 rect.MaxX = _left(obj);
250 rect.MaxY = _bottom(obj);
252 OrRectRegion(region, &rect);
254 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
258 MUI_Redraw(obj, MADF_DRAWOBJECT);
260 if (region)
262 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
268 /**************************************************************************
269 OM_NEW
270 **************************************************************************/
271 static IPTR Area__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
273 struct MUI_AreaData *data;
274 struct TagItem *tags, *tag;
276 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
277 if (!obj)
278 return FALSE;
280 /* Initial local instance data */
281 data = INST_DATA(cl, obj);
283 data->mad_Flags =
284 MADF_FILLAREA | MADF_SHOWME | MADF_SHOWSELSTATE | MADF_DROPABLE;
285 data->mad_HorizWeight = data->mad_VertWeight = 100;
286 data->mad_InputMode = MUIV_InputMode_None;
288 /* parse initial taglist */
290 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
292 switch (tag->ti_Tag)
294 case MUIA_Background:
296 data->mad_Flags |= MADF_OWNBG;
297 if (data->mad_BackgroundSpec)
299 zune_image_spec_free(data->mad_BackgroundSpec);
301 data->mad_BackgroundSpec =
302 zune_image_spec_duplicate(tag->ti_Data);
304 break;
306 case MUIA_ControlChar:
307 data->mad_ControlChar = tag->ti_Data;
308 break;
310 case MUIA_CycleChain:
311 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
312 MADF_CYCLECHAIN);
313 break;
315 case MUIA_Disabled:
316 case MUIA_NestedDisabled:
317 if (tag->ti_Data)
319 data->mad_DisableCount = 1;
321 break;
323 case MUIA_FillArea:
324 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_FILLAREA);
325 break;
327 case MUIA_Draggable:
328 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DRAGGABLE);
329 break;
331 case MUIA_Dropable:
332 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DROPABLE);
333 break;
335 case MUIA_FixHeight:
336 data->mad_Flags |= MADF_FIXHEIGHT;
337 data->mad_HardHeight = tag->ti_Data;
338 break;
340 case MUIA_FixHeightTxt:
341 data->mad_HardHeightTxt = (STRPTR) tag->ti_Data;
342 break;
344 case MUIA_FixWidth:
345 data->mad_Flags |= MADF_FIXWIDTH;
346 data->mad_HardWidth = tag->ti_Data;
347 break;
349 case MUIA_FixWidthTxt:
350 data->mad_HardWidthTxt = (STRPTR) tag->ti_Data;
351 break;
353 case MUIA_Font:
354 data->mad_FontPreset = tag->ti_Data;
355 break;
357 case MUIA_Frame:
358 data->mad_Frame = tag->ti_Data;
359 break;
361 case MUIA_FramePhantomHoriz:
362 data->mad_Flags |= MADF_FRAMEPHANTOM;
363 break;
365 case MUIA_FrameTitle:
366 data->mad_FrameTitle = (STRPTR) tag->ti_Data;
367 break;
369 case MUIA_HorizWeight:
370 data->mad_HorizWeight = tag->ti_Data;
371 break;
373 case MUIA_InnerBottom:
374 data->mad_Flags |= MADF_INNERBOTTOM;
375 data->mad_InnerBottom = CLAMP((IPTR) tag->ti_Data, 0, 32);
376 break;
378 case MUIA_InnerLeft:
379 data->mad_Flags |= MADF_INNERLEFT;
380 data->mad_InnerLeft = CLAMP((IPTR) tag->ti_Data, 0, 32);
381 break;
383 case MUIA_InnerRight:
384 data->mad_Flags |= MADF_INNERRIGHT;
385 data->mad_InnerRight = CLAMP((IPTR) tag->ti_Data, 0, 32);
386 break;
388 case MUIA_InnerTop:
389 data->mad_Flags |= MADF_INNERTOP;
390 data->mad_InnerTop = CLAMP((IPTR) tag->ti_Data, 0, 32);
391 break;
393 case MUIA_InputMode:
394 data->mad_InputMode = tag->ti_Data;
395 break;
397 case MUIA_MaxHeight:
398 data->mad_Flags |= MADF_MAXHEIGHT;
399 data->mad_HardHeight = tag->ti_Data;
400 break;
402 case MUIA_MaxWidth:
403 data->mad_Flags |= MADF_MAXWIDTH;
404 data->mad_HardWidth = tag->ti_Data;
405 break;
407 case MUIA_Selected:
408 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_SELECTED);
409 break;
411 case MUIA_ShortHelp:
412 data->mad_ShortHelp = (STRPTR) tag->ti_Data;
413 break;
415 case MUIA_ShowMe:
416 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_SHOWME);
417 break;
419 case MUIA_ShowSelState:
420 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
421 MADF_SHOWSELSTATE);
422 break;
424 case MUIA_VertWeight:
425 data->mad_VertWeight = tag->ti_Data;
426 break;
428 case MUIA_Weight:
429 data->mad_HorizWeight = data->mad_VertWeight = tag->ti_Data;
430 break;
432 case MUIA_ContextMenu:
433 data->mad_ContextMenu = (Object *) tag->ti_Data;
434 break;
438 /* In Soliton MUIA_Selected was set to MUIV_InputMode_RelVerify (=1)
439 ** for MUIA_Input_Mode MUIV_InputMode_RelVerify which is wrong of
440 ** course but MUI seems to filter this out so we have to do it also
442 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
444 if (data->mad_Flags & MADF_SELECTED)
445 D(bug("MUIA_Selected was set in OM_NEW, "
446 "although being in MUIV_InputMode_RelVerify\n"));
447 data->mad_Flags &= ~MADF_SELECTED;
450 data->mad_ehn.ehn_Events = 0; /* Will be filled on demand */
451 data->mad_ehn.ehn_Priority = -5;
453 /* Please also send mui key events to us, no idea if mui handles this
454 * like this */
455 data->mad_ehn.ehn_Flags = MUI_EHF_ALWAYSKEYS;
456 data->mad_ehn.ehn_Object = obj;
457 data->mad_ehn.ehn_Class = cl;
459 data->mad_hiehn.ehn_Events = 0;
460 data->mad_hiehn.ehn_Priority = -10;
461 data->mad_hiehn.ehn_Flags = MUI_EHF_HANDLEINPUT;
462 data->mad_hiehn.ehn_Object = obj;
463 data->mad_hiehn.ehn_Class = 0;
465 return (IPTR) obj;
468 /**************************************************************************
469 OM_DISPOSE
470 **************************************************************************/
471 static IPTR Area__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
473 struct MUI_AreaData *data = INST_DATA(cl, obj);
475 /* Safe to call this with NULL */
476 zune_image_spec_free(data->mad_BackgroundSpec);
478 return DoSuperMethodA(cl, obj, msg);
482 /**************************************************************************
483 OM_SET
484 **************************************************************************/
485 static IPTR Area__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
487 struct MUI_AreaData *data = INST_DATA(cl, obj);
488 struct TagItem *tags = msg->ops_AttrList;
489 struct TagItem *tag;
490 CONST_STRPTR old_backgroundspec;
492 int change_disable = 0; /* Has the disable state changed? */
494 while ((tag = NextTagItem(&tags)) != NULL)
496 switch (tag->ti_Tag)
498 case MUIA_Background:
499 old_backgroundspec = data->mad_BackgroundSpec;
500 data->mad_BackgroundSpec =
501 zune_image_spec_duplicate(tag->ti_Data);
502 if (!data->mad_BackgroundSpec)
504 /* Out of memory */
505 data->mad_BackgroundSpec = old_backgroundspec;
506 break;
509 data->mad_Flags |= MADF_OWNBG;
511 if (old_backgroundspec
512 && (strcmp(data->mad_BackgroundSpec,
513 old_backgroundspec) == 0))
515 /* New background does not differ from old one */
516 zune_image_spec_free(old_backgroundspec);
517 tag->ti_Tag = TAG_IGNORE;
518 break;
521 zune_image_spec_free(old_backgroundspec);
523 if (data->mad_Background)
525 if (_flags(obj) & MADF_CANDRAW)
527 zune_imspec_hide(data->mad_Background);
529 if (_flags(obj) & MADF_SETUP)
531 zune_imspec_cleanup(data->mad_Background);
532 data->mad_Background = NULL;
536 if (_flags(obj) & MADF_SETUP)
538 data->mad_Background =
539 zune_imspec_setup((IPTR) data->mad_BackgroundSpec,
540 muiRenderInfo(obj));
542 if (_flags(obj) & MADF_CANDRAW)
544 zune_imspec_show(data->mad_Background, obj);
546 MUI_Redraw(obj, MADF_DRAWOBJECT);
547 break;
549 case MUIA_FillArea:
550 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_FILLAREA);
551 break;
553 case MUIA_Frame:
554 /* this is not documented in MUI but it is possible,
555 and needed to suppress frame for external images */
556 data->mad_Frame = tag->ti_Data;
557 if (muiGlobalInfo(obj))
559 set_inner_sizes(obj, data);
560 set_title_sizes(obj, data);
562 break;
564 case MUIA_ControlChar:
565 if (_flags(obj) & MADF_SETUP)
566 cleanup_control_char(data, obj);
567 data->mad_ControlChar = tag->ti_Data;
568 if (_flags(obj) & MADF_SETUP)
569 setup_control_char(data, obj, cl);
570 break;
572 case MUIA_CycleChain:
573 // if (data->mad_InputMode == MUIV_InputMode_None)
574 // break;
576 if ((!(_flags(obj) & MADF_CYCLECHAIN) && tag->ti_Data)
577 || ((_flags(obj) & MADF_CYCLECHAIN) && !tag->ti_Data))
579 if (_flags(obj) & MADF_SETUP)
581 cleanup_control_char(data, obj);
582 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
583 MADF_CYCLECHAIN);
584 setup_control_char(data, obj, cl);
586 else
587 _handle_bool_tag(data->mad_Flags, tag->ti_Data,
588 MADF_CYCLECHAIN);
590 break;
592 case MUIA_Disabled:
593 if (tag->ti_Data)
595 if (!data->mad_DisableCount)
597 data->mad_DisableCount = 1;
598 change_disable = 1;
601 else
603 if (data->mad_DisableCount)
605 data->mad_DisableCount = 0;
606 change_disable = 1;
609 break;
611 case MUIA_NestedDisabled:
612 if (tag->ti_Data)
614 if (!data->mad_DisableCount)
615 change_disable = 1;
616 data->mad_DisableCount++;
618 else
620 if (data->mad_DisableCount)
622 data->mad_DisableCount--;
623 if (!data->mad_DisableCount)
624 change_disable = 1;
627 break;
630 case MUIA_HorizWeight:
631 data->mad_HorizWeight = tag->ti_Data;
632 break;
634 case MUIA_Pressed:
635 if (tag->ti_Data)
636 data->mad_Flags |= MADF_PRESSED;
637 else
638 data->mad_Flags &= ~MADF_PRESSED;
639 break;
641 case MUIA_ShortHelp:
642 data->mad_ShortHelp = (STRPTR) tag->ti_Data;
643 break;
645 case MUIA_ShowMe:
647 ULONG oldflags = data->mad_Flags;
648 int recalc = 0;
650 if (tag->ti_Data)
651 data->mad_Flags |= MADF_SHOWME;
652 else
653 data->mad_Flags &= ~MADF_SHOWME;
655 if (oldflags != data->mad_Flags)
657 if (!tag->ti_Data)
659 /* Should be made invisible, so send a MUIM_Hide and
660 ** then a MUIM_Cleanup to the object if needed,
661 ** as objects with MUIA_ShowMe to false get neither
662 ** MUIM_Setup nor MUIM_Show */
663 if (_flags(obj) & MADF_CANDRAW)
665 DoHideMethod(obj);
666 recalc = 1;
668 #if 0 /* SHOWME affects only show/hide */
669 if (_flags(obj) & MADF_SETUP)
670 DoMethod(obj, MUIM_Cleanup);
671 #endif
673 else
675 Object *parent = _parent(obj);
676 /* Will be NULL if direct child of a window! */
678 if (parent)
680 #if 0 /* SHOWME affects only show/hide */
681 if (_flags(parent) & MADF_SETUP)
682 DoSetupMethod(obj, muiRenderInfo(parent));
683 #endif
684 if (_flags(parent) & MADF_CANDRAW)
686 DoShowMethod(obj);
687 recalc = 1;
690 else
692 /* Check if window is open... */
696 /* If renderinfo is NULL _win(obj) doesn't work (crash) */
697 if (recalc && muiRenderInfo(obj))
699 DoMethod(_win(obj), MUIM_Window_RecalcDisplay,
700 (IPTR) _parent(obj));
704 break;
706 case MUIA_Selected:
707 /* D(bug(" Area_Set(%p) :
708 MUIA_Selected val=%ld sss=%d\n", obj, tag->ti_Data,
709 !!(data->mad_Flags & MADF_SHOWSELSTATE)));
711 if (tag->ti_Data && !(data->mad_Flags & MADF_SELECTED))
713 data->mad_Flags |= MADF_SELECTED;
714 MUI_Redraw(obj, MADF_DRAWOBJECT);
716 else if (!tag->ti_Data && (data->mad_Flags & MADF_SELECTED))
718 data->mad_Flags &= ~MADF_SELECTED;
719 MUI_Redraw(obj, MADF_DRAWOBJECT);
721 #if 0 // CHECKME: What's the purpose of this? What superclass will care?
722 else
724 tag->ti_Tag = TAG_IGNORE;
726 #endif
727 break;
729 case MUIA_Timer:
730 data->mad_Timeval = tag->ti_Data;
731 break;
733 case MUIA_VertWeight:
734 data->mad_VertWeight = tag->ti_Data;
735 break;
737 case MUIA_Draggable:
738 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DRAGGABLE);
739 break;
741 case MUIA_Dropable:
742 _handle_bool_tag(data->mad_Flags, tag->ti_Data, MADF_DROPABLE);
743 break;
745 case MUIA_ContextMenu:
746 data->mad_ContextMenu = (Object *) tag->ti_Data;
747 break;
749 case MUIA_Font:
750 data->mad_FontPreset = tag->ti_Data;
751 break;
753 case MUIA_InputMode:
754 data->mad_InputMode = tag->ti_Data;
755 break;
760 if (change_disable)
762 /* Simulate left mouse button release if the area becomes disabled */
763 if (_flags(obj) & MADF_SETUP)
764 handle_release(cl, obj, TRUE);
765 MUI_Redraw(obj, MADF_DRAWOBJECT);
768 return DoSuperMethodA(cl, obj, (Msg) msg);
772 /**************************************************************************
773 OM_GET
774 **************************************************************************/
775 static IPTR Area__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
777 #define STORE *(msg->opg_Storage)
779 struct MUI_AreaData *data = INST_DATA(cl, obj);
781 switch (msg->opg_AttrID)
783 case MUIA_Background:
784 STORE = (IPTR) data->mad_Background;
785 return TRUE;
787 case MUIA_BottomEdge:
788 STORE = (IPTR) _bottom(obj);
789 return TRUE;
791 case MUIA_ControlChar:
792 STORE = data->mad_ControlChar;
793 return TRUE;
795 case MUIA_CycleChain:
796 STORE = ((data->mad_Flags & MADF_CYCLECHAIN) != 0);
797 return TRUE;
799 case MUIA_Disabled:
800 case MUIA_NestedDisabled:
801 STORE = ! !data->mad_DisableCount; /* BOOLEAN */
802 return TRUE;
804 case MUIA_Font:
805 STORE = (IPTR) data->mad_FontPreset;
806 return TRUE;
808 case MUIA_Height:
809 STORE = (IPTR) _height(obj);
810 return TRUE;
812 case MUIA_HorizWeight:
813 STORE = (IPTR) data->mad_HorizWeight;
814 return TRUE;
816 case MUIA_InnerBottom:
817 STORE = (IPTR) data->mad_InnerBottom;
818 return TRUE;
820 case MUIA_InnerLeft:
821 STORE = (IPTR) data->mad_InnerLeft;
822 return TRUE;
824 case MUIA_InnerRight:
825 STORE = (IPTR) data->mad_InnerRight;
826 return TRUE;
828 case MUIA_InnerTop:
829 STORE = (IPTR) data->mad_InnerTop;
830 return TRUE;
832 case MUIA_LeftEdge:
833 STORE = (IPTR) _left(obj);
834 return TRUE;
836 case MUIA_Pressed:
837 STORE = ! !(data->mad_Flags & MADF_PRESSED);
838 return TRUE;
840 case MUIA_RightEdge:
841 STORE = (IPTR) _right(obj);
842 return TRUE;
844 case MUIA_Selected:
845 STORE = ! !(data->mad_Flags & MADF_SELECTED);
846 return TRUE;
848 case MUIA_ShortHelp:
849 STORE = (IPTR) data->mad_ShortHelp;
850 return TRUE;
852 case MUIA_ShowMe:
853 STORE = ! !(data->mad_Flags & MADF_SHOWME);
854 return TRUE;
856 case MUIA_Timer:
857 STORE = data->mad_Timeval;
858 return TRUE;
860 case MUIA_TopEdge:
861 STORE = (IPTR) _top(obj);
862 return TRUE;
864 case MUIA_VertWeight:
865 STORE = (IPTR) data->mad_VertWeight;
866 return TRUE;
868 case MUIA_Width:
869 STORE = (IPTR) _width(obj);
870 return TRUE;
872 case MUIA_Window:
873 if (muiAreaData(obj)->mad_RenderInfo)
874 STORE = (IPTR) _window(obj);
875 else
876 STORE = 0L;
877 return TRUE;
879 case MUIA_WindowObject:
880 if (muiAreaData(obj)->mad_RenderInfo)
881 STORE = (IPTR) _win(obj);
882 else
883 STORE = 0L;
884 return TRUE;
886 case MUIA_ContextMenu:
887 STORE = (IPTR) data->mad_ContextMenu;
888 return TRUE;
890 case MUIA_Frame:
891 STORE = (IPTR) data->mad_Frame;
892 return TRUE;
894 case MUIA_Draggable:
895 STORE = !!(data->mad_Flags & MADF_DRAGGABLE);
896 return TRUE;
898 case MUIA_Dropable:
899 STORE = !!(data->mad_Flags & MADF_DROPABLE);
900 return TRUE;
903 return (DoSuperMethodA(cl, obj, (Msg) msg));
904 #undef STORE
908 /**************************************************************************
909 MUIM_AskMinMax
910 **************************************************************************/
911 static IPTR Area__MUIM_AskMinMax(struct IClass *cl, Object *obj,
912 struct MUIP_AskMinMax *msg)
914 struct MUI_AreaData *data = INST_DATA(cl, obj);
915 const struct ZuneFrameGfx *zframe;
916 const struct MUI_FrameSpec_intern *frame;
917 struct MUI_FrameSpec_intern tempframe;
919 frame = get_intframe(obj, data, &tempframe);
920 zframe = zune_zframe_get(obj, frame);
922 area_update_msizes(obj, data, frame, zframe);
924 msg->MinMaxInfo->MinWidth = _subwidth(obj);
925 msg->MinMaxInfo->MinHeight = _subheight(obj);
927 msg->MinMaxInfo->MaxWidth = msg->MinMaxInfo->MinWidth;
928 msg->MinMaxInfo->MaxHeight = msg->MinMaxInfo->MinHeight;
929 msg->MinMaxInfo->DefWidth = msg->MinMaxInfo->MinWidth;
930 msg->MinMaxInfo->DefHeight = msg->MinMaxInfo->MinHeight;
932 /* D(bug("Area_AskMinMax 0x%lx (%s): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n",
933 obj, data->mad_FrameTitle, */
934 /* msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight, */
935 /* msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight, */
936 /* msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight)); */
938 return TRUE;
942 * Called after MUIM_AskMinMax, to handle fixed and max sizes.
944 void __area_finish_minmax(Object *obj, struct MUI_MinMax *MinMaxInfo)
946 struct MUI_AreaData *data = muiAreaData(obj);
948 if ((_flags(obj) & MADF_FIXHEIGHT) && (data->mad_HardHeight > 0))
950 int h = data->mad_HardHeight + data->mad_subheight;
952 MinMaxInfo->MinHeight =
953 MinMaxInfo->DefHeight =
954 MinMaxInfo->MaxHeight =
955 CLAMP(h, MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
957 else if (data->mad_HardHeightTxt)
959 ZText *text;
961 if ((text =
962 zune_text_new(NULL, data->mad_HardHeightTxt, ZTEXT_ARG_NONE,
963 0)))
965 zune_text_get_bounds(text, obj);
967 MinMaxInfo->MinHeight =
968 MinMaxInfo->DefHeight =
969 MinMaxInfo->MaxHeight =
970 CLAMP(text->height + data->mad_subheight,
971 MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
973 zune_text_destroy(text);
977 else if (_flags(obj) & MADF_MAXHEIGHT)
979 MinMaxInfo->MaxHeight =
980 CLAMP(data->mad_HardHeight + data->mad_subheight,
981 MinMaxInfo->MinHeight, MinMaxInfo->MaxHeight);
984 if ((_flags(obj) & MADF_FIXWIDTH) && (data->mad_HardWidth > 0))
986 int w = data->mad_HardWidth + data->mad_subwidth;
988 MinMaxInfo->MinWidth =
989 MinMaxInfo->DefWidth =
990 MinMaxInfo->MaxWidth =
991 CLAMP(w, MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
993 else if (data->mad_HardWidthTxt)
995 ZText *text;
997 if ((text =
998 zune_text_new(NULL, data->mad_HardWidthTxt, ZTEXT_ARG_NONE,
999 0)))
1001 zune_text_get_bounds(text, obj);
1003 MinMaxInfo->MinWidth =
1004 MinMaxInfo->DefWidth =
1005 MinMaxInfo->MaxWidth =
1006 CLAMP(text->width + data->mad_subwidth,
1007 MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
1009 zune_text_destroy(text);
1013 else if (_flags(obj) & MADF_MAXWIDTH)
1015 MinMaxInfo->MaxWidth =
1016 CLAMP(data->mad_HardWidth + data->mad_subwidth,
1017 MinMaxInfo->MinWidth, MinMaxInfo->MaxWidth);
1020 /* Set minmax */
1021 _minwidth(obj) = MinMaxInfo->MinWidth;
1022 _minheight(obj) = MinMaxInfo->MinHeight;
1023 _maxwidth(obj) = MinMaxInfo->MaxWidth;
1024 _maxheight(obj) = MinMaxInfo->MaxHeight;
1025 _defwidth(obj) = MinMaxInfo->DefWidth;
1026 _defheight(obj) = MinMaxInfo->DefHeight;
1029 /* <-- _top(obj) (frame title position depends of _top(obj))
1030 * ==== Title === <-- frame_top (depends of title, if centered/above)
1031 * | | <-- bgtop (depends of frame, bg always begins under frame)
1032 * | |
1033 * | |
1034 * ============== <-- "bgbottom" and "frame_bottom" (frame overwrites bg (1))
1036 * (1) : needed for phantom frame objects, where no frame overwrites bg, thus bg
1037 * must go as far as theoretical bottom frame border.
1041 * draw object background if MADF_FILLAREA.
1043 static void Area_Draw_handle_background(Object *obj,
1044 struct MUI_AreaData *data, ULONG flags,
1045 const struct ZuneFrameGfx *zframe)
1047 struct MUI_ImageSpec_intern *background;
1048 struct Rectangle r, r2, rects[4];
1049 int i, bgtop, bgleft, bgw, bgh, numrects;
1051 if (!(data->mad_Flags & MADF_SELECTED)
1052 || !(data->mad_Flags & MADF_SHOWSELSTATE))
1053 background = data->mad_Background;
1054 else
1055 background = data->mad_SelBack;
1057 if (zframe->customframe)
1059 bgtop = _top(obj) + data->mad_TitleHeightAbove;
1061 else
1063 bgtop = _top(obj) + data->mad_TitleHeightAbove + zframe->itop;
1066 bgleft = _left(obj);
1067 bgw = _width(obj);
1068 bgh = _height(obj) - bgtop + _top(obj);
1070 r.MinX = bgleft;
1071 r.MinY = bgtop;
1072 r.MaxX = bgleft + bgw - 1;
1073 r.MaxY = bgtop + bgh - 1;
1075 if (data->mad_Flags & MADF_FILLAREA)
1077 rects[0] = r;
1078 numrects = 1;
1080 else
1082 /* MADF_FILLAREA not set. Only draw frame outside of
1083 innerbox (_mleft, _mtop, _mright, _mbottom):
1085 .............
1086 .***********.
1087 .*#########*.
1088 .*#########*.
1089 .***********.
1090 .............
1092 # = innerbox
1093 * = frame outside of innerbox
1094 . = object frame
1097 r2.MinX = _mleft(obj);
1098 r2.MinY = _mtop(obj);
1099 r2.MaxX = _mright(obj);
1100 r2.MaxY = _mbottom(obj);
1102 numrects = SubtractRectFromRect(&r, &r2, rects);
1105 for (i = 0; i < numrects; i++)
1107 if (!background)
1109 /* This will do the rest, TODO: on MADF_DRAWALL we not really
1110 * need to draw this */
1111 /* D(bug(" Area_Draw(%p):%ld: MUIM_DrawBackground\n", obj,
1112 __LINE__)); */
1113 /* ATTENTION: This draws the clipped away regions of the area.
1114 * Comment out and check the result to see what I mean. */
1115 DoMethod(obj, MUIM_DrawBackground,
1116 rects[i].MinX, rects[i].MinY,
1117 rects[i].MaxX - rects[i].MinX + 1,
1118 rects[i].MaxY - rects[i].MinY + 1, rects[i].MinX,
1119 rects[i].MinY, data->mad_Flags);
1121 else
1123 /* D(bug(" Area_Draw(%p):%ld: zune_imspec_draw\n", obj,
1124 __LINE__)); */
1125 zune_imspec_draw(background, data->mad_RenderInfo,
1126 rects[i].MinX, rects[i].MinY,
1127 rects[i].MaxX - rects[i].MinX + 1,
1128 rects[i].MaxY - rects[i].MinY + 1, rects[i].MinX,
1129 rects[i].MinY, 0);
1133 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
1134 WINDOW_REDRAW_WITHOUT_CLEAR)
1136 if (bgtop > _top(obj) && !(flags & MADF_DRAWALL))
1138 /* Fill in the gap produced by the title with the background
1139 * of the parent object but only if
1140 * the upper object hasn't drawn it already
1141 * (which is the case if MADF_DRAWALL is setted) */
1142 DoMethod(obj, MUIM_DrawParentBackground, bgleft, _top(obj), bgw,
1143 bgtop - _top(obj), bgleft, _top(obj), data->mad_Flags);
1150 * draw object frame + title if not MADF_FRAMEPHANTOM.
1152 static void Area_Draw_handle_frame(Object *obj, struct MUI_AreaData *data,
1153 const struct ZuneFrameGfx *zframe)
1155 APTR textdrawclip = (APTR) - 1;
1156 struct Region *region;
1157 int tx;
1158 int tw, frame_height, frame_top;
1159 int addtw;
1160 struct TextExtent te;
1161 int nchars;
1162 int maxtxtwidth;
1164 /* no frametitle, just draw frame and return */
1165 if (!data->mad_FrameTitle)
1167 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1168 _top(obj), _width(obj), _height(obj), _left(obj), _top(obj),
1169 _width(obj), _height(obj));
1170 return;
1173 /* set clipping so that frame is not drawn behind title */
1175 switch (muiGlobalInfo(obj)->mgi_Prefs->group_title_color)
1177 case GROUP_TITLE_COLOR_OUTLINE:
1178 addtw = 2;
1179 break;
1180 case GROUP_TITLE_COLOR_3D:
1181 addtw = 1;
1182 break;
1183 default:
1184 addtw = 0;
1187 maxtxtwidth =
1188 _width(obj) - zframe->ileft - zframe->iright - 2 * 5 - addtw;
1190 nchars = TextFit(_rp(obj), data->mad_FrameTitle,
1191 strlen(data->mad_FrameTitle),
1192 &te, NULL, 1, maxtxtwidth, _font(obj)->tf_YSize);
1194 tw = te.te_Width + addtw;
1195 tx = _left(obj) + (_width(obj) - tw) / 2;
1197 frame_top = _top(obj) + data->mad_TitleHeightAbove;
1198 frame_height = _height(obj) - frame_top + _top(obj);
1200 if ((region = NewRegion()))
1202 struct Rectangle rect;
1203 int hspace = _font(obj)->tf_YSize / 8;
1205 rect.MinX = tx - hspace;
1206 rect.MinY = _top(obj);
1207 rect.MaxX = tx + tw - 1 + hspace;
1208 rect.MaxY = _top(obj) + _font(obj)->tf_YSize - 1;
1209 // frame is not thick enough anyway
1210 OrRectRegion(region, &rect);
1212 rect.MinX = _left(obj);
1213 rect.MinY = _top(obj);
1214 rect.MaxX = _right(obj);
1215 rect.MaxY = _bottom(obj);
1216 XorRectRegion(region, &rect);
1218 textdrawclip = MUI_AddClipRegion(muiRenderInfo(obj), region);
1221 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1222 frame_top, _width(obj), frame_height, _left(obj), frame_top,
1223 _width(obj), frame_height);
1225 if (region && textdrawclip != (APTR) - 1)
1227 MUI_RemoveClipRegion(muiRenderInfo(obj), textdrawclip);
1228 /* DisposeRegion(region);*/ /* sba: DisposeRegion happens in MUI_RemoveClipRegion, this seems wrong to me */
1231 /* Title text drawing */
1232 SetDrMd(_rp(obj), JAM1);
1233 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
1234 if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1235 GROUP_TITLE_COLOR_3D)
1237 Move(_rp(obj), tx + 1, _top(obj) + _font(obj)->tf_Baseline + 1);
1238 Text(_rp(obj), data->mad_FrameTitle, nchars);
1239 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1240 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1241 Text(_rp(obj), data->mad_FrameTitle, nchars);
1243 else if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1244 GROUP_TITLE_COLOR_OUTLINE)
1246 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1248 tx += addtw / 2;
1249 Move(_rp(obj), tx + 1, _top(obj) + _font(obj)->tf_Baseline);
1250 Text(_rp(obj), data->mad_FrameTitle, nchars);
1251 Move(_rp(obj), tx - 1, _top(obj) + _font(obj)->tf_Baseline);
1252 Text(_rp(obj), data->mad_FrameTitle, nchars);
1253 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline + 1);
1254 Text(_rp(obj), data->mad_FrameTitle, nchars);
1255 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline - 1);
1256 Text(_rp(obj), data->mad_FrameTitle, nchars);
1258 SetAPen(_rp(obj), _pens(obj)[MPEN_SHADOW]);
1259 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1260 Text(_rp(obj), data->mad_FrameTitle, nchars);
1262 else
1264 if (muiGlobalInfo(obj)->mgi_Prefs->group_title_color ==
1265 GROUP_TITLE_COLOR_HILITE)
1267 SetAPen(_rp(obj), _pens(obj)[MPEN_SHINE]);
1269 Move(_rp(obj), tx, _top(obj) + _font(obj)->tf_Baseline);
1270 Text(_rp(obj), data->mad_FrameTitle, nchars);
1274 /**************************************************************************
1275 MUIM_Draw
1276 **************************************************************************/
1277 static IPTR Area__MUIM_Draw(struct IClass *cl, Object *obj,
1278 struct MUIP_Draw *msg)
1280 struct MUI_AreaData *data = INST_DATA(cl, obj);
1281 const struct ZuneFrameGfx *zframe;
1282 struct TextFont *obj_font = NULL;
1283 ULONG flags = data->mad_Flags & MADF_DRAWFLAGS;
1285 //APTR areaclip;
1287 /* D(bug("Area_Draw(0x%lx) %ldx%ldx%ldx%ld\n", obj, _left(obj),
1288 _top(obj),_right(obj),_bottom(obj))); */
1289 /* D(bug(" Area_Draw(%p) msg=0x%08lx flags=0x%08lx\n", obj, msg->flags,
1290 _flags(obj))); */
1292 if (flags & MADF_DRAWALL)
1293 flags |= MADF_DRAWOBJECT;
1295 msg->flags = flags;
1296 data->mad_Flags &= ~MADF_DRAWFLAGS;
1298 if (!(flags & MADF_DRAWOBJECT))
1300 /* dont draw bg/frame, let subclass redraw content only
1302 return 0;
1306 /* Background can't be drawn without knowing anything about frame, thus some
1307 * calculations are made before background and frame drawing.
1310 /* on selected state, will get the opposite frame */
1311 const struct MUI_FrameSpec_intern *frame;
1312 struct MUI_FrameSpec_intern tempframe;
1313 int state;
1315 frame = get_intframe(obj, data, &tempframe);
1316 state = frame->state;
1317 if ((data->mad_Flags & MADF_SELECTED)
1318 && (data->mad_Flags & MADF_SHOWSELSTATE))
1319 state ^= 1;
1321 zframe = zune_zframe_get_with_state(obj, frame, state);
1323 /* update innersizes as there are frames which have different inner
1324 * spacings in selected state */
1325 area_update_msizes(obj, data, frame, zframe);
1328 /* Background drawing */
1329 Area_Draw_handle_background(obj, data, msg->flags, zframe);
1331 obj_font = _font(obj);
1332 _font(obj) = zune_font_get(obj, MUIV_Font_Title);
1333 SetFont(_rp(obj), _font(obj));
1335 /* Frame and frametitle drawing */
1336 if (!(data->mad_Flags & MADF_FRAMEPHANTOM))
1338 Area_Draw_handle_frame(obj, data, zframe);
1341 _font(obj) = obj_font;
1342 SetFont(_rp(obj), _font(obj));
1344 /* MUI_RemoveClipping(muiRenderInfo(obj), areaclip);*/
1346 return TRUE;
1349 /**************************************************************************
1350 MUIM_DrawParentBackground
1351 **************************************************************************/
1352 static IPTR Area__MUIM_DrawParentBackground(struct IClass *cl, Object *obj,
1353 struct MUIP_DrawParentBackground *msg)
1355 struct MUI_AreaData *data = INST_DATA(cl, obj);
1356 Object *parent = NULL;
1358 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1359 return FALSE;
1361 get(obj, MUIA_Parent, &parent);
1362 if (parent)
1364 DoMethod(parent, MUIM_DrawBackground, msg->left, msg->top,
1365 msg->width, msg->height, msg->xoffset, msg->yoffset,
1366 msg->flags);
1368 else
1370 D(bug
1371 ("Area_DrawParentBackground(%p) : MUIM_Window_DrawBackground\n",
1372 obj));
1373 DoMethod(_win(obj), MUIM_Window_DrawBackground, msg->left, msg->top,
1374 msg->width, msg->height, msg->xoffset, msg->yoffset,
1375 msg->flags);
1377 return TRUE;
1380 /**************************************************************************
1381 MUIM_DrawBackground
1382 **************************************************************************/
1383 static IPTR Area__MUIM_DrawBackground(struct IClass *cl, Object *obj,
1384 struct MUIP_DrawBackground *msg)
1386 struct MUI_AreaData *data = INST_DATA(cl, obj);
1387 struct MUI_ImageSpec_intern *bg;
1388 LONG state;
1390 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1391 return FALSE;
1393 if ((msg->flags & MADF_SELECTED) && (msg->flags & MADF_SHOWSELSTATE)
1394 && data->mad_SelBack)
1396 /* D(bug("Area_DrawBackground(%p): selected bg\n", obj)); */
1397 bg = data->mad_SelBack;
1398 state = IDS_SELECTED;
1400 else
1402 /* D(bug("Area_DrawBackground(%p): normal bg\n", obj)); */
1403 bg = data->mad_Background;
1404 state = IDS_NORMAL;
1407 const struct ZuneFrameGfx *zframe;
1408 const struct MUI_FrameSpec_intern *frame;
1409 struct MUI_FrameSpec_intern tempframe;
1411 if (!bg)
1413 D(bug("Area_DrawBackground(%p) : MUIM_DrawParentBackground\n",
1414 obj));
1416 return DoMethod(obj, MUIM_DrawParentBackground, msg->left, msg->top,
1417 msg->width, msg->height, msg->xoffset, msg->yoffset,
1418 msg->flags);
1421 frame = get_intframe(obj, data, &tempframe);
1423 int xstate = frame->state;
1424 if ((data->mad_Flags & MADF_SELECTED)
1425 && (data->mad_Flags & MADF_SHOWSELSTATE))
1426 xstate ^= 1;
1428 zframe = zune_zframe_get_with_state(obj, frame, xstate);
1430 if (zframe->customframe == NULL)
1432 /* D(bug("Area_DrawBackground(%p): draw bg\n", obj)); */
1433 zune_imspec_draw(bg, data->mad_RenderInfo,
1434 msg->left, msg->top, msg->width, msg->height,
1435 msg->xoffset, msg->yoffset, state);
1437 // if (!data->mad_FrameTitle)
1438 // {
1441 else
1443 if (zframe->noalpha == FALSE)
1445 zune_imspec_draw(bg, data->mad_RenderInfo,
1446 msg->left, msg->top, msg->width, msg->height,
1447 msg->xoffset, msg->yoffset, state);
1452 if (zframe->customframe)
1454 zframe->draw(zframe->customframe, muiRenderInfo(obj), _left(obj),
1455 _top(obj), _width(obj), _height(obj), msg->left, msg->top,
1456 msg->width, msg->height);
1459 return TRUE;
1462 static IPTR Area__MUIM_DrawBackgroundBuffered(struct IClass *cl,
1463 Object *obj, struct MUIP_DrawBackgroundBuffered *msg)
1465 struct MUI_AreaData *data = INST_DATA(cl, obj);
1466 struct MUI_ImageSpec_intern *bg;
1467 LONG state = 0;
1469 if (!(data->mad_Flags & MADF_CANDRAW)) /* not between show/hide */
1470 return FALSE;
1472 bg = data->mad_Background;
1474 /* D(bug("Area_DrawBackground(%p): draw bg\n", obj)); */
1475 zune_imspec_drawbuffered(bg, msg->rp, data->mad_RenderInfo,
1476 msg->left, msg->top, msg->width, msg->height,
1477 msg->xoffset + msg->left, msg->yoffset + msg->top, state, msg->left,
1478 msg->top, 1, _mleft(obj), _mtop(obj), _mright(obj), _mbottom(obj));
1480 return TRUE;
1483 /* Perverting the EventHandlerNode structure to specify a shortcut.
1485 static void setup_control_char(struct MUI_AreaData *data, Object *obj,
1486 struct IClass *cl)
1488 if (data->mad_ControlChar != 0 || data->mad_Flags & MADF_CYCLECHAIN)
1490 data->mad_ccn.ehn_Events = data->mad_ControlChar;
1491 switch (data->mad_InputMode)
1493 case MUIV_InputMode_RelVerify:
1494 data->mad_ccn.ehn_Flags = MUIKEY_PRESS;
1495 break;
1496 case MUIV_InputMode_Toggle:
1497 data->mad_ccn.ehn_Flags = MUIKEY_TOGGLE;
1498 break;
1499 case MUIV_InputMode_Immediate:
1500 data->mad_ccn.ehn_Flags = MUIKEY_PRESS;
1501 break;
1503 data->mad_ccn.ehn_Priority = 0;
1504 data->mad_ccn.ehn_Object = obj;
1505 data->mad_ccn.ehn_Class = cl;
1506 DoMethod(_win(obj), MUIM_Window_AddControlCharHandler,
1507 (IPTR) & data->mad_ccn);
1512 static void cleanup_control_char(struct MUI_AreaData *data, Object *obj)
1514 if (data->mad_ControlChar != 0 || data->mad_Flags & MADF_CYCLECHAIN)
1516 DoMethod(_win(obj),
1517 MUIM_Window_RemControlCharHandler, (IPTR) & data->mad_ccn);
1521 static const struct MUI_FrameSpec_intern *get_intframe(Object *obj,
1522 struct MUI_AreaData *data, struct MUI_FrameSpec_intern *tempstore)
1524 if (data->mad_Frame > 100)
1526 /* Frame is spec in string format. Store it in tempstore and return
1527 a pointer to it. The caller should have such a temp variable on
1528 the stack. Don't want to add it to MUI_AreaData as that will
1529 increase mem usage of every object. */
1531 if (zune_frame_spec_to_intern((CONST_STRPTR) data->mad_Frame,
1532 tempstore))
1534 return tempstore;
1536 else
1538 return &muiGlobalInfo(obj)->mgi_Prefs->frames[MUIV_Frame_None];
1541 else
1543 /* Frame is MUIV_Frame_<something> */
1544 return &muiGlobalInfo(obj)->mgi_Prefs->frames[data->mad_Frame];
1548 static void set_inner_sizes(Object *obj, struct MUI_AreaData *data)
1550 const struct MUI_FrameSpec_intern *frame;
1551 struct MUI_FrameSpec_intern tempframe;
1553 frame = get_intframe(obj, data, &tempframe);
1554 // Use frame inner spacing when not hardcoded
1555 if (!(data->mad_Flags & MADF_INNERLEFT))
1556 data->mad_InnerLeft = frame->innerLeft;
1557 if (!(data->mad_Flags & MADF_INNERTOP))
1558 data->mad_InnerTop = frame->innerTop;
1559 if (!(data->mad_Flags & MADF_INNERRIGHT))
1560 data->mad_InnerRight = frame->innerRight;
1561 if (!(data->mad_Flags & MADF_INNERBOTTOM))
1562 data->mad_InnerBottom = frame->innerBottom;
1566 static void set_title_sizes(Object *obj, struct MUI_AreaData *data)
1568 if (data->mad_FrameTitle)
1570 const struct ZuneFrameGfx *zframe;
1571 const struct MUI_FrameSpec_intern *frame;
1572 struct MUI_FrameSpec_intern tempframe;
1574 frame = get_intframe(obj, data, &tempframe);
1575 zframe = zune_zframe_get(obj, frame);
1577 _font(obj) = zune_font_get(obj, MUIV_Font_Title);
1579 switch (muiGlobalInfo(obj)->mgi_Prefs->group_title_position)
1581 case GROUP_TITLE_POSITION_ABOVE:
1582 data->mad_TitleHeightAbove = _font(obj)->tf_Baseline;
1583 break;
1584 case GROUP_TITLE_POSITION_CENTERED:
1585 data->mad_TitleHeightAbove = _font(obj)->tf_YSize / 2;
1586 break;
1589 data->mad_TitleHeightAdd =
1590 _font(obj)->tf_YSize - data->mad_InnerTop - zframe->itop;
1591 data->mad_TitleHeightBelow =
1592 data->mad_TitleHeightAdd - data->mad_TitleHeightAbove;
1597 /**************************************************************************
1598 First method to be called after an OM_NEW, it is the place
1599 for all initializations depending on the environment, but not
1600 on the gadget size/position. Matched by MUIM_Cleanup.
1601 **************************************************************************/
1602 static IPTR Area__MUIM_Setup(struct IClass *cl, Object *obj,
1603 struct MUIP_Setup *msg)
1605 struct MUI_AreaData *data = INST_DATA(cl, obj);
1606 const struct ZuneFrameGfx *zframe;
1607 const struct MUI_FrameSpec_intern *frame;
1608 struct MUI_FrameSpec_intern tempframe;
1610 muiRenderInfo(obj) = msg->RenderInfo;
1612 if (data->mad_Frame)
1614 /* no frame allowed for root object (see Area.doc) */
1615 Object *rootobj = NULL;
1616 get(_win(obj), MUIA_Window_RootObject, &rootobj);
1617 if (rootobj == obj)
1619 data->mad_Frame = MUIV_Frame_None;
1620 data->mad_FrameTitle = NULL;
1624 set_inner_sizes(obj, data);
1625 set_title_sizes(obj, data);
1627 frame = get_intframe(obj, data, &tempframe);
1628 zframe = zune_zframe_get(obj, frame);
1630 area_update_msizes(obj, data, frame, zframe);
1632 if (data->mad_Flags & MADF_OWNBG)
1634 data->mad_Background =
1635 zune_imspec_setup((IPTR) data->mad_BackgroundSpec,
1636 muiRenderInfo(obj));
1639 if ((data->mad_Flags & MADF_SHOWSELSTATE) &&
1640 (data->mad_InputMode != MUIV_InputMode_None))
1642 data->mad_SelBack =
1643 zune_imspec_setup(MUII_SelectedBack, muiRenderInfo(obj));
1646 if (data->mad_InputMode != MUIV_InputMode_None || data->mad_ContextMenu)
1648 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1649 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1650 (IPTR) & data->mad_ehn);
1653 /* Those are filled by RequestIDCMP() */
1654 if (data->mad_hiehn.ehn_Events)
1655 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1656 (IPTR) & data->mad_hiehn);
1658 setup_control_char(data, obj, cl);
1659 // setup_cycle_chain (data, obj);
1661 if (data->mad_FontPreset == MUIV_Font_Inherit)
1663 if (_parent(obj) != NULL && _parent(obj) != _win(obj))
1664 data->mad_Font = _font(_parent(obj));
1665 else
1667 D(bug("Area_Setup %p: getting normal font\n", obj));
1668 data->mad_Font = zune_font_get(obj, MUIV_Font_Normal);
1669 D(bug("Area_Setup %p: got normal font %p\n", obj,
1670 data->mad_Font));
1673 else
1675 data->mad_Font = zune_font_get(obj, data->mad_FontPreset);
1678 _flags(obj) |= MADF_SETUP;
1680 data->mad_Timer.ihn_Flags = MUIIHNF_TIMER;
1681 data->mad_Timer.ihn_Method = MUIM_Timer;
1682 data->mad_Timer.ihn_Object = obj;
1684 return TRUE;
1688 /**************************************************************************
1689 Called to match a MUIM_Setup, when environment is no longer available.
1690 **************************************************************************/
1691 static IPTR Area__MUIM_Cleanup(struct IClass *cl, Object *obj,
1692 struct MUIP_Cleanup *msg)
1694 struct MUI_AreaData *data = INST_DATA(cl, obj);
1696 _flags(obj) &= ~MADF_SETUP;
1698 // cleanup_cycle_chain (data, obj);
1699 cleanup_control_char(data, obj);
1701 if (data->mad_Timer.ihn_Millis)
1703 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
1704 (IPTR) & data->mad_Timer);
1705 data->mad_Timer.ihn_Millis = 0;
1708 /* Remove the handler if it is added */
1709 if (data->mad_hiehn.ehn_Events)
1710 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1711 (IPTR) & data->mad_hiehn);
1713 /* Remove the event handler if it has been added */
1714 if (data->mad_ehn.ehn_Events)
1715 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1716 (IPTR) & data->mad_ehn);
1718 D(bug("Area cleanup %p active=%p\n", obj,
1719 (Object *) XGET(_win(obj), MUIA_Window_ActiveObject)));
1720 if (obj == (Object *) XGET(_win(obj), MUIA_Window_ActiveObject))
1722 D(bug("we are active, unset us\n"));
1723 set(_win(obj), MUIA_Window_ActiveObject,
1724 MUIV_Window_ActiveObject_None);
1727 /* It's safe to call the following function with NULL */
1728 if ((data->mad_Flags & MADF_SHOWSELSTATE) &&
1729 (data->mad_InputMode != MUIV_InputMode_None))
1731 zune_imspec_cleanup(data->mad_SelBack);
1732 data->mad_SelBack = NULL;
1734 if (data->mad_Flags & MADF_OWNBG)
1736 zune_imspec_cleanup(data->mad_Background);
1737 data->mad_Background = NULL;
1740 muiRenderInfo(obj) = NULL;
1742 return TRUE;
1746 /**************************************************************************
1747 Called after the window is open and the area layouted, but before
1748 any drawing. Matched by one MUIM_Hide.
1749 Good place to init things depending on gadget size/position.
1750 **************************************************************************/
1751 static IPTR Area__MUIM_Show(struct IClass *cl, Object *obj,
1752 struct MUIP_Show *msg)
1754 struct MUI_AreaData *data = INST_DATA(cl, obj);
1756 zune_imspec_show(data->mad_Background, obj);
1758 if (data->mad_Flags & MADF_SHOWSELSTATE
1759 && data->mad_InputMode != MUIV_InputMode_None)
1761 zune_imspec_show(data->mad_SelBack, obj);
1764 return TRUE;
1767 /**************************************************************************
1768 Called when the window is about to be closed, to match MUIM_Show.
1769 **************************************************************************/
1770 static IPTR Area__MUIM_Hide(struct IClass *cl, Object *obj,
1771 struct MUIP_Hide *msg)
1773 struct MUI_AreaData *data = INST_DATA(cl, obj);
1775 zune_imspec_hide(data->mad_Background);
1776 if (data->mad_Flags & MADF_SHOWSELSTATE
1777 && data->mad_InputMode != MUIV_InputMode_None)
1779 zune_imspec_hide(data->mad_SelBack);
1782 if (data->mad_ContextZMenu)
1784 zune_close_menu(data->mad_ContextZMenu);
1785 data->mad_ContextZMenu = NULL;
1788 return TRUE;
1791 /**************************************************************************
1792 Called when gadget activated
1793 **************************************************************************/
1794 static IPTR Area__MUIM_GoActive(struct IClass *cl, Object *obj, Msg msg)
1796 //bug("Area_GoActive %p\n", obj);
1797 if (_flags(obj) & MADF_CANDRAW)
1798 _zune_focus_new(obj, ZUNE_FOCUS_TYPE_ACTIVE_OBJ);
1799 return TRUE;
1802 /**************************************************************************
1803 Called when gadget deactivated
1804 **************************************************************************/
1805 static IPTR Area__MUIM_GoInactive(struct IClass *cl, Object *obj, Msg msg)
1807 //bug("Area_GoInactive %p\n", obj);
1808 if (_flags(obj) & MADF_CANDRAW)
1809 _zune_focus_destroy(obj, ZUNE_FOCUS_TYPE_ACTIVE_OBJ);
1810 return TRUE;
1813 /**************************************************************************
1814 This one or derived methods won't be called if short help is
1815 not set in area instdata. So set this to a dummy val if overriding
1816 **************************************************************************/
1817 static IPTR Area__MUIM_CreateShortHelp(struct IClass *cl, Object *obj,
1818 struct MUIP_CreateShortHelp *msg)
1820 struct MUI_AreaData *data = INST_DATA(cl, obj);
1822 return (IPTR) data->mad_ShortHelp;
1825 /**************************************************************************
1827 **************************************************************************/
1828 static IPTR Area__MUIM_DeleteShortHelp(struct IClass *cl, Object *obj,
1829 struct MUIP_DeleteShortHelp *msg)
1831 return TRUE;
1834 /**************************************************************************
1836 **************************************************************************/
1837 static IPTR Area__MUIM_CreateBubble(struct IClass *cl, Object *obj,
1838 struct MUIP_CreateBubble *msg)
1840 return (IPTR) zune_bubble_create(obj, msg->x, msg->y, msg->txt,
1841 msg->flags);
1844 /**************************************************************************
1846 **************************************************************************/
1847 static IPTR Area__MUIM_DeleteBubble(struct IClass *cl, Object *obj,
1848 struct MUIP_DeleteBubble *msg)
1850 zune_bubble_delete(obj, msg->bubble);
1852 return TRUE;
1855 /* either lmb or press key */
1856 static void handle_press(struct IClass *cl, Object *obj)
1858 struct MUI_AreaData *data = INST_DATA(cl, obj);
1860 switch (data->mad_InputMode)
1862 case MUIV_InputMode_RelVerify:
1863 SetAttrs(obj, MUIA_Selected, TRUE, MUIA_Pressed, TRUE, TAG_DONE);
1864 set(obj, MUIA_Timer, ++muiAreaData(obj)->mad_Timeval);
1865 if (!data->mad_Timer.ihn_Millis && data->mad_DisableCount == 0)
1867 data->mad_Timer.ihn_Millis = 300;
1868 DoMethod(_app(obj), MUIM_Application_AddInputHandler,
1869 (IPTR) & data->mad_Timer);
1871 break;
1873 case MUIV_InputMode_Immediate:
1875 IPTR selected = FALSE;
1877 get(obj, MUIA_Selected, &selected);
1878 if (selected)
1880 /* D(bug("handle_press(%p) : nnset MUIA_Selected FALSE\n", obj)); */
1881 nnset(obj, MUIA_Selected, FALSE);
1883 /* D(bug("handle_press(%p) : set MUIA_Selected TRUE\n", obj)); */
1884 set(obj, MUIA_Selected, TRUE);
1885 /* D(bug("handle_press(%p) : done\n", obj)); */
1886 break;
1888 case MUIV_InputMode_Toggle:
1889 // although undocumented, MUI sets MUIA_Pressed too
1890 SetAttrs(obj, MUIA_Selected, !(data->mad_Flags & MADF_SELECTED),
1891 MUIA_Pressed, !(data->mad_Flags & MADF_PRESSED), TAG_DONE);
1892 break;
1896 /* either lmb or release key */
1897 static void handle_release(struct IClass *cl, Object *obj, int cancel)
1899 struct MUI_AreaData *data = INST_DATA(cl, obj);
1901 if (data->mad_ehn.ehn_Events)
1902 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1903 (IPTR) &data->mad_ehn);
1904 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
1905 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1906 (IPTR) &data->mad_ehn);
1908 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
1910 if (data->mad_Flags & MADF_SELECTED)
1912 if (cancel)
1913 nnset(obj, MUIA_Pressed, FALSE);
1914 else
1915 set(obj, MUIA_Pressed, FALSE);
1917 set(obj, MUIA_Selected, FALSE);
1921 if (data->mad_Timer.ihn_Millis)
1923 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
1924 (IPTR) & data->mad_Timer);
1925 data->mad_Timer.ihn_Millis = 0;
1930 static IPTR event_button(Class *cl, Object *obj,
1931 struct IntuiMessage *imsg)
1933 struct MUI_AreaData *data = INST_DATA(cl, obj);
1934 BOOL in = _between(_left(obj), imsg->MouseX, _right(obj))
1935 && _between(_top(obj), imsg->MouseY, _bottom(obj));
1937 switch (imsg->Code)
1939 case SELECTDOWN:
1940 if (data->mad_InputMode == MUIV_InputMode_None)
1941 break;
1943 if (in)
1945 // set(_win(obj), MUIA_Window_ActiveObject, obj);
1946 data->mad_ClickX = imsg->MouseX;
1947 data->mad_ClickY = imsg->MouseY;
1949 if ((data->mad_InputMode != MUIV_InputMode_Toggle)
1950 && (data->mad_Flags & MADF_SELECTED))
1951 break;
1952 nnset(obj, MUIA_Timer, 0);
1953 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
1955 if (data->mad_ehn.ehn_Events)
1956 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
1957 (IPTR) &data->mad_ehn);
1958 data->mad_ehn.ehn_Events |= IDCMP_MOUSEMOVE | IDCMP_RAWKEY;
1959 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
1960 (IPTR) &data->mad_ehn);
1962 handle_press(cl, obj);
1963 return MUI_EventHandlerRC_Eat;
1965 break;
1967 case SELECTUP:
1968 if (data->mad_InputMode == MUIV_InputMode_None)
1969 break;
1971 if (data->mad_ehn.ehn_Events != IDCMP_MOUSEBUTTONS)
1973 handle_release(cl, obj, FALSE /* cancel */ );
1974 return MUI_EventHandlerRC_Eat;
1976 break;
1978 case MENUDOWN:
1979 if (in && data->mad_ContextMenu)
1981 Object *menuobj =
1982 (Object *) DoMethod(obj, MUIM_ContextMenuBuild,
1983 imsg->MouseX, imsg->MouseY);
1984 if (menuobj)
1986 struct NewMenu *newmenu = NULL;
1988 /* stegerg: HACKME, CHECKME! The menu/menu item objs should
1989 automatically be connected (parentobject setup) without
1990 need for this, but they aren't. Because of how family
1991 class is and is used by other classes, I think!? */
1992 DoMethod(menuobj, MUIM_ConnectParent, obj);
1994 get(menuobj, MUIA_Menuitem_NewMenu, &newmenu);
1995 if (newmenu)
1997 if (data->mad_ContextZMenu)
1998 zune_close_menu(data->mad_ContextZMenu);
1999 data->mad_ContextZMenu =
2000 zune_open_menu(_window(obj), newmenu);
2003 if (data->mad_ehn.ehn_Events)
2004 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2005 (IPTR) &data->mad_ehn);
2006 data->mad_ehn.ehn_Events |= IDCMP_MOUSEMOVE;
2007 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2008 (IPTR) &data->mad_ehn);
2010 return MUI_EventHandlerRC_Eat;
2012 break;
2014 case MENUUP:
2015 if (data->mad_ContextZMenu)
2017 struct MenuItem *item = zune_leave_menu(data->mad_ContextZMenu);
2019 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2020 (IPTR) &data->mad_ehn);
2021 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2022 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2023 (IPTR) &data->mad_ehn);
2025 if (item)
2027 Object *itemobj = (Object *) GTMENUITEM_USERDATA(item);
2029 /* CHECKME: MUIA_MenuItem_Trigger should probably be set inside
2030 MUIM_ContextMenuChoice!? But there I only know about
2031 itemobj, not MenuItem itself! */
2032 if (item->Flags & CHECKIT)
2034 set(itemobj, MUIA_Menuitem_Checked,
2035 ! !(item->Flags & CHECKED));
2039 set(itemobj, MUIA_Menuitem_Trigger, item);
2041 DoMethod(obj, MUIM_ContextMenuChoice, itemobj);
2045 zune_close_menu(data->mad_ContextZMenu);
2046 data->mad_ContextZMenu = NULL;
2048 return MUI_EventHandlerRC_Eat;
2051 break;
2054 return 0;
2057 static IPTR event_motion(Class *cl, Object *obj,
2058 struct IntuiMessage *imsg)
2060 struct MUI_AreaData *data = INST_DATA(cl, obj);
2062 if ((imsg->Qualifier & IEQUALIFIER_RBUTTON) && data->mad_ContextZMenu)
2064 zune_mouse_update(data->mad_ContextZMenu, 0);
2065 return MUI_EventHandlerRC_Eat;
2068 if (imsg->Qualifier & IEQUALIFIER_LEFTBUTTON)
2070 BOOL in = _between(_left(obj), imsg->MouseX, _right(obj))
2071 && _between(_top(obj), imsg->MouseY, _bottom(obj));
2073 if (in)
2075 if ((data->mad_Flags & MADF_DRAGGABLE)
2076 && ((abs(data->mad_ClickX - imsg->MouseX) >= 3)
2077 || (abs(data->mad_ClickY - imsg->MouseY) >= 3)))
2078 /* should be user configurable */
2080 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
2081 set(obj, MUIA_Selected, FALSE);
2082 nnset(obj, MUIA_Pressed, FALSE);
2084 if (data->mad_ehn.ehn_Events)
2085 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2086 (IPTR) &data->mad_ehn);
2087 data->mad_ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
2088 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2089 (IPTR) &data->mad_ehn);
2090 if (data->mad_Timer.ihn_Millis)
2092 DoMethod(_app(obj), MUIM_Application_RemInputHandler,
2093 (IPTR) & data->mad_Timer);
2094 data->mad_Timer.ihn_Millis = 0;
2097 DoMethod(obj, MUIM_DoDrag, data->mad_ClickX - _left(obj),
2098 data->mad_ClickY - _top(obj), 0);
2099 return MUI_EventHandlerRC_Eat;
2103 if (data->mad_InputMode == MUIV_InputMode_RelVerify)
2105 if (!in && (data->mad_Flags & MADF_SELECTED)) /* going out */
2107 set(obj, MUIA_Selected, FALSE);
2109 else if (in && !(data->mad_Flags & MADF_SELECTED)) /* going in */
2111 set(obj, MUIA_Selected, TRUE);
2115 return MUI_EventHandlerRC_Eat;
2118 /**************************************************************************
2120 **************************************************************************/
2121 static IPTR Area__MUIM_HandleEvent(struct IClass *cl, Object *obj,
2122 struct MUIP_HandleEvent *msg)
2124 struct MUI_AreaData *data = INST_DATA(cl, obj);
2126 if (data->mad_DisableCount)
2127 return 0;
2128 if (data->mad_InputMode == MUIV_InputMode_None
2129 && !data->mad_ContextMenu)
2130 return 0;
2132 if (msg->muikey != MUIKEY_NONE)
2134 switch (msg->muikey)
2136 case MUIKEY_PRESS:
2137 if (data->mad_Flags & MADF_SELECTED)
2138 break;
2139 if (data->mad_ehn.ehn_Events)
2140 DoMethod(_win(obj), MUIM_Window_RemEventHandler,
2141 (IPTR) &data->mad_ehn);
2142 data->mad_ehn.ehn_Events |= IDCMP_RAWKEY;
2143 DoMethod(_win(obj), MUIM_Window_AddEventHandler,
2144 (IPTR) &data->mad_ehn);
2145 handle_press(cl, obj);
2146 return MUI_EventHandlerRC_Eat;
2148 case MUIKEY_TOGGLE:
2149 if (data->mad_InputMode == MUIV_InputMode_Toggle)
2150 set(obj, MUIA_Selected, !(data->mad_Flags & MADF_SELECTED));
2151 return MUI_EventHandlerRC_Eat;
2153 case MUIKEY_RELEASE:
2154 handle_release(cl, obj, FALSE /* cancel */ );
2155 return MUI_EventHandlerRC_Eat;
2157 return 0;
2160 if (msg->imsg)
2162 switch (msg->imsg->Class)
2164 case IDCMP_MOUSEBUTTONS:
2165 return event_button(cl, obj, msg->imsg);
2166 case IDCMP_MOUSEMOVE:
2167 return event_motion(cl, obj, msg->imsg);
2168 case IDCMP_RAWKEY:
2170 unsigned char code;
2171 UWORD msg_code;
2172 /* Remove the up prefix as convert key does not convert an
2173 * upkey event */
2174 msg_code = msg->imsg->Code;
2175 msg->imsg->Code &= ~IECODE_UP_PREFIX;
2176 code = ConvertKey(msg->imsg);
2177 msg->imsg->Code = msg_code;
2179 if (code != 0 && code == data->mad_ControlChar)
2181 if (msg->imsg->Code & IECODE_UP_PREFIX)
2183 msg->muikey = MUIKEY_RELEASE;
2185 else
2187 msg->muikey = MUIKEY_PRESS;
2189 msg->imsg = NULL;
2190 return Area__MUIM_HandleEvent(cl, obj, msg);
2193 if (msg->imsg->
2194 Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
2196 handle_release(cl, obj, TRUE /* cancel */ );
2199 /* Do not eat wheel movement events */
2200 if ((msg->imsg->Code == RAWKEY_NM_WHEEL_UP)
2201 || (msg->imsg->Code == RAWKEY_NM_WHEEL_DOWN))
2202 return 0;
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