move additional libs under workbench/
[AROS-Contrib.git] / bgui / baseclass.c
blob02c0b3cde036f2ddd59ab9068b9f0a641701c5c7
1 /*
2 * @(#) $Header$
4 * BGUI library
5 * baseclass.c
7 * (C) Copyright 1998 Manuel Lemos.
8 * (C) Copyright 1996-1997 Ian J. Einman.
9 * (C) Copyright 1993-1996 Jaba Development.
10 * (C) Copyright 1993-1996 Jan van den Baard.
11 * All Rights Reserved.
13 * $Log$
14 * Revision 42.9 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.8 2003/01/18 19:09:55 chodorowski
18 * Instead of using the _AROS or __AROS preprocessor symbols, use __AROS__.
20 * Revision 42.7 2000/08/17 15:09:18 chodorowski
21 * Fixed compiler warnings.
23 * Revision 42.6 2000/08/10 17:52:47 stegerg
24 * temp fix for relayout refresh bug which only happens in AROS. temp. solved
25 * by doing a RefreshGList in windowclass.c/WindowClassRelease method.
27 * Revision 42.5 2000/08/09 11:45:57 chodorowski
28 * Removed a lot of #ifdefs that disabled the AROS_LIB* macros when not building on AROS. This is now handled in contrib/bgui/include/bgui_compilerspecific.h.
30 * Revision 42.4 2000/07/07 17:07:49 stegerg
31 * fixed PACKW #define, which must be different on AROS, because
32 * I changed all methods to use STACKULONG/STACKUWORD/??? types.
34 * Revision 42.3 2000/05/29 00:40:23 bergers
35 * Update to compile with AROS now. Should also still compile with SASC etc since I only made changes that test the define __AROS__. The compilation is still very noisy but it does the trick for the main directory. Maybe members of the BGUI team should also have a look at the compiler warnings because some could also cause problems on other systems... (Comparison always TRUE due to datatype (or something like that)). And please compile it on an Amiga to see whether it still works... Thanks.
37 * Revision 42.2 2000/05/15 19:27:00 stegerg
38 * another hundreds of REG() macro replacements in func headers/protos.
40 * Revision 42.1 2000/05/14 23:32:46 stegerg
41 * changed over 200 function headers which all use register
42 * parameters (oh boy ...), because the simple REG() macro
43 * doesn't work with AROS. And there are still hundreds
44 * of headers left to be fixed :(
46 * Many of these functions would also work with stack
47 * params, but since i have fixed every single one
48 * I encountered up to now, I guess will have to do
49 * the same for the rest.
51 * Revision 42.0 2000/05/09 22:08:19 mlemos
52 * Bumped to revision 42.0 before handing BGUI to AROS team
54 * Revision 41.11 2000/05/09 19:53:49 mlemos
55 * Merged with the branch Manuel_Lemos_fixes.
57 * Revision 41.10.2.15 1999/08/30 00:46:12 mlemos
58 * Fixed rendering a object in BASE_RELAYOUT when the minimum dimensions did
59 * not change.
61 * Revision 41.10.2.14 1999/08/30 00:20:01 mlemos
62 * Assured that the object is not rendered in BASE_RELAYOUT if it is inhibited.
64 * Revision 41.10.2.13 1999/08/29 20:21:55 mlemos
65 * Renamed the GRM_RELAYOUT to BASE_RELAYOUT.
67 * Revision 41.10.2.12 1999/08/01 04:15:28 mlemos
68 * Avoided trying to copy invisible rendered portions of an object in a view.
70 * Revision 41.10.2.11 1999/07/26 22:17:33 mlemos
71 * Re-enabled drag token conversion into a window while stopped.
73 * Revision 41.10.2.10 1999/07/03 15:17:31 mlemos
74 * Replaced the calls to CallHookPkt to BGUI_CallHookPkt.
76 * Revision 41.10.2.9 1998/12/08 03:28:20 mlemos
77 * Ensured that whenever the gadget border activation flags are changed the
78 * the IMAGE_Border attribute of the frame and the label will reflect the
79 * current gadget position.
80 * Corrected the choice of background color for erasing the area of a gadget
81 * in the border without any parents with frames.
83 * Revision 41.10.2.8 1998/12/07 14:46:15 mlemos
84 * Ensured that any previously opened font is closed when setting BT_TextAttr.
86 * Revision 41.10.2.7 1998/12/07 03:36:59 mlemos
87 * Fixed potential text font leak.
89 * Revision 41.10.2.6 1998/12/07 03:06:54 mlemos
90 * Replaced OpenFont and CloseFont calls by the respective BGUI debug macros.
92 * Revision 41.10.2.5 1998/11/13 16:44:18 mlemos
93 * Fixed missing Rastport assignment in GM_RENDER that was preventing view
94 * class to work.
96 * Revision 41.10.2.4 1998/07/05 19:34:11 mlemos
97 * Made calls to AllocBaseInfo in BaseClassDragActive and BaseClassDragUpdate
98 * ensure that the rastport is properly obtained.
100 * Revision 41.10.2.3 1998/03/01 17:26:15 mlemos
101 * Fixed BaseInfo memory leak.
103 * Revision 41.10.2.2 1998/03/01 15:36:46 mlemos
104 * Removed tracing debugging statements.
106 * Revision 41.10.2.1 1998/03/01 15:33:31 mlemos
107 * Added support to track BaseInfo memory leaks.
109 * Revision 41.10 1998/02/25 21:11:33 mlemos
110 * Bumping to 41.10
112 * Revision 1.1 1998/02/25 17:07:27 mlemos
113 * Ian sources
118 #define WW(x)
120 /* Get the prototype for kprintf() */
122 #ifdef __AROS__
123 #include <clib/arossupport_protos.h>
124 #else
125 #include <clib/debug_protos.h>
126 #endif
128 /// Class definitions.
130 #include "include/classdefs.h"
132 #define bd_Flags bd_BC.bc_Flags /* See below. */
133 #define bd_OuterBox bd_BC.bc_OuterBox /* Domain of object. */
134 #define bd_InnerBox bd_BC.bc_InnerBox /* Internal area. */
135 #define bd_HitBox bd_BC.bc_HitBox /* Object hitbox. */
136 #define bd_Extentions bd_BC.bc_Extensions /* Label extensions. */
137 #define bd_Frame bd_BC.bc_Frame /* Frame for this object. */
138 #define bd_Label bd_BC.bc_Label /* Label for this object. */
139 #define bd_Parent bd_BC.bc_Window /* Parent window object. */
140 #define bd_View bd_BC.bc_View /* Parent view object. */
141 #define bd_RPort bd_BC.bc_RPort /* RastPort that is rendered to. */
142 #define bd_TextAttr bd_BC.bc_TextAttr /* Font to use. */
143 #define bd_TextFont bd_BC.bc_TextFont /* Font to use (opened). */
144 #define bd_Group bd_BC.bc_Group
145 #define bd_Window bd_BC.bc_Window
146 #define bd_Member bd_BC.bc_GroupNode /* Associated group member data. */
149 * Object instance data.
151 typedef struct bd_ {
152 BC bd_BC; /* Shared data. */
153 struct Hook *bd_HelpHook; /* Hook for help function. */
154 UBYTE *bd_HelpFile; /* File name for help. */
155 UBYTE *bd_HelpNode; /* Node name for AmigaGuide file. */
156 ULONG bd_HelpLine; /* Line number in help file. */
157 UBYTE *bd_HelpText; /* Text for requester help. */
158 LONG bd_HelpTextID; /* Text for requester help. */
159 UBYTE *bd_ToolTip; /* ToolTip text. */
160 LONG bd_ToolTipID; /* ToolTip text ID. */
161 struct RastPort *bd_PreBuffer; /* Render beforehand for later use. */
162 BMO *bd_BMO; /* Drag bitmap information. */
163 UWORD bd_Thresh; /* Drag Threshold. */
164 UWORD bd_DragQual; /* Drag qualifier. */
165 struct Window *bd_DragWindow; /* Window of drag bitmap. */
166 UWORD bd_MouseAct; /* Mouse button activation. */
167 UWORD bd_Qual; /* Input qualifier. */
168 UBYTE *bd_Key, bd_RawKey; /* Key equivalent. */
169 WORD bd_LeftOffset; /* Left offset. */
170 WORD bd_RightOffset; /* Right offset. */
171 WORD bd_TopOffset; /* Top offset. */
172 WORD bd_BottomOffset; /* Bottom offset. */
173 } BD;
175 #define BDF_DRAGGABLE (1 << 0) /* The object can be dragged. */
176 #define BDF_DROPPABLE (1 << 1) /* The object can be dropped on. */
177 #define BDF_LABEL_CLICK (1 << 2) /* Count label-clicks as a hit. */
178 #define BDF_REPORT_ID (1 << 3) /* Report ID if RMB/MMB */
179 #define BDF_NORECESSED (1 << 4) /* Dont recess frame when selected. */
180 #define BDF_ISACTIVE (1 << 5) /* Object active? */
181 #define BDF_MOVING (1 << 6) /* We're moving... */
182 #define BDF_MOVE_DROPBOX (1 << 10) /* Standard moving dropbox */
183 #define BDF_BUFFER (1 << 11) /* Buffer this object? */
184 #define BDF_INHIBITED (1 << 12) /* Located on a invisible page. */
185 #define BDF_GOT_LABEL_EXT (1 << 13) /* Got label extentions. */
186 #define BDF_FIXED_FONT (1 << 14) /* Font set during create. */
187 #define BDF_CACHE_NOTIFY (1 << 15) /* Notify upon window opening. */
191 /// CalcDimensions
193 makeproto ULONG CalcDimensions(Class *cl, Object *obj, struct bmDimensions *bmd, UWORD mx, UWORD my)
195 ULONG rc;
197 if ((rc = AsmDoSuperMethodA(cl, obj, (Msg)bmd)))
199 bmd->bmd_Extent->be_Min.Width += mx;
200 bmd->bmd_Extent->be_Min.Height += my;
202 bmd->bmd_Extent->be_Nom.Width += mx;
203 bmd->bmd_Extent->be_Nom.Height += my;
205 return rc;
209 #ifdef __AROS__
210 makearosproto
211 AROS_LH3(VOID, BGUI_PostRender,
212 AROS_LHA(Class *, cl, A0),
213 AROS_LHA(Object *, obj, A2),
214 AROS_LHA(struct gpRender *, gpr, A1),
215 struct Library *, BGUIBase, 23, BGUI)
216 #else
217 makeproto SAVEDS ASM VOID BGUI_PostRender(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct gpRender *gpr)
218 #endif
220 AROS_LIBFUNC_INIT
222 AROS_LIBFUNC_EXIT
225 /// RM_REFRESH
227 * Refresh after a set.
229 METHOD(BaseClassRefresh, struct rmRefresh *, rr)
231 ULONG rc = rr->rr_Flags;
233 if (rc & (RAF_RESIZE|RAF_REDRAW))
235 DoRenderMethod(obj, (struct GadgetInfo *)rr->rr_Context, GREDRAW_REDRAW);
237 rc &= ~(RAF_RESIZE|RAF_REDRAW);
239 return rc;
241 METHOD_END
243 /// OM_NEW
245 * Create a shiny new object.
247 METHOD(BaseClassNew, struct opSet *, ops)
249 BD *bd;
250 IPTR rc;
251 struct TagItem *tags = ops->ops_AttrList;
254 * We let the superclass setup an object
255 * for us.
257 if ((rc = NewSuperObject(cl, obj, tags)))
260 * Get the instance data.
262 bd = INST_DATA(cl, rc);
265 * Try to create a label
266 * and a frame.
268 bd->bd_DragQual = (UWORD)~0;
269 bd->bd_RawKey = (UBYTE)~0;
270 bd->bd_Qual = (UWORD)~0;
271 bd->bd_Thresh = 3;
273 AsmCoerceMethod(cl, (Object *)rc, RM_SETM, ops->ops_AttrList, RAF_INITIAL);
275 return rc;
277 METHOD_END
279 /// RM_GET
281 * Get an attribute.
283 METHOD(BaseClassGet, struct rmAttr *, ra)
285 ULONG rc;
287 rc = BGUI_GetAttrChart(cl, obj, ra);
289 return rc;
291 METHOD_END
293 /// RM_GETCUSTOM
295 * Get custom attributes.
297 METHOD(BaseClassGetCustom, struct rmAttr *, ra)
299 BD *bd = (BD *)INST_DATA(cl, obj);
300 ULONG attr = ra->ra_Attr->ti_Tag;
301 ULONG *store = (ULONG *)ra->ra_Attr->ti_Data;
303 switch (attr)
305 case BT_ToolTip:
306 if (bd->bd_Flags & BDF_ISACTIVE)
307 STORE NULL;
308 break;
310 return 1;
312 METHOD_END
314 /// RM_GETATTRFLAGS
316 * Get the flags of an attribute.
318 METHOD(BaseClassGetAttrFlags, struct rmAttr *, ra)
320 static struct TagItem chart[] =
322 { BT_LabelClick, CHART_FLAG(bd_, bd_Flags, BDF_LABEL_CLICK), },
323 { BT_NoRecessed, CHART_FLAG(bd_, bd_Flags, BDF_NORECESSED), },
324 { BT_DragObject, CHART_FLAG(bd_, bd_Flags, BDF_DRAGGABLE), },
325 { BT_DropObject, CHART_FLAG(bd_, bd_Flags, BDF_DROPPABLE), },
326 { BT_Buffer, CHART_FLAG(bd_, bd_Flags, BDF_BUFFER), },
327 { BT_IsActive, CHART_FLAG(bd_, bd_Flags, BDF_ISACTIVE), },
328 { BT_ReportID, CHART_FLAG(bd_, bd_Flags, BDF_REPORT_ID), },
329 { BT_Inhibit, CHART_FLAG(bd_, bd_Flags, BDF_INHIBITED) | RAF_NOSET, },
331 { BT_LabelObject, CHART_ATTR(bd_, bd_Label) | RAF_CUSTOM | RAF_NOSET, },
332 { BT_FrameObject, CHART_ATTR(bd_, bd_Frame) | RAF_CUSTOM | RAF_NOSET, },
333 { BT_TextAttr, CHART_ATTR(bd_, bd_TextAttr) | RAF_CUSTOM | RAF_NOSET, },
334 { BT_TextFont, CHART_ATTR(bd_, bd_TextFont) | RAF_NOSET, },
335 { BT_HelpHook, CHART_ATTR(bd_, bd_HelpHook), },
336 { BT_HelpFile, CHART_ATTR(bd_, bd_HelpFile), },
337 { BT_HelpNode, CHART_ATTR(bd_, bd_HelpNode), },
338 { BT_HelpLine, CHART_ATTR(bd_, bd_HelpLine), },
339 { BT_HelpText, CHART_ATTR(bd_, bd_HelpText), },
340 { BT_HelpTextID, CHART_ATTR(bd_, bd_HelpTextID), },
341 { BT_ToolTip, CHART_ATTR(bd_, bd_ToolTip) | RAF_CUSTOM, },
342 { BT_ToolTipID, CHART_ATTR(bd_, bd_ToolTipID), },
343 { BT_DragThreshold, CHART_ATTR(bd_, bd_Thresh), },
344 { BT_DragQualifier, CHART_ATTR(bd_, bd_DragQual), },
345 { BT_MouseActivation, CHART_ATTR(bd_, bd_MouseAct), },
346 { BT_Key, CHART_ATTR(bd_, bd_Key) | RAF_CUSTOM, },
347 { BT_RawKey, CHART_ATTR(bd_, bd_RawKey) | RAF_CUSTOM, },
348 { BT_Qualifier, CHART_ATTR(bd_, bd_Qual), },
349 { BT_HitBox, CHART_ATTR(bd_, bd_HitBox) | RAF_ADDRESS, },
350 { BT_OuterBox, CHART_ATTR(bd_, bd_OuterBox) | RAF_ADDRESS, },
351 { BT_InnerBox, CHART_ATTR(bd_, bd_InnerBox) | RAF_ADDRESS, },
352 { BT_LeftOffset, CHART_ATTR(bd_, bd_LeftOffset) | RAF_SIGNED, },
353 { BT_RightOffset, CHART_ATTR(bd_, bd_RightOffset) | RAF_SIGNED, },
354 { BT_TopOffset, CHART_ATTR(bd_, bd_TopOffset) | RAF_SIGNED, },
355 { BT_BottomOffset, CHART_ATTR(bd_, bd_BottomOffset) | RAF_SIGNED, },
357 { BT_ParentWindow, CHART_ATTR(bd_, bd_Window) | RAF_CUSTOM, },
358 { BT_ParentView, CHART_ATTR(bd_, bd_View), },
359 { BT_ParentGroup, CHART_ATTR(bd_, bd_Group) | RAF_CUSTOM, },
360 { BT_GroupMember, CHART_ATTR(bd_, bd_Member), },
362 { GA_ID, RAF_SUPER | RAF_NOUPDATE | RAF_NOP, },
364 { TAG_DONE },
367 return GetTagData(ra->ra_Attr->ti_Tag, 0, chart);
369 METHOD_END
371 /// RM_SET
373 * Set standard attributes.
375 METHOD(BaseClassSet, struct rmAttr *, ra)
377 BD *bd;
378 ULONG attr, data, rc;
380 rc = BGUI_SetAttrChart(cl, obj, ra);
382 if (!(rc & RAF_UNDERSTOOD))
384 bd = (BD *)INST_DATA(cl, obj);
385 attr = ra->ra_Attr->ti_Tag;
386 data = ra->ra_Attr->ti_Data;
388 if (!bd->bd_Label && LAB_TAG(attr))
390 bd->bd_Label = BGUI_NewObject(BGUI_LABEL_IMAGE, IMAGE_InBorder, GADGET(obj)->Activation & BORDERMASK, TAG_DONE);
391 rc = RAF_RESIZE;
393 if (bd->bd_Label) rc |= AsmDoMethodA(bd->bd_Label, (Msg)ra);
395 if (rc & RAF_UNDERSTOOD) return rc;
397 if (LGO_TAG(attr))
399 rc = RAF_UNDERSTOOD|RAF_RESIZE;
401 if (bd->bd_Member) DoSetMethodNG(bd->bd_Member, attr, data, TAG_DONE);
403 else if (FRM_TAG(attr))
405 rc = RAF_UNDERSTOOD|RAF_REDRAW;
407 if (attr == FRM_Type) rc |= RAF_RESIZE;
409 if (bd->bd_Frame)
411 DoSetMethodNG(bd->bd_Frame, attr, data, TAG_DONE);
413 else
415 if (attr != FRM_ThinFrame)
417 bd->bd_Frame = BGUI_NewObject(BGUI_FRAME_IMAGE, attr, data, IMAGE_InBorder,
418 GADGET(obj)->Activation & BORDERMASK, TAG_DONE);
419 rc |= RAF_RESIZE;
424 else
426 switch(ra->ra_Attr->ti_Tag)
428 case GA_TopBorder:
429 case GA_BottomBorder:
430 case GA_LeftBorder:
431 case GA_RightBorder:
432 bd = (BD *)INST_DATA(cl, obj);
433 if (bd->bd_Frame)
435 DoSetMethodNG(bd->bd_Frame, IMAGE_InBorder, GADGET(obj)->Activation & BORDERMASK, TAG_END);
436 rc |= RAF_REDRAW;
438 if (bd->bd_Label)
440 DoSetMethodNG(bd->bd_Label, IMAGE_InBorder, GADGET(obj)->Activation & BORDERMASK, TAG_END);
441 rc |= RAF_REDRAW;
443 break;
446 return rc;
448 METHOD_END
450 /// RM_SETCUSTOM
452 * Set custom attributes.
454 METHOD(BaseClassSetCustom, struct rmAttr *, ra)
456 BD *bd = (BD *)INST_DATA(cl, obj);
457 struct TextAttr *ta;
458 struct TextFont *tf;
459 Tag attr = ra->ra_Attr->ti_Tag;
460 IPTR data = ra->ra_Attr->ti_Data;
462 switch (attr)
464 case BT_LabelObject:
465 if (bd->bd_Label) DisposeObject(bd->bd_Label);
466 if ((bd->bd_Label = (Object *)data))
468 bd->bd_Flags &= ~BDF_GOT_LABEL_EXT;
469 DoSetMethodNG(bd->bd_Label, IMAGE_InBorder, GADGET(obj)->Activation & BORDERMASK, TAG_END);
471 break;
473 case BT_FrameObject:
474 if (bd->bd_Frame) DisposeObject(bd->bd_Frame);
475 if ((bd->bd_Frame = (Object *)data))
477 DoSetMethodNG(bd->bd_Frame, IMAGE_InBorder, GADGET(obj)->Activation & BORDERMASK, TAG_END);
479 break;
481 case BT_TextAttr:
483 * Only change the font if it was not defined yet and if it was
484 * not set at create time.
486 if (bd->bd_Flags & BDF_FIXED_FONT)
487 break;
490 * We only change the font when it opens ok.
492 if ((ta = (struct TextAttr *)data))
494 if ((tf = BGUI_OpenFont(ta)))
496 bd->bd_TextAttr = ta;
497 if(bd->bd_TextFont)
498 BGUI_CloseFont(bd->bd_TextFont);
499 bd->bd_TextFont = tf;
500 bd->bd_Flags &= ~BDF_GOT_LABEL_EXT;
502 if (ra->ra_Flags & RAF_INITIAL) bd->bd_Flags |= BDF_FIXED_FONT;
505 * Change the font settings on the images.
507 if (bd->bd_Label) DoSetMethodNG(bd->bd_Label, IMAGE_TextFont, tf, TAG_END);
508 if (bd->bd_Frame) DoSetMethodNG(bd->bd_Frame, IMAGE_TextFont, tf, TAG_END);
511 break;
513 case BT_Key:
514 bd->bd_RawKey = (UBYTE)~0;
515 break;
517 case BT_RawKey:
518 bd->bd_Key = NULL;
519 break;
521 case BT_ParentGroup:
522 if (bd->bd_Frame) DoSetMethodNG(bd->bd_Frame, BT_ParentGroup, data, TAG_DONE);
523 break;
525 case BT_ParentWindow:
526 if (bd->bd_Flags & BDF_CACHE_NOTIFY)
528 //DoNotifyMethod(obj, ops->ops_GInfo, 0, GA_ID, GADGET(obj)->GadgetID, TAG_END);
529 bd->bd_Flags &= ~BDF_CACHE_NOTIFY;
531 break;
533 return 1;
535 METHOD_END
537 /// OM_NOTIFY
538 METHOD(BaseClassNotify, struct opUpdate *, opu)
540 BD *bd = INST_DATA(cl, obj);
542 AsmDoSuperMethodA(cl, obj, (Msg)opu);
544 if (!opu->opu_GInfo || !opu->opu_GInfo->gi_Window)
546 bd->bd_Flags |= BDF_CACHE_NOTIFY;
549 return 1;
551 METHOD_END
553 /// OM_DISPOSE
555 * They do not need us anymore.
557 METHOD(BaseClassDispose, Msg, msg)
559 BD *bd = (BD *)INST_DATA(cl, obj);
562 * Delete frame and label.
564 if (bd->bd_Frame)
565 DisposeObject(bd->bd_Frame);
566 if (bd->bd_Label)
567 DisposeObject(bd->bd_Label);
568 if (bd->bd_PreBuffer)
569 BGUI_FreeRPortBitMap(bd->bd_PreBuffer);
570 if (bd->bd_TextFont)
571 BGUI_CloseFont(bd->bd_TextFont);
574 * Let the superclass dispose
575 * of us.
577 return AsmDoSuperMethodA(cl, obj, msg);
579 METHOD_END
581 /// GM_HITTEST
583 * Are we hit?
585 METHOD(BaseClassHitTest, struct gpHitTest *, gpht)
587 BD *bd = INST_DATA(cl, obj);
588 struct IBox *ibox = (bd->bd_Flags & BDF_LABEL_CLICK) ? &bd->bd_OuterBox : &bd->bd_HitBox;
591 * Get absolute click position.
593 WORD x = GADGET(obj)->LeftEdge + gpht->gpht_Mouse.X;
594 WORD y = GADGET(obj)->TopEdge + gpht->gpht_Mouse.Y;
596 return (ULONG)(PointInBox(ibox, x, y) ? GMR_GADGETHIT : 0);
598 METHOD_END
600 /// GM_HELPTEST
602 * Are we hit?
604 METHOD(BaseClassHelpTest, struct gpHitTest *, gpht)
606 BD *bd = INST_DATA(cl, obj);
607 struct IBox *ibox = &bd->bd_OuterBox;
610 * Get absolute click position.
612 WORD x = GADGET(obj)->LeftEdge + gpht->gpht_Mouse.X;
613 WORD y = GADGET(obj)->TopEdge + gpht->gpht_Mouse.Y;
615 return (ULONG)(PointInBox(ibox, x, y) ? GMR_HELPHIT : GMR_NOHELPHIT);
617 METHOD_END
619 /// GM_RENDER
621 * Render the object.
623 METHOD(BaseClassRenderX, struct gpRender *, gpr)
625 BD *bd = INST_DATA(cl, obj);
626 struct RastPort *rp = NULL;
627 struct BaseInfo *bi;
628 int x, y, from_x, from_y, to_x, to_y;
629 struct IBox *box, to;
630 ULONG rc = 0;
631 IPTR gok = TRUE;
634 * Are we inhibited? If so we do not render ourselves.
636 if (bd->bd_Window)
637 Get_Attr(bd->bd_Window, WINDOW_GadgetOK, &gok);
639 if ((bd->bd_Flags & BDF_INHIBITED) || (!gok))
640 return 0;
642 if (bd->bd_Flags & BDF_BUFFER)
645 * Use buffer?
647 if (bd->bd_Window)
649 Get_Attr(bd->bd_Window, WINDOW_BufferRP, (IPTR *)&rp);
653 if (!rp) rp = gpr->gpr_RPort;
656 * Handle virtual groups.
658 if (bd->bd_View)
660 Get_Attr(bd->bd_View, VIEW_ObjectBuffer, (IPTR *)&rp);
663 if ((bd->bd_RPort = rp))
665 #ifdef DEBUG_BGUI
666 if (bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_GadgetInfo, gpr->gpr_GInfo, BI_RastPort, rp, TAG_DONE))
667 #else
668 if ((bi = AllocBaseInfo(BI_GadgetInfo, gpr->gpr_GInfo, BI_RastPort, rp, TAG_DONE)))
669 #endif
671 bi->bi_Window = bd->bd_Parent;
674 * Layout the object.
676 if ((rc = AsmDoMethod(obj, BASE_LAYOUT, bi, GADGETBOX(obj), 0)))
679 * Remove layer from buffer if not needed.
681 //if (bd->bd_Parent) AsmDoMethod(bd->bd_Parent, WM_CLIP, NULL, CLIPACTION_NONE);
683 rc = AsmDoMethod(obj, BASE_RENDER, bi, gpr->gpr_Redraw);
685 FreeBaseInfo(bi);
689 if (rc)
691 if (bd->bd_View)
693 if (rp != gpr->gpr_RPort)
695 IPTR tmp;
696 Get_Attr(bd->bd_View, VIEW_AbsoluteX, &tmp);
697 x = (int)tmp;
698 Get_Attr(bd->bd_View, VIEW_AbsoluteY, &tmp);
699 y = (int)tmp;
701 from_x = bd->bd_OuterBox.Left;
702 from_y = bd->bd_OuterBox.Top;
704 to.Left = to_x = x + from_x;
705 to.Top = to_y = y + from_y;
706 to.Width = bd->bd_OuterBox.Width;
707 to.Height = bd->bd_OuterBox.Height;
710 * Convert from ibox to rectangle.
712 to.Width += to.Left - 1;
713 to.Height += to.Top - 1;
715 AsmDoMethod(bd->bd_View, VIEW_CLIP, &to, TRUE);
718 * Convert from rectangle to ibox.
720 to.Width -= to.Left - 1;
721 to.Height -= to.Top - 1;
724 * Get clipping offsets.
726 from_x += to.Left - to_x;
727 from_y += to.Top - to_y;
730 * Copy the object to the window.
732 if(to.Width>0
733 && to.Height>0)
734 ClipBlit(rp, from_x, from_y, gpr->gpr_RPort, to.Left, to.Top, to.Width, to.Height, 0xC0);
736 //if (BASE_DATA(bd->bd_View)->bc_View)
738 // DoSetMethodNG(BASE_DATA(bd->bd_View)->bc_View, VIEW_ObjectBuffer, NULL, TAG_DONE);
739 //};
742 else
744 if (rp && (rp != gpr->gpr_RPort))
747 * Remove layer from buffer.
749 if (bd->bd_Window)
751 AsmDoMethod(bd->bd_Window, WM_CLIP, NULL, CLIPACTION_NONE);
754 box = (gpr->gpr_Redraw == GREDRAW_REDRAW) ? &bd->bd_OuterBox : &bd->bd_InnerBox;
757 * Blast the GUI to the window.
759 if(box->Width>0
760 && box->Height>0)
761 ClipBlit(rp, box->Left, box->Top, gpr->gpr_RPort, box->Left, box->Top, box->Width, box->Height, 0xC0);
765 return rc;
767 METHOD_END
769 /// BASE_LAYOUT
771 * Render the baseclass imagery.
773 METHOD(BaseClassLayout, struct bmLayout *, bml)
775 BD *bd = INST_DATA(cl, obj);
776 int dw, dh;
777 UWORD gflags = GADGET(obj)->Flags;
778 struct BaseInfo *bi = bml->bml_BInfo;
781 * Get gadget bounds.
783 bd->bd_OuterBox = *(bml->bml_Bounds);
786 * Don't bother with this if we are completely absolute.
788 if (gflags & (GFLG_RELRIGHT|GFLG_RELBOTTOM|GFLG_RELWIDTH|GFLG_RELHEIGHT))
791 * Get domain width and height.
793 dw = bi->bi_Domain.Width;
794 dh = bi->bi_Domain.Height;
797 * Adjust for any relativity.
799 if (gflags & GFLG_RELRIGHT) bd->bd_OuterBox.Left += dw - 1;
800 if (gflags & GFLG_RELBOTTOM) bd->bd_OuterBox.Top += dh - 1;
801 if (gflags & GFLG_RELWIDTH) bd->bd_OuterBox.Width += dw;
802 if (gflags & GFLG_RELHEIGHT) bd->bd_OuterBox.Height += dh;
805 bd->bd_HitBox = bd->bd_OuterBox;
808 * Do we have a label?
810 if (bd->bd_Label && bi->bi_RPort)
813 * If the extentions are already known we
814 * we do not bother getting them again.
816 if (!(bd->bd_Flags & BDF_GOT_LABEL_EXT))
819 * Setup label extentions.
821 DoExtentMethod(bd->bd_Label, bi->bi_RPort, &bd->bd_Extentions, NULL, NULL, EXTF_MAXIMUM);
824 * We got the extentions.
826 bd->bd_Flags |= BDF_GOT_LABEL_EXT;
830 * Adjust hitbox accordingly.
832 bd->bd_HitBox.Left += -bd->bd_Extentions.Left;
833 bd->bd_HitBox.Top += -bd->bd_Extentions.Top;
834 bd->bd_HitBox.Width -= -bd->bd_Extentions.Left + bd->bd_Extentions.Width;
835 bd->bd_HitBox.Height -= -bd->bd_Extentions.Top + bd->bd_Extentions.Height;
838 * Setup label bounds.
840 SetImageBounds(bd->bd_Label, &bd->bd_HitBox);
843 bd->bd_InnerBox = bd->bd_HitBox;
845 bd->bd_InnerBox.Left += bd->bd_LeftOffset;
846 bd->bd_InnerBox.Top += bd->bd_TopOffset;
847 bd->bd_InnerBox.Width -= bd->bd_LeftOffset + bd->bd_RightOffset;
848 bd->bd_InnerBox.Height -= bd->bd_TopOffset + bd->bd_BottomOffset;
851 * Setup frame bounds.
853 if (bd->bd_Frame)
855 AsmDoMethod(bd->bd_Frame, FRAMEM_SETUPBOUNDS, &bd->bd_HitBox, &bd->bd_InnerBox);
857 return 1;
859 METHOD_END
861 /// BASE_RENDER
863 * Render the baseclass imagery.
865 METHOD(BaseClassRender, struct bmRender *, bmr)
867 BD *bd = INST_DATA(cl, obj), *bd2;
868 struct BaseInfo *bi = bmr->bmr_BInfo;
869 ULONG state;
870 Object *parent, *frame;
871 struct Rectangle rect;
874 * Complete redraw?
876 if (bmr->bmr_Flags == GREDRAW_REDRAW)
879 * What state do we render?
881 state = GadgetState(bi, obj, bd->bd_Flags & BDF_NORECESSED);
883 if (bd->bd_Frame)
885 BDrawImageState(bi, bd->bd_Frame, 0, 0, state);
887 else
889 bd2 = bd;
891 while ((parent = bd2->bd_Group))
893 bd2 = INST_DATA(cl, parent);
894 if ((frame = bd2->bd_Frame))
897 * Use the frame for our backfill.
899 rect.MinX = bd->bd_InnerBox.Left;
900 rect.MinY = bd->bd_InnerBox.Top;
901 rect.MaxX = bd->bd_InnerBox.Width + rect.MinX - 1;
902 rect.MaxY = bd->bd_InnerBox.Height + rect.MinY - 1;
904 AsmDoMethod(frame, FRAMEM_BACKFILL, bi, &rect, state);
905 break;
909 if (!parent)
911 UWORD apen;
914 * If we do not have a frame, we need to clear the area ourselves.
916 switch (state)
918 case IDS_SELECTED:
919 apen = FILLPEN;
920 break;
921 case IDS_INACTIVESELECTED:
922 case IDS_INACTIVENORMAL:
923 apen = BACKGROUNDPEN;
924 break;
925 default:
927 * And BACKGROUNDPEN for normal frames.
929 apen = (GADGET(obj)->Activation & BORDERMASK) ? FILLPEN : BACKGROUNDPEN;
930 break;
932 BSetDPenA(bi, apen);
933 BSetDrMd(bi, JAM1);
934 BClearAfPt(bi);
935 BBoxFillA(bi, &bd->bd_InnerBox);
940 * Render the label.
942 if (bd->bd_Label) BDrawImageState(bi, bd->bd_Label, 0, 0, state);
945 if (bd->bd_Frame)
947 rect.MinX = bd->bd_InnerBox.Left + 2;
948 rect.MinY = bd->bd_InnerBox.Top + 2;
949 rect.MaxX = bd->bd_InnerBox.Width + rect.MinX - 5;
950 rect.MaxY = bd->bd_InnerBox.Height + rect.MinY - 5;
952 BSetDrPt(bi, 0xAAAA);
953 BSetDrMd(bi, JAM1);
954 BSetDPenA(bi, SHADOWPEN);
955 Move(bi->bi_RPort, rect.MaxX, rect.MinY);
956 Draw(bi->bi_RPort, rect.MinX, rect.MinY);
957 Draw(bi->bi_RPort, rect.MinX, rect.MaxY);
958 Draw(bi->bi_RPort, rect.MaxX, rect.MaxY);
959 Draw(bi->bi_RPort, rect.MaxX, rect.MinY);
963 return 1;
965 METHOD_END
967 /// BASE_HELP
969 * Show help.
971 METHOD(BaseClassHelp, struct bmShowHelp *, bsh)
973 BD *bd = INST_DATA(cl, obj);
974 struct NewAmigaGuide nag = { };
975 ULONG rc = BMHELP_NOT_ME;
976 struct gpHitTest gph;
979 * We only show help when
980 * necessary or possible.
982 if (bd->bd_HelpFile || bd->bd_HelpText || bd->bd_HelpHook)
984 #if 0
985 WORD l, t, w, h, dw, dh;
987 * Setup the gadget bounds.
989 l = GADGET(obj)->LeftEdge;
990 t = GADGET(obj)->TopEdge;
991 w = GADGET(obj)->Width;
992 h = GADGET(obj)->Height;
995 * When one of the GFLGREL... flags
996 * is set adjust the appropiate value.
998 if (!(GADGET(obj)->GadgetType & GTYP_REQGADGET))
1000 dw = bsh->bsh_Window->Width;
1001 dh = bsh->bsh_Window->Height;
1002 } else {
1003 dw = bsh->bsh_Requester->Width;
1004 dh = bsh->bsh_Requester->Height;
1008 * Adjust coords.
1010 if (GADGET(obj)->Flags & GFLG_RELRIGHT ) l += dw - 1;
1011 if (GADGET(obj)->Flags & GFLG_RELBOTTOM) t += dh - 1;
1012 if (GADGET(obj)->Flags & GFLG_RELWIDTH ) w += dw;
1013 if (GADGET(obj)->Flags & GFLG_RELHEIGHT) h += dh;
1016 * Mouse pointer in the gadget?
1018 if (bsh->bsh_Mouse.X >= l && bsh->bsh_Mouse.X < (l + w) &&
1019 bsh->bsh_Mouse.Y >= t && bsh->bsh_Mouse.Y < (t + h))
1020 #endif
1022 gph.MethodID = GM_HELPTEST;
1023 gph.gpht_Mouse.X = bsh->bsh_Mouse.X - GADGET(obj)->LeftEdge;
1024 gph.gpht_Mouse.Y = bsh->bsh_Mouse.Y - GADGET(obj)->TopEdge;
1026 if (BGUI_DoGadgetMethodA(obj, bsh->bsh_Window, bsh->bsh_Requester, (Msg)&gph) == GMR_HELPHIT)
1028 if (bd->bd_HelpHook)
1029 { /*
1030 * Help Hook ?
1032 rc = BGUI_CallHookPkt(bd->bd_HelpHook, obj, NULL);
1034 else if (bd->bd_HelpText)
1037 * Help-requester?
1039 ShowHelpReq(bsh->bsh_Window, bd->bd_HelpText);
1040 rc = BMHELP_OK;
1042 else if (bd->bd_HelpFile)
1045 * Initialize the NewAmigaGuide structure.
1047 nag.nag_Name = (STRPTR)bd->bd_HelpFile;
1048 nag.nag_Node = (STRPTR)bd->bd_HelpNode;
1049 nag.nag_Line = bd->bd_HelpLine;
1050 nag.nag_Screen = bsh->bsh_Window->WScreen;
1053 * Try to open it.
1055 if (!DisplayAGuideInfo(&nag, TAG_END)) rc = BMHELP_FAILURE;
1056 else rc = BMHELP_OK;
1060 return rc;
1062 METHOD_END
1064 /// BASE_DIMENSIONS
1066 * They want to know our minimum dimensions.
1068 METHOD(BaseClassDimensions, struct bmDimensions *, bmd)
1070 BD *bd = INST_DATA(cl, obj);
1072 bmd->bmd_Extent->be_Min.Width = bd->bd_LeftOffset + bd->bd_RightOffset;
1073 bmd->bmd_Extent->be_Min.Height = bd->bd_TopOffset + bd->bd_BottomOffset;
1075 bmd->bmd_Extent->be_Nom = bmd->bmd_Extent->be_Min;
1077 bmd->bmd_Extent->be_Max.Width = bmd->bmd_Extent->be_Max.Height = 0xFFFF;
1080 * Get frame offset.
1082 if (bd->bd_Frame) AsmDoMethodA(bd->bd_Frame, (Msg)bmd);
1084 return 1;
1086 METHOD_END
1088 /// GRM_DIMENSIONS
1090 * They want to know our minimum dimensions.
1092 METHOD(BaseClassDimensionsX, struct grmDimensions *, dim)
1094 BD *bd = INST_DATA(cl, obj);
1095 struct BaseInfo *bi;
1096 struct bguiExtent be;
1097 ULONG rc = 0;
1099 #ifdef DEBUG_BGUI
1100 if ((bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_GadgetInfo, dim->grmd_GInfo, BI_RastPort, dim->grmd_RPort, TAG_DONE)))
1101 #else
1102 if ((bi = AllocBaseInfo(BI_GadgetInfo, dim->grmd_GInfo, BI_RastPort, dim->grmd_RPort, TAG_DONE)))
1103 #endif
1105 if ((rc = AsmDoMethod(obj, BASE_DIMENSIONS, bi, &be, 0)))
1108 * Compute minimum width/height according to the label and its position.
1110 if (bd->bd_Label) AsmDoMethod(bd->bd_Label, BASE_DIMENSIONS, bi, &be, 0);
1113 * Copy to grmDimensions.
1115 *(dim->grmd_MinSize.Width ) = be.be_Min.Width;
1116 *(dim->grmd_MinSize.Height) = be.be_Min.Height;
1118 if (dim->grmd_Flags & GDIMF_MAXIMUM)
1120 *(dim->grmd_MaxSize.Width ) = be.be_Max.Width;
1121 *(dim->grmd_MaxSize.Height) = be.be_Max.Height;
1124 if (dim->grmd_Flags & GDIMF_NOMINAL)
1126 *(dim->grmd_NomSize.Width ) = be.be_Nom.Width;
1127 *(dim->grmd_NomSize.Height) = be.be_Nom.Height;
1130 FreeBaseInfo(bi);
1132 return rc;
1134 METHOD_END
1136 /// BASE_RELAYOUT
1138 METHOD(BaseClassRelayout, struct bmRelayout *, bmr)
1140 BD *bd = INST_DATA(cl, obj);
1141 UWORD minw, minh, maxw = 0xFFFF, maxh = 0xFFFF;
1142 ULONG rc = 0;
1143 struct GadgetInfo *gi = bmr->bmr_GInfo;
1144 struct RastPort *rp = bmr->bmr_RPort;
1145 Object *wo = bd->bd_Window;
1147 WW(kprintf("** BaseClassRelayout\n"));
1148 if (!wo) return 0;
1149 WW(kprintf("** BaseClassRelayout. wo != 0. calling GRM_DIMENSIONS\n"));
1151 AsmDoMethod(obj, GRM_DIMENSIONS, gi, rp, &minw, &minh, GDIMF_MAXIMUM, &maxw, &maxh);
1152 WW(kprintf("** BaseClassRelayout. GRM_DIMENSIONS returned minw = %d minh = %d\n",minw,minh));
1154 if ((minw <= bd->bd_OuterBox.Width) && (minh <= bd->bd_OuterBox.Height))
1156 WW(kprintf("** BaseClassRelayout: minw and minh are <= outerbox.width/height\n"));
1157 if(!(bd->bd_Flags & BDF_INHIBITED))
1159 kprintf("** BaseClassRelayout: not inhibited. trying GM_RENDER\n");
1161 if((rp=BGUI_ObtainGIRPort(gi)))
1163 WW(kprintf("** BaseClassRelayout: doing GM_RENDER\n"));
1164 rc=AsmDoMethod(obj,GM_RENDER,gi,rp,GREDRAW_REDRAW);
1165 ReleaseGIRPort(rp);
1167 else
1168 rc=0;
1170 else
1171 rc=1;
1173 else
1175 WW(kprintf("** BaseClassRelayout: minw and minh are > outerbox.width/height\n"));
1176 if (bd->bd_Group)
1178 WW(kprintf("** BaseClassRelayout: has bd->bd_Group -> sending BASE_RELAYOUT to group"));
1179 rc = AsmDoMethodA(bd->bd_Group, (Msg)bmr);
1181 else
1183 WW(kprintf("** BaseClassRelayout: does not have bd->bd_Group sending WM_RELAYOUT\n"));
1184 rc = AsmDoMethod(wo, WM_RELAYOUT);
1187 return rc;
1189 METHOD_END
1193 /// BASE_LEFTEXT
1195 * Left extention request.
1197 METHOD(BaseClassLeftExt, struct bmLeftExt *, le)
1199 BD *bd = INST_DATA(cl, obj);
1200 UWORD dummy;
1201 struct IBox ibox;
1202 int ext;
1205 * Do we have a label?
1207 if (bd->bd_Label)
1210 * Get the left-extention of the label if we do not have it yet.
1212 if (!(bd->bd_Flags & BDF_GOT_LABEL_EXT))
1214 DoExtentMethod(bd->bd_Label, le->bmle_RPort, &ibox, &dummy, &dummy, EXTF_MAXIMUM);
1215 ext = -ibox.Left;
1217 else
1219 ext = -bd->bd_Extentions.Left;
1222 else ext = 0;
1224 *(le->bmle_Extention) = ext;
1226 return 1;
1228 METHOD_END
1230 /// WM_KEYACTIVE
1232 * No key input.
1234 METHOD(BaseClassKeyActive, struct wmKeyInput *, wmki)
1236 return WMKF_CANCEL;
1238 METHOD_END
1242 * Pack two words in a long.
1244 //#define PACKW(w1,w2) (((w1<<16)&0xFFFF0000)|(w2&0xFFFF))
1246 #ifdef __AROS__
1247 #define PACKW(w1,w2) w1,w2
1248 #else
1249 #define PACKW(w1,w2) ( (((UWORD)w1) << 16) | ((UWORD)w2) )
1250 #endif
1252 #define bd_ActRec bd_BMO->bmo_ActRec
1253 #define bd_ActWin bd_BMO->bmo_ActWin
1254 #define bd_ActPtr bd_BMO->bmo_ActPtr
1256 /// GM_GOACTIVE
1258 * Go active.
1260 METHOD(BaseClassGoActive, struct gpInput *, gpi)
1262 BD *bd = INST_DATA(cl, obj);
1265 * Are we draggable?
1267 if (bd->bd_Flags & BDF_DRAGGABLE && gpi->gpi_IEvent->ie_Qualifier & bd->bd_DragQual)
1270 * Close parent tool-tip.
1272 if (bd->bd_Parent)
1274 Forbid();
1275 AsmDoMethod(bd->bd_Parent, WM_CLOSETOOLTIP);
1276 Permit();
1280 * Let the object create a bitmap.
1282 if ((bd->bd_BMO = CreateBMO(obj, gpi->gpi_GInfo)))
1284 return GMR_MEACTIVE;
1287 return GMR_NOREUSE;
1289 METHOD_END
1291 /// BASE_DRAGGING
1293 * Handle input.
1295 METHOD(BaseClassDragging, struct gpInput *, gpi)
1297 BD *bd = INST_DATA(cl, obj);
1298 BMO *bmo = bd->bd_BMO;
1299 WORD dx, dy, nx, ny;
1300 ULONG rc = bd->bd_Flags & BDF_MOVING ? BDR_DRAGGING : BDR_NONE;
1301 struct IBox *db;
1302 struct GadgetInfo *gi = gpi->gpi_GInfo;
1305 * We only process input if we have drag-buffers.
1307 if (bmo)
1310 * When we have an active receiver we send
1311 * it an update message each timer tick.
1313 if ((bd->bd_Flags & BDF_MOVING) && (gpi->gpi_IEvent->ie_Class == IECLASS_TIMER))
1315 if (!--bmo->bmo_BMDelay)
1318 * Open window.
1320 LayerBMO(bmo);
1323 if (bd->bd_ActRec)
1326 * Send an update to the target.
1330 * Get mouse position.
1332 nx = gi->gi_Screen->MouseX;
1333 ny = gi->gi_Screen->MouseY;
1336 * Get the hitbox bounds of the
1337 * receiver.
1339 Get_Attr(bd->bd_ActRec, BT_HitBox, (IPTR *)&db);
1342 * Get mouse coords relative to the
1343 * receiver hitbox.
1345 dx = nx - (bd->bd_ActPtr->LeftEdge + db->Left);
1346 dy = ny - (bd->bd_ActPtr->TopEdge + db->Top );
1349 * Send off a drag update message
1350 * to the receiver.
1352 if (!bmo->bmo_BMWindow && bmo->bmo_BMDelay) EraseBMO(bmo);
1354 if (myDoGadgetMethod(bd->bd_ActRec, bd->bd_ActPtr, NULL, BASE_DRAGUPDATE, NULL, obj, PACKW(dx, dy)) != BUR_CONTINUE)
1357 * Deactivate target.
1359 myDoGadgetMethod(bd->bd_ActRec, bd->bd_ActPtr, NULL, BASE_DRAGINACTIVE, NULL, obj);
1360 bd->bd_ActRec = NULL;
1363 if (!bmo->bmo_BMWindow && bmo->bmo_BMDelay) MoveBMO(bmo, nx, ny);
1366 else if (gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
1368 switch (gpi->gpi_IEvent->ie_Code)
1370 case SELECTUP:
1371 case MENUDOWN:
1373 * Were we moved?
1375 if (bd->bd_Flags & BDF_MOVING)
1378 * Hide object.
1380 EraseBMO(bmo);
1383 * "Drop" us on the target.
1385 if (bd->bd_ActRec && gpi->gpi_IEvent->ie_Code == SELECTUP)
1386 myDoGadgetMethod(bd->bd_ActRec, gi->gi_Window, gi->gi_Requester, BASE_DROPPED, NULL, obj, bd->bd_ActPtr, NULL);
1389 * Deactivate the target.
1391 if (bd->bd_ActRec)
1392 myDoGadgetMethod(bd->bd_ActRec, bd->bd_ActPtr, NULL, BASE_DRAGINACTIVE, NULL, obj);
1395 * Selecting the menu button or when there is no active drop object means we return
1396 * BDR_CANCEL. Otherwise we return BDR_DROP.
1398 if ((gpi->gpi_IEvent->ie_Code == MENUDOWN) || ! bd->bd_ActRec)
1399 rc = BDR_CANCEL;
1400 else
1401 rc = BDR_DROP;
1402 } else
1403 rc = BDR_NONE;
1406 * Unlock the window.
1408 if (bd->bd_ActWin) AsmDoMethod(bd->bd_ActWin, WM_UNLOCK);
1409 break;
1411 default:
1413 * Pick up mouse coordinates.
1415 nx = gi->gi_Screen->MouseX;
1416 ny = gi->gi_Screen->MouseY;
1418 bmo->bmo_BMDelay = 5;
1421 * Are we moving yet?
1423 if (bd->bd_Flags & BDF_MOVING)
1426 * Move the object to the new position.
1428 MoveBMO(bmo, nx, ny);
1431 * Were still dragging along...
1433 rc = BDR_DRAGGING;
1435 else
1437 dx = nx - bmo->bmo_CX;
1438 dy = ny - bmo->bmo_CY;
1439 if (((dx * dx) + (dy * dy)) >= (bd->bd_Thresh * bd->bd_Thresh))
1442 * They have passed the Threshold.
1444 bd->bd_Flags |= BDF_MOVING;
1447 * Tell'm to prepare for moving.
1449 rc = BDR_DRAGPREPARE;
1452 break;
1456 return rc;
1458 METHOD_END
1460 /// GM_GOINACTIVE
1462 METHOD(BaseClassGoInactive, struct gpGoInactive *, gpgi)
1464 BD *bd = INST_DATA(cl, obj);
1467 * Any buffering available?
1469 if (bd->bd_BMO)
1472 * Cleanup the buffers.
1474 DeleteBMO(bd->bd_BMO);
1475 bd->bd_BMO = NULL;
1478 * Clear all drag related flags.
1480 bd->bd_Flags &= ~BDF_MOVING;
1483 return AsmDoSuperMethodA(cl, obj, (Msg)gpgi);
1485 METHOD_END
1487 /// BASE_DRAGQUERY
1489 * Query request if this object is willing or able
1490 * to receive the drag-object data.
1492 METHOD(BaseClassDragQuery, struct bmDragPoint *, bmdp)
1494 BD *bd = INST_DATA(cl, obj);
1495 ULONG rc = BQR_REJECT;
1498 * The baseclass will allow _all_ drag objects
1499 * when this object is DROPPABLE and the mouse is
1500 * located inside the hitbox bounds.
1503 if (bd->bd_Flags & BDF_DROPPABLE)
1505 if (bmdp->bmdp_Mouse.X >= 0 &&
1506 bmdp->bmdp_Mouse.Y >= 0 &&
1507 bmdp->bmdp_Mouse.X < bd->bd_HitBox.Width &&
1508 bmdp->bmdp_Mouse.Y < bd->bd_HitBox.Height)
1509 rc = BQR_ACCEPT;
1511 return rc;
1513 METHOD_END
1515 /// BASE_DRAGACTIVE
1517 * Show us as being the active receiver of the
1518 * drag object.
1520 METHOD(BaseClassDragActive, struct bmDragMsg *, bmdm)
1522 BD *bd = INST_DATA(cl, obj);
1523 struct BaseInfo *bi;
1525 bd->bd_Flags |= BDF_MOVE_DROPBOX;
1528 * Let's show'm were active.
1530 #ifdef DEBUG_BGUI
1531 if ((bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_GadgetInfo, bmdm->bmdm_GInfo, BI_RastPort, NULL, TAG_DONE)))
1532 #else
1533 if ((bi = AllocBaseInfo(BI_GadgetInfo, bmdm->bmdm_GInfo, BI_RastPort, NULL, TAG_DONE)))
1534 #endif
1537 * Draw the box.
1539 DottedBox(bi, &bd->bd_HitBox);
1541 FreeBaseInfo(bi);
1543 return 1;
1545 METHOD_END
1547 /// BASE_DRAGUPDATE
1549 * We return BUR_CONTINUE while the coordinates are
1550 * still in the hitbox bounds.
1552 METHOD(BaseClassDragUpdate, struct bmDragPoint *, bmdp)
1554 BD *bd = INST_DATA(cl, obj);
1555 struct BaseInfo *bi;
1557 int x = bmdp->bmdp_Mouse.X;
1558 int y = bmdp->bmdp_Mouse.Y;
1560 if (bd->bd_Flags & BDF_MOVE_DROPBOX)
1562 #ifdef DEBUG_BGUI
1563 if ((bi = AllocBaseInfoDebug(__FILE__,__LINE__,BI_GadgetInfo, bmdp->bmdp_GInfo, BI_RastPort, NULL, TAG_DONE)))
1564 #else
1565 if ((bi = AllocBaseInfo(BI_GadgetInfo, bmdp->bmdp_GInfo, BI_RastPort, NULL, TAG_DONE)))
1566 #endif
1568 DottedBox(bi, &bd->bd_HitBox);
1569 FreeBaseInfo(bi);
1573 if ((x >= 0) && (y >= 0) && (x < bd->bd_HitBox.Width) && (y < bd->bd_HitBox.Height))
1574 return BUR_CONTINUE;
1576 return BUR_ABORT;
1578 METHOD_END
1580 /// BASE_DRAGDROPPED
1582 * We beep the display when we are dropped and
1583 * the message get's here.
1585 METHOD(BaseClassDragDropped, struct bmDropped *, bmd)
1588 * Only beep our screen.
1590 if (bmd->bmd_GInfo)
1591 DisplayBeep(bmd->bmd_GInfo->gi_Screen);
1593 return 1;
1595 METHOD_END
1597 /// BASE_DRAG_INACTIVE
1599 * Deactivate us as being the active receiver of the
1600 * drag object.
1602 METHOD(BaseClassDragInactive, struct bmDragMsg *, bmdm)
1604 BD *bd = INST_DATA(cl, obj);
1605 struct GadgetInfo *gi = bmdm->bmdm_GInfo;
1606 struct RastPort *rp;
1608 bd->bd_Flags &= ~BDF_MOVE_DROPBOX;
1611 * We will force a redraw of the object
1612 * to eliminate any changes made when the
1613 * object was activated.
1615 if ((rp = BGUI_ObtainGIRPort(bmdm->bmdm_GInfo)))
1618 * Refresh the object.
1620 AsmDoMethod(obj, GM_RENDER, gi, rp, GREDRAW_REDRAW);
1621 ReleaseGIRPort(rp);
1622 return 1;
1624 return 0;
1626 METHOD_END
1628 /// BASE_GETDRAGOBJECT
1630 * Create a bitmap with the image that has to be dragged
1631 * around. The baseclass defaults to a bitmap containing
1632 * the hitbox imagery of the object.
1634 METHOD(BaseClassGetObject, struct bmGetDragObject *, bmgo)
1636 BD *bd = INST_DATA(cl, obj);
1637 struct GadgetInfo *gi = bmgo->bmgo_GInfo, tgi = *gi;
1638 struct RastPort rp = gi->gi_Screen->RastPort;
1639 IPTR rc;
1641 int x = bd->bd_HitBox.Left;
1642 int y = bd->bd_HitBox.Top;
1643 int w = bd->bd_HitBox.Width;
1644 int h = bd->bd_HitBox.Height;
1647 * Allocate a bitmap large enough to hold
1648 * the hitbox of the object.
1650 if ((rc = (IPTR)BGUI_AllocBitMap(w, h, FGetDepth(&rp), BMF_CLEAR, rp.BitMap)))
1653 * Setup rastport for rendering into this new BitMap.
1655 rp.Layer = NULL;
1656 rp.BitMap = (struct BitMap *)rc;
1659 * Setup the GadgetInfo for rendering gadget into this new BitMap.
1661 tgi.gi_RastPort = &rp;
1662 tgi.gi_Layer = NULL;
1665 * Copy the HitBox bounds into the message structure.
1667 *bmgo->bmgo_Bounds = bd->bd_HitBox;
1669 SetAttrs(obj, GA_Left, 0, GA_Top, 0, TAG_DONE);
1670 AsmDoMethod(obj, GM_RENDER, &tgi, &rp, GREDRAW_REDRAW);
1671 SetAttrs(obj, GA_Left, x, GA_Top, y, TAG_DONE);
1673 return rc;
1675 METHOD_END
1677 /// BASE_FREEDRAGOBJECT
1679 * Free the bitmap allocate with BASE_GETDRAGOBJECT.
1681 METHOD(BaseClassFreeObject, struct bmFreeDragObject *, bmfo)
1684 * Simply free the bitmap created
1685 * in the BASE_GETDRAGOBJECT method.
1687 BGUI_FreeBitMap(bmfo->bmfo_ObjBitMap);
1688 return 1;
1690 METHOD_END
1692 /// BASE_MOVEBOUNDS
1694 static void MoveBox(struct IBox *box, struct bmMoveBounds *bmmb)
1696 box->Left += bmmb->bmmb_ChangeX;
1697 box->Top += bmmb->bmmb_ChangeY;
1698 box->Width += bmmb->bmmb_ChangeW;
1699 box->Height += bmmb->bmmb_ChangeH;
1702 METHOD(BaseClassMoveBounds, struct bmMoveBounds *, bmmb)
1704 BD *bd = INST_DATA(cl, obj);
1706 MoveBox(GADGETBOX(obj), bmmb);
1707 MoveBox(&bd->bd_OuterBox, bmmb);
1708 MoveBox(&bd->bd_InnerBox, bmmb);
1709 MoveBox(&bd->bd_HitBox, bmmb);
1711 return 1;
1713 METHOD_END
1715 /// BASE_FINDKEY
1717 * Does object has the proper key?
1719 METHOD(BaseClassFindKey, struct bmFindKey *, bmfk)
1721 #define QUAL_SHIFT (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)
1722 #define QUAL_ALT (IEQUALIFIER_LALT|IEQUALIFIER_RALT)
1723 #define QUAL_MASK 0x71FF
1725 BD *bd = INST_DATA(cl, obj);
1727 UWORD Key = bmfk->bmfk_Key.Key;
1728 UWORD Qual = bmfk->bmfk_Key.Qual & QUAL_MASK;
1729 UBYTE key = bd->bd_RawKey;
1730 UWORD qual = bd->bd_Qual & QUAL_MASK;
1732 if ((GADGET(obj)->Flags & GFLG_DISABLED) || (bd->bd_Flags & BDF_INHIBITED))
1733 return (IPTR)NULL;
1735 if (qual == QUAL_MASK) Qual = qual;
1737 if (((qual & QUAL_SHIFT) == QUAL_SHIFT) && (Qual & QUAL_SHIFT)) Qual |= QUAL_SHIFT;
1738 if (((qual & QUAL_ALT) == QUAL_ALT) && (Qual & QUAL_ALT)) Qual |= QUAL_ALT;
1740 if (Key & 0xFF00) /* RAWKEY press, must match exactly */
1742 if (key != (UBYTE)~0)
1744 if ((key == (Key & 0x007F)) && (qual == Qual))
1746 return (IPTR)obj;
1750 else /* VANILLAKEY press */
1752 if (bd->bd_Key) /* We have a vanilla key equivalent */
1754 if ((ToLower(*bd->bd_Key) == ToLower(Key)) && (qual == Qual))
1756 return (IPTR)obj;
1760 return (IPTR)NULL;
1762 METHOD_END
1764 /// BASE_KEYLABEL
1766 * Attach key from label to object.
1768 METHOD(BaseClassKeyLabel, struct bmKeyLabel *, bmkl)
1770 BD *bd = INST_DATA(cl, obj);
1771 IPTR rc = 0;
1773 if (bd->bd_Label)
1775 bd->bd_Key = NULL;
1776 bd->bd_RawKey = (UBYTE)~0;
1777 bd->bd_Qual = 0;
1779 Get_Attr(bd->bd_Label, LAB_KeyChar, &rc);
1780 if (rc)
1782 bd->bd_Key = (UBYTE *)rc;
1783 bd->bd_Qual = (UWORD)~0;
1786 return rc;
1788 METHOD_END
1790 /// BASE_LOCALIZE
1792 * Attach key from label to object.
1794 METHOD(BaseClassLocalize, struct bmLocalize *, bml)
1796 BD *bd = INST_DATA(cl, obj);
1798 if (bd->bd_Label) AsmDoMethodA(bd->bd_Label, (Msg)bml);
1799 if (bd->bd_Frame) AsmDoMethodA(bd->bd_Frame, (Msg)bml);
1801 if (bd->bd_HelpTextID) bd->bd_HelpText =
1802 BGUI_GetCatalogStr(bml->bml_Locale, bd->bd_HelpTextID, bd->bd_HelpText);
1804 if (bd->bd_ToolTipID) bd->bd_ToolTip =
1805 BGUI_GetCatalogStr(bml->bml_Locale, bd->bd_ToolTipID, bd->bd_ToolTip);
1807 return 1;
1809 METHOD_END
1811 /// BASE_INHIBIT
1813 * Inhibit/uninhibit object.
1815 METHOD(BaseClassInhibit, struct bmInhibit *, bmi)
1817 BD *bd = INST_DATA(cl, obj);
1819 if (bmi->bmi_Inhibit) bd->bd_Flags |= BDF_INHIBITED;
1820 else bd->bd_Flags &= ~BDF_INHIBITED;
1822 return 1;
1824 METHOD_END
1826 /// BASE_IS_MULTI
1827 METHOD(BaseClassIsMulti, Msg, msg)
1829 return FALSE;
1831 METHOD_END
1833 /// Class initialization.
1835 * Class function array.
1837 STATIC DPFUNC ClassFunc[] =
1839 { RM_GET, BaseClassGet, },
1840 { RM_GETCUSTOM, BaseClassGetCustom, },
1841 { RM_SET, BaseClassSet, },
1842 { RM_SETCUSTOM, BaseClassSetCustom, },
1843 { RM_GETATTRFLAGS, BaseClassGetAttrFlags, },
1844 { RM_REFRESH, BaseClassRefresh, },
1845 { OM_NOTIFY, BaseClassNotify, },
1846 { OM_DISPOSE, BaseClassDispose, },
1847 { OM_NEW, BaseClassNew, },
1849 { BASE_LAYOUT, BaseClassLayout, },
1850 { BASE_RENDER, BaseClassRender, },
1851 { BASE_DIMENSIONS, BaseClassDimensions, },
1853 { GM_RENDER, BaseClassRenderX, },
1854 { GRM_DIMENSIONS, BaseClassDimensionsX, },
1855 { BASE_RELAYOUT, BaseClassRelayout, },
1857 { GM_HITTEST, BaseClassHitTest, },
1858 { GM_HELPTEST, BaseClassHelpTest, },
1859 { BASE_IS_MULTI, BaseClassIsMulti, },
1860 { BASE_SHOWHELP, BaseClassHelp, },
1861 { BASE_LEFTEXT, BaseClassLeftExt, },
1862 { WM_KEYACTIVE, BaseClassKeyActive, },
1863 { GM_GOACTIVE, BaseClassGoActive, },
1864 { GM_GOINACTIVE, BaseClassGoInactive, },
1865 { BASE_MOVEBOUNDS, BaseClassMoveBounds, },
1866 { BASE_DRAGGING, BaseClassDragging, },
1867 { BASE_DRAGQUERY, BaseClassDragQuery, },
1868 { BASE_DRAGACTIVE, BaseClassDragActive, },
1869 { BASE_DRAGUPDATE, BaseClassDragUpdate, },
1870 { BASE_DROPPED, BaseClassDragDropped, },
1871 { BASE_DRAGINACTIVE, BaseClassDragInactive, },
1872 { BASE_GETDRAGOBJECT, BaseClassGetObject, },
1873 { BASE_FREEDRAGOBJECT, BaseClassFreeObject, },
1874 { BASE_FINDKEY, BaseClassFindKey, },
1875 { BASE_KEYLABEL, BaseClassKeyLabel, },
1876 { BASE_LOCALIZE, BaseClassLocalize, },
1877 { BASE_INHIBIT, BaseClassInhibit, },
1879 { DF_END },
1882 makeproto Class *BaseClass = NULL;
1885 * Simple class initialization.
1887 makeproto Class *InitBaseClass(void)
1889 return BaseClass = BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_GADGET_OBJECT,
1890 CLASS_ObjectSize, sizeof(BD),
1891 CLASS_DFTable, ClassFunc,
1892 TAG_DONE);