Updated to latest source.
[AROS-Contrib.git] / bgui / viewclass.c
blobbbb513e25b57cde7f9cd731b8a06914887fc0c83
1 /*
2 * @(#) $Header$
4 * BGUI library
5 * viewclass.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.2 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.1 2000/05/15 19:27:03 stegerg
18 * another hundreds of REG() macro replacements in func headers/protos.
20 * Revision 42.0 2000/05/09 22:10:39 mlemos
21 * Bumped to revision 42.0 before handing BGUI to AROS team
23 * Revision 41.11 2000/05/09 19:55:27 mlemos
24 * Merged with the branch Manuel_Lemos_fixes.
26 * Revision 41.10.2.4 1999/08/01 22:49:31 mlemos
27 * Assured proper replacement of scroller bars after the object is created.
29 * Revision 41.10.2.3 1999/08/01 19:23:33 mlemos
30 * Assured that external scroller gadgets are redrawn when the view position
31 * is updated.
33 * Revision 41.10.2.2 1999/08/01 04:13:48 mlemos
34 * Assured that the rendering of a view within a view is not clipped against
35 * the window boundaries.
36 * Assured that the view of the self created scroll bars is the same as of the
37 * view object.
38 * Made the scroll bars be rendered or updated in the GM_RENDER method.
39 * Added support for the VIEW_CLIP method to not clip against the parent view
40 * if requested.
42 * Revision 41.10.2.1 1998/12/06 22:36:10 mlemos
43 * Set parent window of contained object on the view object creation.
44 * Set parent window and parent view of of the scroller gadgets on the view
45 * object creation.
47 * Revision 41.10 1998/02/25 21:13:31 mlemos
48 * Bumping to 41.10
50 * Revision 1.1 1998/02/25 17:10:04 mlemos
51 * Ian sources
56 /// Class definitiions.
57 #include "include/classdefs.h"
60 * Instance data.
62 typedef struct {
63 ULONG vd_Flags; /* View flags. */
64 struct IBox vd_AreaBox; /* Current area bounds. */
65 UWORD vd_MinWidth; /* Minimum width of area. */
66 UWORD vd_MinHeight; /* Minimum height of area. */
67 Object *vd_Object; /* Object to view. */
68 UWORD vd_ObjectWidth; /* Width of object. */
69 UWORD vd_ObjectHeight; /* Height of object. */
70 struct RastPort *vd_ObjectBuffer; /* RastPort buffer. */
71 UWORD vd_ScaleWidth; /* Extra width. */
72 UWORD vd_ScaleHeight; /* Extra height. */
73 UWORD vd_ScaleMinWidth; /* Scaled minimum width. */
74 UWORD vd_ScaleMinHeight; /* Scaled minimum height. */
75 Object *vd_VScroller; /* Vertical scroller. */
76 Object *vd_HScroller; /* Horizontal scroller. */
77 UWORD vd_ScrollerW; /* Width of v-scroller. */
78 UWORD vd_ScrollerH; /* Height of h-scroller. */
79 WORD vd_X, vd_Y; /* Current position. */
80 WORD vd_BX, vd_BY; /* Base position. */
81 WORD vd_LX, vd_LY; /* Last position. */
82 UWORD vd_Qualifier; /* Qualifier for drag move. */
83 Object *vd_Parent; /* Parent window. */
84 Object *vd_ParentView; /* Parent view. */
85 struct Rectangle vd_ClipRect; /* Clipping rectangle. */
86 UWORD vd_CachedWidth; /* Cached width of object. */
87 UWORD vd_CachedHeight; /* Cached height of object. */
88 BOOL vd_OwnVScroller; /* Own Vertical scroller. */
89 BOOL vd_OwnHScroller; /* Own Horizontal scroller. */
90 } VD;
92 #define VDF_NODISPOSEOBJECT (1<<0) /* Don't dispose object. */
93 #define VDF_VPROPACTIVE (1<<1) /* VScroller active. */
94 #define VDF_HPROPACTIVE (1<<2) /* HScroller active. */
95 #define VDF_DIRECT (1<<3) /* Directly access object. */
96 #define VDF_DRAGMOVE (1<<4) /* Move while dragging. */
97 #define VDF_NO_DRAGMOVE (1<<5) /* Allow this feature. */
100 * Prop map-lists.
102 static struct TagItem VProp2View[] = {
103 PGA_Top, VIEW_Y,
104 TAG_DONE
107 static struct TagItem HProp2View[] = {
108 PGA_Top, VIEW_X,
109 TAG_DONE
113 /// OM_NEW
115 METHOD(ViewClassNew, struct opSet *, ops)
117 VD *vd;
118 ULONG rc;
119 struct TagItem *tstate, *tag, *tags;
121 tags = DefTagList(BGUI_VIEW_GADGET, ops->ops_AttrList);
124 * Let the superclass create an object.
126 if (rc = NewSuperObject(cl, obj, tags))
128 vd = INST_DATA(cl, rc);
130 AsmCoerceMethod(cl, (Object *)rc, OM_SET, tags, NULL);
133 * Object required!
135 if (vd->vd_Object)
137 BC *bc = BASE_DATA(rc);
139 DoSetMethodNG(vd->vd_Object, BT_ParentView, rc, BT_ParentGroup, rc, BT_ParentWindow, vd->vd_Parent, TAG_DONE);
141 vd->vd_OwnHScroller=vd->vd_OwnVScroller=TRUE;
144 * Filter out frame and label attributes.
146 tstate = tags;
147 while (tag = NextTagItem(&tstate))
149 switch (tag->ti_Tag)
152 * We control the horizontal, we control the vertical.
154 case PGA_Freedom:
156 * Don't disable prop!
158 case GA_Disabled:
160 * No drag'n'drop on the prop.
162 case BT_DragObject:
163 case BT_DropObject:
164 tag->ti_Tag = TAG_IGNORE;
165 break;
167 case VIEW_HScroller:
168 tag->ti_Tag = TAG_IGNORE;
169 vd->vd_OwnHScroller=FALSE;
170 break;
172 case VIEW_VScroller:
173 tag->ti_Tag = TAG_IGNORE;
174 vd->vd_OwnVScroller=FALSE;
175 break;
177 default:
178 if (FRM_TAG(tag->ti_Tag) || LAB_TAG(tag->ti_Tag))
179 tag->ti_Tag = TAG_IGNORE;
180 break;
184 if(vd->vd_OwnHScroller)
186 Object *scroller;
188 vd->vd_OwnHScroller=FALSE;
189 if((scroller = BGUI_NewObject(BGUI_PROP_GADGET,
190 GA_ID, GADGET(rc)->GadgetID,
191 PGA_DontTarget, TRUE,
192 PGA_Freedom, FREEHORIZ,
193 PGA_Arrows, FALSE,
194 BT_ParentView, bc->bc_View,
195 BT_ParentWindow, vd->vd_Parent,
196 TAG_MORE, tags)))
198 DoSetMethodNG((Object *)rc, VIEW_HScroller, scroller, TAG_DONE);
199 vd->vd_OwnHScroller=TRUE;
200 vd->vd_ScrollerH = 14;
204 if(vd->vd_OwnVScroller)
206 Object *scroller;
208 vd->vd_OwnVScroller=FALSE;
209 if((scroller = BGUI_NewObject(BGUI_PROP_GADGET,
210 GA_ID, GADGET(rc)->GadgetID,
211 PGA_DontTarget, TRUE,
212 PGA_Freedom, FREEVERT,
213 PGA_Arrows, FALSE,
214 BT_ParentView, bc->bc_View,
215 BT_ParentWindow, vd->vd_Parent,
216 TAG_MORE, tags)))
218 DoSetMethodNG((Object *)rc, VIEW_VScroller, scroller, TAG_DONE);
219 vd->vd_OwnVScroller=TRUE;
220 vd->vd_ScrollerW = 14;
224 return rc;
226 else
229 * Fail :(
231 AsmCoerceMethod(cl, (Object *)rc, OM_DISPOSE);
232 rc = 0;
235 FreeTagItems(tags);
237 return rc;
239 METHOD_END
241 /// OM_DISPOSE
243 METHOD(ViewClassDispose, Msg, msg)
245 VD *vd = INST_DATA(cl, obj);
247 if (vd->vd_OwnVScroller) DisposeObject(vd->vd_VScroller);
248 if (vd->vd_OwnHScroller) DisposeObject(vd->vd_HScroller);
250 if (vd->vd_ObjectBuffer) BGUI_FreeRPortBitMap(vd->vd_ObjectBuffer);
252 if (!(vd->vd_Flags & VDF_NODISPOSEOBJECT))
253 if (vd->vd_Object) DisposeObject(vd->vd_Object);
255 return AsmDoSuperMethodA(cl, obj, msg);
257 METHOD_END
259 /// OM_SET
260 METHOD(ViewClassSet, struct opSet *, ops)
262 VD *vd = INST_DATA(cl, obj);
263 struct TagItem *tstate = ops->ops_AttrList, *tag;
264 ULONG rc = 1, update = FALSE, data;
267 * First we let the superclass
268 * do it's thing.
270 AsmDoSuperMethodA(cl, obj, (Msg)ops);
272 while (tag = NextTagItem(&tstate))
274 data = tag->ti_Data;
275 switch (tag->ti_Tag)
277 case VIEW_MinWidth:
278 vd->vd_MinWidth = data;
279 break;
281 case VIEW_MinHeight:
282 vd->vd_MinHeight = data;
283 break;
285 case VIEW_ScaleMinWidth:
286 vd->vd_ScaleMinWidth = data;
287 break;
289 case VIEW_ScaleMinHeight:
290 vd->vd_ScaleMinHeight = data;
291 break;
293 case VIEW_ScaleWidth:
294 vd->vd_ScaleWidth = data;
295 break;
297 case VIEW_ScaleHeight:
298 vd->vd_ScaleHeight = data;
299 break;
301 case VIEW_Object:
302 vd->vd_Object = (Object *)data;
303 break;
305 case VIEW_X:
306 if (vd->vd_X != data) update = TRUE;
307 vd->vd_X = data;
308 break;
310 case VIEW_Y:
311 if (vd->vd_Y != data) update = TRUE;
312 vd->vd_Y = data;
313 break;
315 case VIEW_ObjectBuffer:
316 if (vd->vd_ObjectBuffer) BGUI_FreeRPortBitMap(vd->vd_ObjectBuffer);
317 vd->vd_ObjectBuffer = (struct RastPort *)data;
318 break;
320 case VIEW_NoDisposeObject:
321 if (data)
322 vd->vd_Flags |= VDF_NODISPOSEOBJECT;
323 else
324 vd->vd_Flags &= ~VDF_NODISPOSEOBJECT;
325 break;
327 case VIEW_VScroller:
328 if (vd->vd_OwnVScroller)
330 DisposeObject(vd->vd_VScroller);
331 vd->vd_OwnVScroller=FALSE;
333 if (vd->vd_VScroller = (Object *)data)
335 AsmDoMethod(vd->vd_VScroller, BASE_ADDMAP, obj, VProp2View);
336 vd->vd_ScrollerW = 0;
337 update=TRUE;
339 break;
341 case VIEW_HScroller:
342 if (vd->vd_OwnHScroller)
344 DisposeObject(vd->vd_HScroller);
345 vd->vd_OwnHScroller=FALSE;
347 if (vd->vd_HScroller = (Object *)data)
349 AsmDoMethod(vd->vd_HScroller, BASE_ADDMAP, obj, HProp2View);
350 vd->vd_ScrollerH = 0;
351 update=TRUE;
353 break;
355 case BT_ParentView:
356 vd->vd_ParentView = (Object *)data;
357 break;
359 case BT_ParentWindow:
360 vd->vd_Parent = (Object *)data;
361 case BT_TextAttr:
362 case FRM_ThinFrame:
363 DoMultiSet(tag->ti_Tag, data, 3, vd->vd_Object, vd->vd_HScroller, vd->vd_VScroller);
364 break;
367 if (vd->vd_ScaleWidth < 100) vd->vd_ScaleWidth = 100;
368 if (vd->vd_ScaleHeight < 100) vd->vd_ScaleHeight = 100;
370 if (update
371 && ops->ops_GInfo)
372 DoRenderMethod(obj, ops->ops_GInfo, GREDRAW_UPDATE);
374 return rc;
376 METHOD_END
378 /// OM_GET
379 METHOD(ViewClassGet, struct opGet *, opg)
381 VD *vd = INST_DATA(cl, obj);
382 BC *bc = BASE_DATA(obj);
383 ULONG rc = 1;
384 ULONG *store = opg->opg_Storage;
386 switch (opg->opg_AttrID)
388 case VIEW_MinWidth:
389 STORE vd->vd_MinWidth;
390 break;
392 case VIEW_MinHeight:
393 STORE vd->vd_MinHeight;
394 break;
396 case VIEW_ScaleMinWidth:
397 STORE vd->vd_ScaleMinWidth;
398 break;
400 case VIEW_ScaleMinHeight:
401 STORE vd->vd_ScaleMinHeight;
402 break;
404 case VIEW_ScaleWidth:
405 STORE vd->vd_ScaleWidth;
406 break;
408 case VIEW_ScaleHeight:
409 STORE vd->vd_ScaleHeight;
410 break;
412 case VIEW_X:
413 STORE vd->vd_X;
414 break;
416 case VIEW_Y:
417 STORE vd->vd_Y;
418 break;
420 case VIEW_AbsoluteX:
421 if (vd->vd_ParentView)
422 Get_Attr(vd->vd_ParentView, VIEW_AbsoluteX, store);
423 else
424 *store = 0;
425 *store += ((vd->vd_Flags & VDF_DIRECT) ? &bc->bc_OuterBox : &bc->bc_InnerBox)->Left - vd->vd_X;
426 break;
428 case VIEW_AbsoluteY:
429 if (vd->vd_ParentView)
430 Get_Attr(vd->vd_ParentView, VIEW_AbsoluteY, store);
431 else
432 *store = 0;
433 *store += ((vd->vd_Flags & VDF_DIRECT) ? &bc->bc_OuterBox : &bc->bc_InnerBox)->Top - vd->vd_Y;
434 break;
436 case VIEW_ObjectBuffer:
437 STORE vd->vd_ObjectBuffer;
438 break;
440 case BT_PostRenderHighestClass:
441 STORE cl;
442 break;
444 default:
445 rc = AsmDoSuperMethodA(cl, obj, (Msg)opg);
446 break;
448 return rc;
450 METHOD_END
452 /// ViewClassForward
454 * Forward a message to the object.
456 METHOD(ViewClassForward, Msg, msg)
458 VD *vd = INST_DATA(cl, obj);
459 ULONG rc = GMR_NOREUSE;
462 * Do we have an active member?
464 if (vd->vd_Object)
467 * Forward the message to the object.
469 rc = AsmDoMethodA(vd->vd_Object, msg);
472 * Take over the object's GadgetID.
474 GADGET(obj)->GadgetID = GADGET(vd->vd_Object)->GadgetID;
476 return rc;
478 METHOD_END
480 /// GM_RENDER
482 METHOD(ViewClassRender, struct gpRender *, gpr)
484 VD *vd = INST_DATA(cl, obj);
485 BC *bc = BASE_DATA(obj);
486 struct GadgetInfo *gi = gpr->gpr_GInfo;
487 struct RastPort *rp;
488 Object *o = vd->vd_Object, *vscroll, *hscroll;
489 ULONG rc = 0;
490 UWORD ow, oh, vw, vh, sw, sh;
491 struct Rectangle cr;
492 struct IBox *box;
494 DoSetMethodNG(bc->bc_Frame, FRM_OuterOffsetRight, vd->vd_ScrollerW,
495 FRM_OuterOffsetBottom, vd->vd_ScrollerH,
496 TAG_DONE);
499 * See if rendering is allowed.
501 if (!AsmDoSuperMethodA(cl, obj, (Msg)gpr))
502 return 0;
504 if (o && (rp = bc->bc_RPort))
506 if ((gpr->gpr_Redraw == GREDRAW_REDRAW) || !vd->vd_ObjectBuffer)
508 AsmDoMethod(o, GRM_DIMENSIONS, gi, rp, &vd->vd_CachedWidth, &vd->vd_CachedHeight, 0);
511 ow = ScaleWeight(vd->vd_CachedWidth, 100, vd->vd_ScaleWidth);
512 oh = ScaleWeight(vd->vd_CachedHeight, 100, vd->vd_ScaleHeight);
514 vscroll = vd->vd_VScroller;
515 hscroll = vd->vd_HScroller;
517 sw = vd->vd_ScrollerW;
518 sh = vd->vd_ScrollerH;
520 if ((ow < bc->bc_OuterBox.Width) && (oh < bc->bc_OuterBox.Height))
522 vd->vd_Flags |= VDF_DIRECT;
524 if (sw) vscroll = 0;
525 if (sh) hscroll = 0;
527 box = &bc->bc_OuterBox;
529 else
531 vd->vd_Flags &= ~VDF_DIRECT;
533 box = &bc->bc_InnerBox;
536 vw = box->Width;
537 vh = box->Height;
539 if (ow < vw) ow = vw;
540 if (oh < vh) oh = vh;
542 vd->vd_ObjectWidth = ow;
543 vd->vd_ObjectHeight = oh;
545 vd->vd_X = range(vd->vd_X, 0, ow - vw);
546 vd->vd_Y = range(vd->vd_Y, 0, oh - vh);
548 if (hscroll) DoSetMethodNG(hscroll, PGA_Top, vd->vd_X, PGA_Total, ow, PGA_Visible, vw, TAG_DONE);
549 if (vscroll) DoSetMethodNG(vscroll, PGA_Top, vd->vd_Y, PGA_Total, oh, PGA_Visible, vh, TAG_DONE);
551 DoSetMethodNG(o, GA_Left, 0, GA_Top, 0, GA_Width, ow, GA_Height, oh, TAG_DONE);
552 if ((gpr->gpr_Redraw == GREDRAW_REDRAW) || !vd->vd_ObjectBuffer)
554 if (vd->vd_ObjectBuffer) BGUI_FreeRPortBitMap(vd->vd_ObjectBuffer);
556 if (!(vd->vd_ObjectBuffer = BGUI_CreateRPortBitMap(rp, ow, oh, FGetDepth(rp))))
557 return 0;
559 AsmDoMethod(o, GM_RENDER, gi, vd->vd_ObjectBuffer, GREDRAW_REDRAW);
562 if (hscroll
563 && (!(vd->vd_Flags & VDF_DIRECT)
564 || !sw))
566 if (sw)
568 DoSetMethodNG(hscroll, GA_Left, bc->bc_OuterBox.Left,
569 GA_Top, bc->bc_OuterBox.Top + bc->bc_OuterBox.Height - sh,
570 GA_Width, bc->bc_OuterBox.Width - sw,
571 GA_Height, sh,
572 TAG_DONE);
574 AsmDoMethod(hscroll, GM_RENDER, gi, rp, gpr->gpr_Redraw);
576 if (vscroll
577 && (!(vd->vd_Flags & VDF_DIRECT)
578 || !sh))
580 if (sh)
582 DoSetMethodNG(vscroll, GA_Left, bc->bc_OuterBox.Left + bc->bc_OuterBox.Width - sw,
583 GA_Top, bc->bc_OuterBox.Top,
584 GA_Width, sw,
585 GA_Height, bc->bc_OuterBox.Height - sh,
586 TAG_DONE);
588 AsmDoMethod(vscroll, GM_RENDER, gi, rp, gpr->gpr_Redraw);
591 box = (vd->vd_Flags & VDF_DIRECT) ? &bc->bc_OuterBox : &bc->bc_InnerBox;
593 vd->vd_X = range(vd->vd_X, 0, vd->vd_ObjectWidth - box->Width);
594 vd->vd_Y = range(vd->vd_Y, 0, vd->vd_ObjectHeight - box->Height);
596 cr.MinX = box->Left;
597 cr.MinY = box->Top;
598 cr.MaxX = box->Left + box->Width - 1;
599 cr.MaxY = box->Top + box->Height - 1;
601 AsmDoMethod(obj, VIEW_CLIP, &cr, FALSE);
602 ClipBlit(vd->vd_ObjectBuffer, vd->vd_X, vd->vd_Y,
603 rp, cr.MinX, cr.MinY, cr.MaxX - cr.MinX + 1, cr.MaxY - cr.MinY + 1, 0xC0);
605 rc = 1;
607 BGUI_PostRender(cl, obj, gpr);
609 return rc;
611 METHOD_END
615 * Forward certain types of messages with modifications.
617 ULONG ForwardViewMsg(Class *cl, Object *s, Object *d, Msg msg)
619 VD *vd = INST_DATA(cl, s);
620 WORD *mouse = NULL;
621 ULONG rc, storage;
624 * Get address of mouse coordinates in message.
626 switch (msg->MethodID)
628 case GM_HITTEST:
629 case GM_HELPTEST:
630 mouse = (WORD *)&((struct gpHitTest *)msg)->gpht_Mouse;
631 break;
632 case GM_GOACTIVE:
633 case GM_HANDLEINPUT:
634 mouse = (WORD *)&((struct gpInput *)msg)->gpi_Mouse;
635 break;
637 if (!mouse) return 0;
640 * Store the coordinates.
642 storage = *(ULONG *)mouse;
645 * Adjust the coordinates to be relative to the destination object.
647 mouse[0] += vd->vd_X;
648 mouse[1] += vd->vd_Y;
651 * Send the message to the destination object.
653 rc = AsmDoMethodA(d, msg);
656 * Put the coordinates back to what they were originally.
658 *(ULONG *)mouse = storage;
660 return rc;
663 /// GM_HITTEST
665 * Forward a message to the object.
667 METHOD(ViewClassHitTest, struct gpHitTest *, gph)
669 VD *vd = INST_DATA(cl, obj);
670 BC *bc = BASE_DATA(obj);
671 ULONG rc = 0;
674 * Get absolute click position.
676 WORD l = GADGET(obj)->LeftEdge + gph->gpht_Mouse.X;
677 WORD t = GADGET(obj)->TopEdge + gph->gpht_Mouse.Y;
679 if (PointInBox(&bc->bc_InnerBox, l, t))
682 * Hit inside the view area?
684 rc = ForwardViewMsg(cl, obj, vd->vd_Object, (Msg)gph);
685 if (rc != GMR_GADGETHIT)
687 if (!(vd->vd_Flags & (VDF_NO_DRAGMOVE|VDF_DIRECT)))
689 vd->vd_Flags |= VDF_DRAGMOVE;
691 vd->vd_BX = vd->vd_X;
692 vd->vd_BY = vd->vd_Y;
693 vd->vd_LX = gph->gpht_Mouse.X;
694 vd->vd_LY = gph->gpht_Mouse.Y;
696 rc = GMR_GADGETHIT;
701 * Take over the object's GadgetID.
703 GADGET(obj)->GadgetID = GADGET(vd->vd_Object)->GadgetID;
706 if (!rc && vd->vd_VScroller)
709 * Route the message.
711 rc = ForwardMsg(obj, vd->vd_VScroller, (Msg)gph);
714 * Mark the scroller active.
716 if (rc == GMR_GADGETHIT) vd->vd_Flags |= VDF_VPROPACTIVE;
719 if (!rc && vd->vd_HScroller)
722 * Route the message.
724 rc = ForwardMsg(obj, vd->vd_HScroller, (Msg)gph);
727 * Mark the scroller active.
729 if (rc == GMR_GADGETHIT) vd->vd_Flags |= VDF_HPROPACTIVE;
731 return rc;
733 METHOD_END
735 /// GM_HANDLEINPUT
737 * Handle input.
739 METHOD(ViewClassHandleInput, struct gpInput *, gpi)
741 VD *vd = INST_DATA(cl, obj);
742 struct InputEvent *ie;
743 ULONG rc;
746 * Drag-moving?
748 if (vd->vd_Flags & VDF_DRAGMOVE)
750 ie = gpi->gpi_IEvent;
752 // qualifier stuff here return GMR_NOREUSE;
754 if (ie->ie_Class == IECLASS_RAWMOUSE)
756 if (ie->ie_Code == SELECTUP)
758 return GMR_NOREUSE;
760 if (ie->ie_Code == MENUDOWN)
762 DoSetMethod(obj, gpi->gpi_GInfo, VIEW_X, vd->vd_BX, VIEW_Y, vd->vd_BY, TAG_DONE);
764 return GMR_NOREUSE;
767 //if (ie->ie_Class == IECLASS_POINTERPOS)
769 DoSetMethod(obj, gpi->gpi_GInfo, VIEW_X, vd->vd_BX - gpi->gpi_Mouse.X + vd->vd_LX,
770 VIEW_Y, vd->vd_BY - gpi->gpi_Mouse.Y + vd->vd_LY, TAG_DONE);
773 return GMR_MEACTIVE;
777 * VScroller active?
779 if (vd->vd_Flags & VDF_VPROPACTIVE)
780 return ForwardMsg(obj, vd->vd_VScroller, (Msg)gpi) & ~GMR_VERIFY;
783 * HScroller active?
785 if (vd->vd_Flags & VDF_HPROPACTIVE)
786 return ForwardMsg(obj, vd->vd_HScroller, (Msg)gpi) & ~GMR_VERIFY;
788 if (vd->vd_Object)
791 * Route the message.
793 rc = ForwardViewMsg(cl, obj, vd->vd_Object, (Msg)gpi);
796 * Take over the object's GadgetID.
798 *(gpi->gpi_Termination) =
799 GADGET(obj)->GadgetID = GADGET(vd->vd_Object)->GadgetID;
801 return rc;
803 return 0;
805 METHOD_END
807 /// GM_GOINACTIVE
809 * Go inactive.
811 METHOD(ViewClassGoInactive, struct gpGoInactive *, gpgi)
813 VD *vd = INST_DATA(cl, obj);
814 ULONG rc = 0;
816 if (vd->vd_Flags & VDF_DRAGMOVE)
818 vd->vd_Flags &= ~VDF_DRAGMOVE;
819 return AsmDoSuperMethodA(cl, obj, (Msg)gpgi);
822 if (vd->vd_VScroller && (vd->vd_Flags & VDF_VPROPACTIVE))
825 * Mark the scroller as not active.
827 vd->vd_Flags &= ~VDF_VPROPACTIVE;
829 * If the scroller was active pass this message on for compatibility reasons.
831 return AsmDoMethodA(vd->vd_VScroller, (Msg)gpgi);
834 if (vd->vd_HScroller && (vd->vd_Flags & VDF_HPROPACTIVE))
837 * Mark the scroller as not active.
839 vd->vd_Flags &= ~VDF_HPROPACTIVE;
841 * If the scroller was active pass this message on for compatibility reasons.
843 return AsmDoMethodA(vd->vd_HScroller, (Msg)gpgi);
846 if (vd->vd_Object)
849 * Route the message.
851 rc = AsmDoMethodA(vd->vd_Object, (Msg)gpgi);
854 * Take over the object's GadgetID.
856 GADGET(obj)->GadgetID = GADGET(vd->vd_Object)->GadgetID;
858 return rc;
860 METHOD_END
862 /// GRM_WHICHOBJECT
864 * Get the object under the mouse.
866 METHOD(ViewClassWhichObject, struct grmWhichObject *, grwo)
868 VD *vd = INST_DATA(cl, obj);
869 BC *bc = BASE_DATA(obj);
870 Object *ob = vd->vd_Object;
871 struct grmWhichObject wo = *grwo;
873 int x = grwo->grwo_Coords.X;
874 int y = grwo->grwo_Coords.Y;
875 int r = bc->bc_OuterBox.Left + bc->bc_OuterBox.Width - vd->vd_ScrollerW;
876 int b = bc->bc_OuterBox.Top + bc->bc_OuterBox.Height - vd->vd_ScrollerH;
878 if ((x >= r) && (y >= b));
880 if (x >= r)
882 return (ULONG)vd->vd_VScroller;
884 if (y >= b)
886 return (ULONG)vd->vd_HScroller;
889 wo.MethodID = GRM_WHICHOBJECT;
890 wo.grwo_Coords.X = x + vd->vd_X;
891 wo.grwo_Coords.Y = y + vd->vd_Y;
894 * Is object a group?
896 if (IsMulti(ob))
899 * Route message.
901 ob = (Object *)AsmDoMethodA(ob, (Msg)&wo);
903 return (ULONG)ob;
905 METHOD_END
907 /// BASE_DIMENSIONS
909 * Simple dimensions request.
911 METHOD(ViewClassDimensions, struct bmDimensions *, bmd)
913 VD *vd = INST_DATA(cl, obj);
914 struct BaseInfo *bi = bmd->bmd_BInfo;
915 UWORD ow, oh;
916 ULONG mw, mh;
918 if (vd->vd_ScaleMinWidth || vd->vd_ScaleMinHeight)
920 AsmDoMethod(vd->vd_Object, GRM_DIMENSIONS, bi, bi->bi_RPort, &ow, &oh, 0);
923 if (vd->vd_ScaleMinWidth)
925 mw = ScaleWeight(ow, 100, vd->vd_ScaleMinWidth);
927 else
929 mw = vd->vd_MinWidth;
932 if (vd->vd_ScaleMinHeight)
934 mh = ScaleWeight(oh, 100, vd->vd_ScaleMinHeight);
936 else
938 mh = vd->vd_MinHeight;
941 if (mw < 8) mw = 8;
942 if (mh < 8) mh = 8;
945 * We simply add the specified minimum width and height
946 * which are passed to us at create time, plus the scrollers.
948 return CalcDimensions(cl, obj, bmd, mw + vd->vd_ScrollerW, mh + vd->vd_ScrollerH);
950 METHOD_END
952 /// VIEW_CLIP
954 METHOD(ViewClassClip, struct vmClip *, vmc)
956 VD *vd = INST_DATA(cl, obj);
957 BC *bc = BASE_DATA(obj);
958 struct IBox *box = (vd->vd_Flags & VDF_DIRECT) ? &bc->bc_OuterBox : &bc->bc_InnerBox;
960 int x1 = box->Left;
961 int y1 = box->Top;
962 int x2 = box->Width + x1 - 1;
963 int y2 = box->Height + y1 - 1;
965 if (vmc->vmc_Rectangle->MinX < x1) vmc->vmc_Rectangle->MinX = x1;
966 if (vmc->vmc_Rectangle->MaxX > x2) vmc->vmc_Rectangle->MaxX = x2;
967 if (vmc->vmc_Rectangle->MinY < y1) vmc->vmc_Rectangle->MinY = y1;
968 if (vmc->vmc_Rectangle->MaxY > y2) vmc->vmc_Rectangle->MaxY = y2;
970 if (vmc->vmc_WindowClip
971 && vd->vd_ParentView)
972 AsmDoMethodA(vd->vd_ParentView, (Msg)vmc);
974 return 1;
976 METHOD_END
978 /// BASE_IS_MULTI
979 METHOD(ViewClassIsMulti, Msg, msg)
981 return TRUE;
983 METHOD_END
985 /// Class initialization.
987 * Class function table.
989 STATIC DPFUNC ClassFunc[] = {
990 VIEW_CLIP, (FUNCPTR)ViewClassClip,
991 OM_NEW, (FUNCPTR)ViewClassNew,
992 OM_GET, (FUNCPTR)ViewClassGet,
993 OM_SET, (FUNCPTR)ViewClassSet,
994 OM_UPDATE, (FUNCPTR)ViewClassSet,
995 OM_DISPOSE, (FUNCPTR)ViewClassDispose,
996 GM_RENDER, (FUNCPTR)ViewClassRender,
997 BASE_DIMENSIONS, (FUNCPTR)ViewClassDimensions,
998 GRM_WHICHOBJECT, (FUNCPTR)ViewClassWhichObject,
999 GM_HITTEST, (FUNCPTR)ViewClassHitTest,
1000 GM_GOACTIVE, (FUNCPTR)ViewClassHandleInput,
1001 GM_HANDLEINPUT, (FUNCPTR)ViewClassHandleInput,
1002 GM_GOINACTIVE, (FUNCPTR)ViewClassGoInactive,
1003 BASE_MOVEBOUNDS, (FUNCPTR)ViewClassForward,
1004 BASE_LOCALIZE, (FUNCPTR)ViewClassForward,
1005 BASE_KEYLABEL, (FUNCPTR)ViewClassForward,
1006 BASE_FINDKEY, (FUNCPTR)ViewClassForward,
1007 BASE_SHOWHELP, (FUNCPTR)ViewClassForward,
1008 BASE_INHIBIT, (FUNCPTR)ViewClassForward,
1009 BASE_IS_MULTI, (FUNCPTR)ViewClassIsMulti,
1010 DF_END, NULL
1014 * Simple class initialization.
1016 makeproto Class *InitViewClass(void)
1018 return BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_BASE_GADGET,
1019 CLASS_ObjectSize, sizeof(VD),
1020 CLASS_DFTable, ClassFunc,
1021 TAG_DONE);