fix remapping behavior. Remapping is only necessary if we are rendering on the workbe...
[AROS-Contrib.git] / bgui / viewclass.c
blob67c84c2d8245bfd6eef36b347092bf69ccfe5a6f
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 IPTR rc;
119 struct TagItem *tstate;
120 struct TagItem *tag, *tags;
122 tags = DefTagList(BGUI_VIEW_GADGET, ops->ops_AttrList);
125 * Let the superclass create an object.
127 if ((rc = NewSuperObject(cl, obj, tags)))
129 vd = INST_DATA(cl, rc);
131 AsmCoerceMethod(cl, (Object *)rc, OM_SET, tags, NULL);
134 * Object required!
136 if (vd->vd_Object)
138 BC *bc = BASE_DATA(rc);
140 DoSetMethodNG(vd->vd_Object, BT_ParentView, rc, BT_ParentGroup, rc, BT_ParentWindow, vd->vd_Parent, TAG_DONE);
142 vd->vd_OwnHScroller=vd->vd_OwnVScroller=TRUE;
145 * Filter out frame and label attributes.
147 tstate = tags;
148 while ((tag = NextTagItem(&tstate)))
150 switch (tag->ti_Tag)
153 * We control the horizontal, we control the vertical.
155 case PGA_Freedom:
157 * Don't disable prop!
159 case GA_Disabled:
161 * No drag'n'drop on the prop.
163 case BT_DragObject:
164 case BT_DropObject:
165 tag->ti_Tag = TAG_IGNORE;
166 break;
168 case VIEW_HScroller:
169 tag->ti_Tag = TAG_IGNORE;
170 vd->vd_OwnHScroller=FALSE;
171 break;
173 case VIEW_VScroller:
174 tag->ti_Tag = TAG_IGNORE;
175 vd->vd_OwnVScroller=FALSE;
176 break;
178 default:
179 if (FRM_TAG(tag->ti_Tag) || LAB_TAG(tag->ti_Tag))
180 tag->ti_Tag = TAG_IGNORE;
181 break;
185 if(vd->vd_OwnHScroller)
187 Object *scroller;
189 vd->vd_OwnHScroller=FALSE;
190 if((scroller = BGUI_NewObject(BGUI_PROP_GADGET,
191 GA_ID, GADGET(rc)->GadgetID,
192 PGA_DontTarget, TRUE,
193 PGA_Freedom, FREEHORIZ,
194 PGA_Arrows, FALSE,
195 BT_ParentView, bc->bc_View,
196 BT_ParentWindow, vd->vd_Parent,
197 TAG_MORE, tags)))
199 DoSetMethodNG((Object *)rc, VIEW_HScroller, scroller, TAG_DONE);
200 vd->vd_OwnHScroller=TRUE;
201 vd->vd_ScrollerH = 14;
205 if(vd->vd_OwnVScroller)
207 Object *scroller;
209 vd->vd_OwnVScroller=FALSE;
210 if((scroller = BGUI_NewObject(BGUI_PROP_GADGET,
211 GA_ID, GADGET(rc)->GadgetID,
212 PGA_DontTarget, TRUE,
213 PGA_Freedom, FREEVERT,
214 PGA_Arrows, FALSE,
215 BT_ParentView, bc->bc_View,
216 BT_ParentWindow, vd->vd_Parent,
217 TAG_MORE, tags)))
219 DoSetMethodNG((Object *)rc, VIEW_VScroller, scroller, TAG_DONE);
220 vd->vd_OwnVScroller=TRUE;
221 vd->vd_ScrollerW = 14;
225 return rc;
227 else
230 * Fail :(
232 AsmCoerceMethod(cl, (Object *)rc, OM_DISPOSE);
233 rc = 0;
236 FreeTagItems(tags);
238 return rc;
240 METHOD_END
242 /// OM_DISPOSE
244 METHOD(ViewClassDispose, Msg, msg)
246 VD *vd = INST_DATA(cl, obj);
248 if (vd->vd_OwnVScroller) DisposeObject(vd->vd_VScroller);
249 if (vd->vd_OwnHScroller) DisposeObject(vd->vd_HScroller);
251 if (vd->vd_ObjectBuffer) BGUI_FreeRPortBitMap(vd->vd_ObjectBuffer);
253 if (!(vd->vd_Flags & VDF_NODISPOSEOBJECT))
254 if (vd->vd_Object) DisposeObject(vd->vd_Object);
256 return AsmDoSuperMethodA(cl, obj, msg);
258 METHOD_END
260 /// OM_SET
261 METHOD(ViewClassSet, struct opSet *, ops)
263 VD *vd = INST_DATA(cl, obj);
264 ULONG rc = 1, update = FALSE;
265 IPTR data;
266 struct TagItem *tstate = ops->ops_AttrList;
267 struct TagItem *tag;
270 * First we let the superclass
271 * do it's thing.
273 AsmDoSuperMethodA(cl, obj, (Msg)ops);
275 while ((tag = NextTagItem(&tstate)))
277 data = tag->ti_Data;
278 switch (tag->ti_Tag)
280 case VIEW_MinWidth:
281 vd->vd_MinWidth = data;
282 break;
284 case VIEW_MinHeight:
285 vd->vd_MinHeight = data;
286 break;
288 case VIEW_ScaleMinWidth:
289 vd->vd_ScaleMinWidth = data;
290 break;
292 case VIEW_ScaleMinHeight:
293 vd->vd_ScaleMinHeight = data;
294 break;
296 case VIEW_ScaleWidth:
297 vd->vd_ScaleWidth = data;
298 break;
300 case VIEW_ScaleHeight:
301 vd->vd_ScaleHeight = data;
302 break;
304 case VIEW_Object:
305 vd->vd_Object = (Object *)data;
306 break;
308 case VIEW_X:
309 if (vd->vd_X != data) update = TRUE;
310 vd->vd_X = data;
311 break;
313 case VIEW_Y:
314 if (vd->vd_Y != data) update = TRUE;
315 vd->vd_Y = data;
316 break;
318 case VIEW_ObjectBuffer:
319 if (vd->vd_ObjectBuffer) BGUI_FreeRPortBitMap(vd->vd_ObjectBuffer);
320 vd->vd_ObjectBuffer = (struct RastPort *)data;
321 break;
323 case VIEW_NoDisposeObject:
324 if (data)
325 vd->vd_Flags |= VDF_NODISPOSEOBJECT;
326 else
327 vd->vd_Flags &= ~VDF_NODISPOSEOBJECT;
328 break;
330 case VIEW_VScroller:
331 if (vd->vd_OwnVScroller)
333 DisposeObject(vd->vd_VScroller);
334 vd->vd_OwnVScroller=FALSE;
336 if ((vd->vd_VScroller = (Object *)data))
338 AsmDoMethod(vd->vd_VScroller, BASE_ADDMAP, obj, VProp2View);
339 vd->vd_ScrollerW = 0;
340 update=TRUE;
342 break;
344 case VIEW_HScroller:
345 if (vd->vd_OwnHScroller)
347 DisposeObject(vd->vd_HScroller);
348 vd->vd_OwnHScroller=FALSE;
350 if ((vd->vd_HScroller = (Object *)data))
352 AsmDoMethod(vd->vd_HScroller, BASE_ADDMAP, obj, HProp2View);
353 vd->vd_ScrollerH = 0;
354 update=TRUE;
356 break;
358 case BT_ParentView:
359 vd->vd_ParentView = (Object *)data;
360 break;
362 case BT_ParentWindow:
363 vd->vd_Parent = (Object *)data;
364 case BT_TextAttr:
365 case FRM_ThinFrame:
366 DoMultiSet(tag->ti_Tag, data, 3, vd->vd_Object, vd->vd_HScroller, vd->vd_VScroller);
367 break;
370 if (vd->vd_ScaleWidth < 100) vd->vd_ScaleWidth = 100;
371 if (vd->vd_ScaleHeight < 100) vd->vd_ScaleHeight = 100;
373 if (update
374 && ops->ops_GInfo)
375 DoRenderMethod(obj, ops->ops_GInfo, GREDRAW_UPDATE);
377 return rc;
379 METHOD_END
381 /// OM_GET
382 METHOD(ViewClassGet, struct opGet *, opg)
384 VD *vd = INST_DATA(cl, obj);
385 BC *bc = BASE_DATA(obj);
386 ULONG rc = 1;
387 IPTR *store = opg->opg_Storage;
389 switch (opg->opg_AttrID)
391 case VIEW_MinWidth:
392 STORE vd->vd_MinWidth;
393 break;
395 case VIEW_MinHeight:
396 STORE vd->vd_MinHeight;
397 break;
399 case VIEW_ScaleMinWidth:
400 STORE vd->vd_ScaleMinWidth;
401 break;
403 case VIEW_ScaleMinHeight:
404 STORE vd->vd_ScaleMinHeight;
405 break;
407 case VIEW_ScaleWidth:
408 STORE vd->vd_ScaleWidth;
409 break;
411 case VIEW_ScaleHeight:
412 STORE vd->vd_ScaleHeight;
413 break;
415 case VIEW_X:
416 STORE vd->vd_X;
417 break;
419 case VIEW_Y:
420 STORE vd->vd_Y;
421 break;
423 case VIEW_AbsoluteX:
424 if (vd->vd_ParentView)
425 Get_Attr(vd->vd_ParentView, VIEW_AbsoluteX, store);
426 else
427 *store = 0;
428 *store += ((vd->vd_Flags & VDF_DIRECT) ? &bc->bc_OuterBox : &bc->bc_InnerBox)->Left - vd->vd_X;
429 break;
431 case VIEW_AbsoluteY:
432 if (vd->vd_ParentView)
433 Get_Attr(vd->vd_ParentView, VIEW_AbsoluteY, store);
434 else
435 *store = 0;
436 *store += ((vd->vd_Flags & VDF_DIRECT) ? &bc->bc_OuterBox : &bc->bc_InnerBox)->Top - vd->vd_Y;
437 break;
439 case VIEW_ObjectBuffer:
440 STORE vd->vd_ObjectBuffer;
441 break;
443 case BT_PostRenderHighestClass:
444 STORE cl;
445 break;
447 default:
448 rc = AsmDoSuperMethodA(cl, obj, (Msg)opg);
449 break;
451 return rc;
453 METHOD_END
455 /// ViewClassForward
457 * Forward a message to the object.
459 METHOD(ViewClassForward, Msg, msg)
461 VD *vd = INST_DATA(cl, obj);
462 ULONG rc = GMR_NOREUSE;
465 * Do we have an active member?
467 if (vd->vd_Object)
470 * Forward the message to the object.
472 rc = AsmDoMethodA(vd->vd_Object, msg);
475 * Take over the object's GadgetID.
477 GADGET(obj)->GadgetID = GADGET(vd->vd_Object)->GadgetID;
479 return rc;
481 METHOD_END
483 /// GM_RENDER
485 METHOD(ViewClassRender, struct gpRender *, gpr)
487 VD *vd = INST_DATA(cl, obj);
488 BC *bc = BASE_DATA(obj);
489 struct GadgetInfo *gi = gpr->gpr_GInfo;
490 struct RastPort *rp;
491 Object *o = vd->vd_Object, *vscroll, *hscroll;
492 ULONG rc = 0;
493 UWORD ow, oh, vw, vh, sw, sh;
494 struct Rectangle cr;
495 struct IBox *box;
497 DoSetMethodNG(bc->bc_Frame, FRM_OuterOffsetRight, vd->vd_ScrollerW,
498 FRM_OuterOffsetBottom, vd->vd_ScrollerH,
499 TAG_DONE);
502 * See if rendering is allowed.
504 if (!AsmDoSuperMethodA(cl, obj, (Msg)gpr))
505 return 0;
507 if (o && (rp = bc->bc_RPort))
509 if ((gpr->gpr_Redraw == GREDRAW_REDRAW) || !vd->vd_ObjectBuffer)
511 AsmDoMethod(o, GRM_DIMENSIONS, gi, rp, &vd->vd_CachedWidth, &vd->vd_CachedHeight, 0);
514 ow = ScaleWeight(vd->vd_CachedWidth, 100, vd->vd_ScaleWidth);
515 oh = ScaleWeight(vd->vd_CachedHeight, 100, vd->vd_ScaleHeight);
517 vscroll = vd->vd_VScroller;
518 hscroll = vd->vd_HScroller;
520 sw = vd->vd_ScrollerW;
521 sh = vd->vd_ScrollerH;
523 if ((ow < bc->bc_OuterBox.Width) && (oh < bc->bc_OuterBox.Height))
525 vd->vd_Flags |= VDF_DIRECT;
527 if (sw) vscroll = 0;
528 if (sh) hscroll = 0;
530 box = &bc->bc_OuterBox;
532 else
534 vd->vd_Flags &= ~VDF_DIRECT;
536 box = &bc->bc_InnerBox;
539 vw = box->Width;
540 vh = box->Height;
542 if (ow < vw) ow = vw;
543 if (oh < vh) oh = vh;
545 vd->vd_ObjectWidth = ow;
546 vd->vd_ObjectHeight = oh;
548 vd->vd_X = range(vd->vd_X, 0, ow - vw);
549 vd->vd_Y = range(vd->vd_Y, 0, oh - vh);
551 if (hscroll) DoSetMethodNG(hscroll, PGA_Top, vd->vd_X, PGA_Total, ow, PGA_Visible, vw, TAG_DONE);
552 if (vscroll) DoSetMethodNG(vscroll, PGA_Top, vd->vd_Y, PGA_Total, oh, PGA_Visible, vh, TAG_DONE);
554 DoSetMethodNG(o, GA_Left, 0, GA_Top, 0, GA_Width, ow, GA_Height, oh, TAG_DONE);
555 if ((gpr->gpr_Redraw == GREDRAW_REDRAW) || !vd->vd_ObjectBuffer)
557 if (vd->vd_ObjectBuffer) BGUI_FreeRPortBitMap(vd->vd_ObjectBuffer);
559 if (!(vd->vd_ObjectBuffer = BGUI_CreateRPortBitMap(rp, ow, oh, FGetDepth(rp))))
560 return 0;
562 AsmDoMethod(o, GM_RENDER, gi, vd->vd_ObjectBuffer, GREDRAW_REDRAW);
565 if (hscroll
566 && (!(vd->vd_Flags & VDF_DIRECT)
567 || !sw))
569 if (sw)
571 DoSetMethodNG(hscroll, GA_Left, bc->bc_OuterBox.Left,
572 GA_Top, bc->bc_OuterBox.Top + bc->bc_OuterBox.Height - sh,
573 GA_Width, bc->bc_OuterBox.Width - sw,
574 GA_Height, sh,
575 TAG_DONE);
577 AsmDoMethod(hscroll, GM_RENDER, gi, rp, gpr->gpr_Redraw);
579 if (vscroll
580 && (!(vd->vd_Flags & VDF_DIRECT)
581 || !sh))
583 if (sh)
585 DoSetMethodNG(vscroll, GA_Left, bc->bc_OuterBox.Left + bc->bc_OuterBox.Width - sw,
586 GA_Top, bc->bc_OuterBox.Top,
587 GA_Width, sw,
588 GA_Height, bc->bc_OuterBox.Height - sh,
589 TAG_DONE);
591 AsmDoMethod(vscroll, GM_RENDER, gi, rp, gpr->gpr_Redraw);
594 box = (vd->vd_Flags & VDF_DIRECT) ? &bc->bc_OuterBox : &bc->bc_InnerBox;
596 vd->vd_X = range(vd->vd_X, 0, vd->vd_ObjectWidth - box->Width);
597 vd->vd_Y = range(vd->vd_Y, 0, vd->vd_ObjectHeight - box->Height);
599 cr.MinX = box->Left;
600 cr.MinY = box->Top;
601 cr.MaxX = box->Left + box->Width - 1;
602 cr.MaxY = box->Top + box->Height - 1;
604 AsmDoMethod(obj, VIEW_CLIP, &cr, FALSE);
605 ClipBlit(vd->vd_ObjectBuffer, vd->vd_X, vd->vd_Y,
606 rp, cr.MinX, cr.MinY, cr.MaxX - cr.MinX + 1, cr.MaxY - cr.MinY + 1, 0xC0);
608 rc = 1;
610 BGUI_PostRender(cl, obj, gpr);
612 return rc;
614 METHOD_END
618 * Forward certain types of messages with modifications.
620 ULONG ForwardViewMsg(Class *cl, Object *s, Object *d, Msg msg)
622 VD *vd = INST_DATA(cl, s);
623 WORD *mouse = NULL;
624 ULONG rc, storage;
627 * Get address of mouse coordinates in message.
629 switch (msg->MethodID)
631 case GM_HITTEST:
632 case GM_HELPTEST:
633 mouse = (WORD *)&((struct gpHitTest *)msg)->gpht_Mouse;
634 break;
635 case GM_GOACTIVE:
636 case GM_HANDLEINPUT:
637 mouse = (WORD *)&((struct gpInput *)msg)->gpi_Mouse;
638 break;
640 if (!mouse) return 0;
643 * Store the coordinates.
645 storage = *(ULONG *)mouse;
648 * Adjust the coordinates to be relative to the destination object.
650 mouse[0] += vd->vd_X;
651 mouse[1] += vd->vd_Y;
654 * Send the message to the destination object.
656 rc = AsmDoMethodA(d, msg);
659 * Put the coordinates back to what they were originally.
661 *(ULONG *)mouse = storage;
663 return rc;
666 /// GM_HITTEST
668 * Forward a message to the object.
670 METHOD(ViewClassHitTest, struct gpHitTest *, gph)
672 VD *vd = INST_DATA(cl, obj);
673 BC *bc = BASE_DATA(obj);
674 ULONG rc = 0;
677 * Get absolute click position.
679 WORD l = GADGET(obj)->LeftEdge + gph->gpht_Mouse.X;
680 WORD t = GADGET(obj)->TopEdge + gph->gpht_Mouse.Y;
682 if (PointInBox(&bc->bc_InnerBox, l, t))
685 * Hit inside the view area?
687 rc = ForwardViewMsg(cl, obj, vd->vd_Object, (Msg)gph);
688 if (rc != GMR_GADGETHIT)
690 if (!(vd->vd_Flags & (VDF_NO_DRAGMOVE|VDF_DIRECT)))
692 vd->vd_Flags |= VDF_DRAGMOVE;
694 vd->vd_BX = vd->vd_X;
695 vd->vd_BY = vd->vd_Y;
696 vd->vd_LX = gph->gpht_Mouse.X;
697 vd->vd_LY = gph->gpht_Mouse.Y;
699 rc = GMR_GADGETHIT;
704 * Take over the object's GadgetID.
706 GADGET(obj)->GadgetID = GADGET(vd->vd_Object)->GadgetID;
709 if (!rc && vd->vd_VScroller)
712 * Route the message.
714 rc = ForwardMsg(obj, vd->vd_VScroller, (Msg)gph);
717 * Mark the scroller active.
719 if (rc == GMR_GADGETHIT) vd->vd_Flags |= VDF_VPROPACTIVE;
722 if (!rc && vd->vd_HScroller)
725 * Route the message.
727 rc = ForwardMsg(obj, vd->vd_HScroller, (Msg)gph);
730 * Mark the scroller active.
732 if (rc == GMR_GADGETHIT) vd->vd_Flags |= VDF_HPROPACTIVE;
734 return rc;
736 METHOD_END
738 /// GM_HANDLEINPUT
740 * Handle input.
742 METHOD(ViewClassHandleInput, struct gpInput *, gpi)
744 VD *vd = INST_DATA(cl, obj);
745 struct InputEvent *ie;
746 ULONG rc;
749 * Drag-moving?
751 if (vd->vd_Flags & VDF_DRAGMOVE)
753 ie = gpi->gpi_IEvent;
755 // qualifier stuff here return GMR_NOREUSE;
757 if (ie->ie_Class == IECLASS_RAWMOUSE)
759 if (ie->ie_Code == SELECTUP)
761 return GMR_NOREUSE;
763 if (ie->ie_Code == MENUDOWN)
765 DoSetMethod(obj, gpi->gpi_GInfo, VIEW_X, vd->vd_BX, VIEW_Y, vd->vd_BY, TAG_DONE);
767 return GMR_NOREUSE;
770 //if (ie->ie_Class == IECLASS_POINTERPOS)
772 DoSetMethod(obj, gpi->gpi_GInfo, VIEW_X, vd->vd_BX - gpi->gpi_Mouse.X + vd->vd_LX,
773 VIEW_Y, vd->vd_BY - gpi->gpi_Mouse.Y + vd->vd_LY, TAG_DONE);
776 return GMR_MEACTIVE;
780 * VScroller active?
782 if (vd->vd_Flags & VDF_VPROPACTIVE)
783 return ForwardMsg(obj, vd->vd_VScroller, (Msg)gpi) & ~GMR_VERIFY;
786 * HScroller active?
788 if (vd->vd_Flags & VDF_HPROPACTIVE)
789 return ForwardMsg(obj, vd->vd_HScroller, (Msg)gpi) & ~GMR_VERIFY;
791 if (vd->vd_Object)
794 * Route the message.
796 rc = ForwardViewMsg(cl, obj, vd->vd_Object, (Msg)gpi);
799 * Take over the object's GadgetID.
801 *(gpi->gpi_Termination) =
802 GADGET(obj)->GadgetID = GADGET(vd->vd_Object)->GadgetID;
804 return rc;
806 return 0;
808 METHOD_END
810 /// GM_GOINACTIVE
812 * Go inactive.
814 METHOD(ViewClassGoInactive, struct gpGoInactive *, gpgi)
816 VD *vd = INST_DATA(cl, obj);
817 ULONG rc = 0;
819 if (vd->vd_Flags & VDF_DRAGMOVE)
821 vd->vd_Flags &= ~VDF_DRAGMOVE;
822 return AsmDoSuperMethodA(cl, obj, (Msg)gpgi);
825 if (vd->vd_VScroller && (vd->vd_Flags & VDF_VPROPACTIVE))
828 * Mark the scroller as not active.
830 vd->vd_Flags &= ~VDF_VPROPACTIVE;
832 * If the scroller was active pass this message on for compatibility reasons.
834 return AsmDoMethodA(vd->vd_VScroller, (Msg)gpgi);
837 if (vd->vd_HScroller && (vd->vd_Flags & VDF_HPROPACTIVE))
840 * Mark the scroller as not active.
842 vd->vd_Flags &= ~VDF_HPROPACTIVE;
844 * If the scroller was active pass this message on for compatibility reasons.
846 return AsmDoMethodA(vd->vd_HScroller, (Msg)gpgi);
849 if (vd->vd_Object)
852 * Route the message.
854 rc = AsmDoMethodA(vd->vd_Object, (Msg)gpgi);
857 * Take over the object's GadgetID.
859 GADGET(obj)->GadgetID = GADGET(vd->vd_Object)->GadgetID;
861 return rc;
863 METHOD_END
865 /// GRM_WHICHOBJECT
867 * Get the object under the mouse.
869 METHOD(ViewClassWhichObject, struct grmWhichObject *, grwo)
871 VD *vd = INST_DATA(cl, obj);
872 BC *bc = BASE_DATA(obj);
873 Object *ob = vd->vd_Object;
874 struct grmWhichObject wo = *grwo;
876 int x = grwo->grwo_Coords.X;
877 int y = grwo->grwo_Coords.Y;
878 int r = bc->bc_OuterBox.Left + bc->bc_OuterBox.Width - vd->vd_ScrollerW;
879 int b = bc->bc_OuterBox.Top + bc->bc_OuterBox.Height - vd->vd_ScrollerH;
881 if ((x >= r) && (y >= b));
883 if (x >= r)
885 return (IPTR)vd->vd_VScroller;
887 if (y >= b)
889 return (IPTR)vd->vd_HScroller;
892 wo.MethodID = GRM_WHICHOBJECT;
893 wo.grwo_Coords.X = x + vd->vd_X;
894 wo.grwo_Coords.Y = y + vd->vd_Y;
897 * Is object a group?
899 if (IsMulti(ob))
902 * Route message.
904 ob = (Object *)AsmDoMethodA(ob, (Msg)&wo);
906 return (IPTR)ob;
908 METHOD_END
910 /// BASE_DIMENSIONS
912 * Simple dimensions request.
914 METHOD(ViewClassDimensions, struct bmDimensions *, bmd)
916 VD *vd = INST_DATA(cl, obj);
917 struct BaseInfo *bi = bmd->bmd_BInfo;
918 UWORD ow, oh;
919 ULONG mw, mh;
921 if (vd->vd_ScaleMinWidth || vd->vd_ScaleMinHeight)
923 AsmDoMethod(vd->vd_Object, GRM_DIMENSIONS, bi, bi->bi_RPort, &ow, &oh, 0);
926 if (vd->vd_ScaleMinWidth)
928 mw = ScaleWeight(ow, 100, vd->vd_ScaleMinWidth);
930 else
932 mw = vd->vd_MinWidth;
935 if (vd->vd_ScaleMinHeight)
937 mh = ScaleWeight(oh, 100, vd->vd_ScaleMinHeight);
939 else
941 mh = vd->vd_MinHeight;
944 if (mw < 8) mw = 8;
945 if (mh < 8) mh = 8;
948 * We simply add the specified minimum width and height
949 * which are passed to us at create time, plus the scrollers.
951 return CalcDimensions(cl, obj, bmd, mw + vd->vd_ScrollerW, mh + vd->vd_ScrollerH);
953 METHOD_END
955 /// VIEW_CLIP
957 METHOD(ViewClassClip, struct vmClip *, vmc)
959 VD *vd = INST_DATA(cl, obj);
960 BC *bc = BASE_DATA(obj);
961 struct IBox *box = (vd->vd_Flags & VDF_DIRECT) ? &bc->bc_OuterBox : &bc->bc_InnerBox;
963 int x1 = box->Left;
964 int y1 = box->Top;
965 int x2 = box->Width + x1 - 1;
966 int y2 = box->Height + y1 - 1;
968 if (vmc->vmc_Rectangle->MinX < x1) vmc->vmc_Rectangle->MinX = x1;
969 if (vmc->vmc_Rectangle->MaxX > x2) vmc->vmc_Rectangle->MaxX = x2;
970 if (vmc->vmc_Rectangle->MinY < y1) vmc->vmc_Rectangle->MinY = y1;
971 if (vmc->vmc_Rectangle->MaxY > y2) vmc->vmc_Rectangle->MaxY = y2;
973 if (vmc->vmc_WindowClip
974 && vd->vd_ParentView)
975 AsmDoMethodA(vd->vd_ParentView, (Msg)vmc);
977 return 1;
979 METHOD_END
981 /// BASE_IS_MULTI
982 METHOD(ViewClassIsMulti, Msg, msg)
984 return TRUE;
986 METHOD_END
988 /// Class initialization.
990 * Class function table.
992 STATIC DPFUNC ClassFunc[] = {
993 { VIEW_CLIP, ViewClassClip, },
994 { OM_NEW, ViewClassNew, },
995 { OM_GET, ViewClassGet, },
996 { OM_SET, ViewClassSet, },
997 { OM_UPDATE, ViewClassSet, },
998 { OM_DISPOSE, ViewClassDispose, },
999 { GM_RENDER, ViewClassRender, },
1000 { BASE_DIMENSIONS, ViewClassDimensions, },
1001 { GRM_WHICHOBJECT, ViewClassWhichObject, },
1002 { GM_HITTEST, ViewClassHitTest, },
1003 { GM_GOACTIVE, ViewClassHandleInput, },
1004 { GM_HANDLEINPUT, ViewClassHandleInput, },
1005 { GM_GOINACTIVE, ViewClassGoInactive, },
1006 { BASE_MOVEBOUNDS, ViewClassForward, },
1007 { BASE_LOCALIZE, ViewClassForward, },
1008 { BASE_KEYLABEL, ViewClassForward, },
1009 { BASE_FINDKEY, ViewClassForward, },
1010 { BASE_SHOWHELP, ViewClassForward, },
1011 { BASE_INHIBIT, ViewClassForward, },
1012 { BASE_IS_MULTI, ViewClassIsMulti, },
1013 { DF_END },
1017 * Simple class initialization.
1019 makeproto Class *InitViewClass(void)
1021 return BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_BASE_GADGET,
1022 CLASS_ObjectSize, sizeof(VD),
1023 CLASS_DFTable, ClassFunc,
1024 TAG_DONE);