# Correct the needed linklibs in curl-config also.
[AROS-Contrib.git] / bgui / propclass.c
blob7924cf6207a9fae8c6c5a126e6fdc99cc6e96a91
1 /*
2 * @(#) $Header$
4 * BGUI library
5 * propclass.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.4 2004/06/16 20:16:48 verhaegs
15 * Use METHODPROTO, METHOD_END and REGFUNCPROTOn where needed.
17 * Revision 42.3 2000/08/17 15:09:18 chodorowski
18 * Fixed compiler warnings.
20 * Revision 42.2 2000/05/15 19:27:02 stegerg
21 * another hundreds of REG() macro replacements in func headers/protos.
23 * Revision 42.1 2000/05/14 23:32:48 stegerg
24 * changed over 200 function headers which all use register
25 * parameters (oh boy ...), because the simple REG() macro
26 * doesn't work with AROS. And there are still hundreds
27 * of headers left to be fixed :(
29 * Many of these functions would also work with stack
30 * params, but since i have fixed every single one
31 * I encountered up to now, I guess will have to do
32 * the same for the rest.
34 * Revision 42.0 2000/05/09 22:09:56 mlemos
35 * Bumped to revision 42.0 before handing BGUI to AROS team
37 * Revision 41.11 2000/05/09 19:54:55 mlemos
38 * Merged with the branch Manuel_Lemos_fixes.
40 * Revision 41.10.2.5 2000/01/30 20:41:12 mlemos
41 * Fixed bug of not adding the arrows size to the minimum and nominal
42 * dimensions of the gadget.
44 * Revision 41.10.2.4 1998/12/06 21:40:53 mlemos
45 * Ensured that when the parent view and window are passed to the arrow
46 * gadgets on their creation.
48 * Revision 41.10.2.3 1998/11/13 18:21:53 mlemos
49 * Reverted the workaround patch that set the screen pointer in the BaseInfo
50 * structure as the real problem was fixed AllocBaseInfo function.
52 * Revision 41.10.2.2 1998/11/03 10:45:28 mlemos
53 * Added workaround to avoid enforcer hits cause by ROM propclass looking at
54 * the GadgetInfo Screen pointer inside GM_RENDER method.
56 * Revision 41.10.2.1 1998/10/01 04:38:52 mlemos
57 * Fixed bug of sending interim notifications after adjusting the knob.
59 * Revision 41.10 1998/02/25 21:12:53 mlemos
60 * Bumping to 41.10
62 * Revision 1.1 1998/02/25 17:09:29 mlemos
63 * Ian sources
68 /// Class definitions.
70 #include "include/classdefs.h"
73 * Object instance data.
75 typedef struct {
76 ULONG pd_Flags; /* see below */
77 Object *pd_Prop; /* prop gadget object */
78 Object *pd_Knob; /* prop gadget knob */
79 Object *pd_Arrow1; /* up/left arrow */
80 Object *pd_Arrow2; /* down/right arrow */
81 LONG pd_Top; /* prop to position */
82 LONG pd_Total; /* prop total range */
83 LONG pd_Visible; /* prop visible portion */
84 LONG pd_Min; /* minimum level */
85 LONG pd_Max; /* maximum level */
86 LONG pd_Level; /* current level */
87 LONG pd_Reset1; /* Initial top value */
88 LONG pd_Reset2; /* Initial top level */
89 UWORD pd_ArrowSize; /* size of arrows */
90 UWORD pd_RptTicks; /* repeat treshold */
91 } PD;
93 #define PDF_ARROWS (1<<0) /* prop has arrows */
94 #define PDF_NEWLOOK (1<<1) /* prop must be "NewLook" */
95 #define PDF_PROPHORIZ (1<<2) /* prop moves horizontally */
96 #define PDF_PROPACTIVE (1<<3) /* prop is active */
97 #define PDF_LEFT_UP (1<<4) /* left/up gadget active */
98 #define PDF_RIGHT_DOWN (1<<5) /* right/down active */
99 #define PDF_RESET (1<<6) /* Reset to pd_Initial */
100 #define PDF_SLIDER (1<<7) /* Slider mode. */
101 #define PDF_READY (1<<8) /* Created and ready. */
106 * Calculate arrow and prop positions.
108 STATIC VOID CalcPropMuck(Class *cl, Object *obj, struct BaseInfo *bi)
110 PD *pd = INST_DATA(cl, obj);
111 BC *bc = BASE_DATA(obj);
112 int size = pd->pd_ArrowSize;
113 ULONG kw, kh;
114 struct IBox arrow1, arrow2;
117 * Check for arrows and where they are placed.
119 if (pd->pd_Flags & PDF_ARROWS)
122 * Copy the hitbox to the destinations
124 arrow1 = arrow2 = bc->bc_HitBox;
127 * FREEHORIZ will get the arrows
128 * on the right side. FREEVERT will
129 * get them below.
131 if (pd->pd_Flags & PDF_PROPHORIZ)
133 arrow1.Left += bc->bc_HitBox.Width;
134 arrow2.Left = arrow1.Left + size;
135 arrow1.Width = arrow2.Width = size;
137 else
139 arrow1.Top += bc->bc_HitBox.Height;
140 arrow2.Top = arrow1.Top + size;
141 arrow1.Height = arrow2.Height = size;
143 SetGadgetBounds(pd->pd_Arrow1, &arrow1);
144 SetGadgetBounds(pd->pd_Arrow2, &arrow2);
148 * Setup the slider.
151 if (pd->pd_Flags & PDF_SLIDER)
153 if (pd->pd_Flags & PDF_PROPHORIZ) pd->pd_Top = pd->pd_Level - pd->pd_Min;
154 else pd->pd_Top = pd->pd_Max - pd->pd_Level;
158 * Set it up.
160 DoSetMethodNG(pd->pd_Prop, GA_Left, bc->bc_InnerBox.Left, GA_Top, bc->bc_InnerBox.Top,
161 GA_Width, bc->bc_InnerBox.Width, GA_Height, bc->bc_InnerBox.Height,
162 PGA_Top, pd->pd_Top, PGA_Total, pd->pd_Total,
163 PGA_Visible, pd->pd_Visible, TAG_DONE);
165 if (pd->pd_Knob)
167 kw = bc->bc_InnerBox.Width;
168 kh = bc->bc_InnerBox.Height;
170 if ((pd->pd_Total > 0) && (pd->pd_Total > pd->pd_Visible))
172 if (pd->pd_Flags & PDF_PROPHORIZ)
174 kw = (kw * (ULONG)pd->pd_Visible) / pd->pd_Total;
175 if (kw < 4) kw = 4;
177 else
179 kh = (kh * (ULONG)pd->pd_Visible) / pd->pd_Total;
180 if (kh < 4) kh = 4;
183 DoSetMethodNG(pd->pd_Knob, IA_Width, kw, IA_Height, kh, TAG_DONE);
187 /// OM_NEW
189 * Create a shiny new object.
191 METHOD(PropClassNew, struct opSet *, ops)
193 PD *pd;
194 BC *bc;
195 struct TagItem *tags;
196 IPTR rc;
197 BOOL horiz;
199 tags = DefTagList(BGUI_PROP_GADGET, ops->ops_AttrList);
202 * First we let the superclass get us an object.
204 if ((rc = NewSuperObject(cl, obj, tags)))
207 * Obtain instance data.
209 pd = INST_DATA(cl, rc);
210 bc = BASE_DATA(rc);
212 if (!bc->bc_Frame) goto failure;
215 * Make sure we are GACT_RELVERIFY.
217 GADGET(rc)->Activation |= GACT_RELVERIFY;
220 * Setup defaults.
222 pd->pd_Visible = 1;
223 pd->pd_Total = 1;
224 pd->pd_Flags = GetTagData(PGA_Slider, FALSE, tags) ? PDF_SLIDER|PDF_PROPHORIZ : PDF_ARROWS;
225 pd->pd_Max = 15;
227 AsmCoerceMethod(cl, (Object *)rc, OM_SET, tags, NULL);
229 horiz = pd->pd_Flags & PDF_PROPHORIZ;
232 * Arrows?
234 if (pd->pd_Flags & PDF_ARROWS)
236 pd->pd_Arrow1 = BGUI_NewObject(BGUI_BUTTON_GADGET,
237 VIT_BuiltIn, horiz ? BUILTIN_ARROW_LEFT : BUILTIN_ARROW_UP,
238 BT_ParentView,bc->bc_View,
239 BT_ParentWindow,bc->bc_Window,
240 TAG_DONE);
242 pd->pd_Arrow2 = BGUI_NewObject(BGUI_BUTTON_GADGET,
243 VIT_BuiltIn, horiz ? BUILTIN_ARROW_RIGHT : BUILTIN_ARROW_DOWN,
244 BT_ParentView,bc->bc_View,
245 BT_ParentWindow,bc->bc_Window,
246 TAG_DONE);
248 if (!(pd->pd_Arrow1 && pd->pd_Arrow2)) goto failure;
251 if ((pd->pd_Prop = NewObject(NULL, PropGClass,
252 GA_RelVerify, TRUE,
253 PGA_Borderless, TRUE,
254 PGA_Freedom, horiz ? FREEHORIZ : FREEVERT,
255 TAG_MORE, tags)))
258 pd->pd_Knob = BGUI_NewObject(BGUI_FRAME_IMAGE,
259 FRM_Type, FRTYPE_FUZZ_RIDGE,
260 //FRM_FrameWidth, 2,
261 //FRM_FrameHeight, 2,
262 FRM_ThinFrame, TRUE,
263 FRM_BackFill, SHINE_RASTER,
264 IMAGE_InBorder, GADGET(rc)->Activation & BORDERMASK,
265 TAG_END);
270 * No disabled.
272 DoSetMethodNG(pd->pd_Prop, GA_Disabled, FALSE, TAG_END);
274 if (pd->pd_Knob)
276 DoSetMethodNG(pd->pd_Prop, GA_Image, pd->pd_Knob, GA_SelectRender, pd->pd_Knob, TAG_DONE);
280 * We target the IDCMP port (when allowed).
282 if (!GetTagData(PGA_DontTarget, FALSE, tags))
283 DoSuperSetMethodNG(cl, (Object *)rc, ICA_TARGET, ICTARGET_IDCMP, TAG_END);
285 pd->pd_Flags |= PDF_READY;
288 * So far, so good....
290 FreeTagItems(tags);
291 return rc;
293 failure:
295 * Shit! Something screwed up...
297 AsmCoerceMethod(cl, (Object *)rc, OM_DISPOSE);
299 FreeTagItems(tags);
300 return 0;
302 METHOD_END
304 /// OM_SET, OM_UPDATE
306 * Change some attributes.
308 METHOD(PropClassSetUpdate, struct opUpdate *, opu)
310 PD *pd = INST_DATA(cl, obj);
311 BC *bc = BASE_DATA(obj);
312 struct TagItem *tstate = opu->opu_AttrList;
313 struct TagItem *tag;
314 ULONG type, redraw = 0, ho, vo;
315 LONG tmp, val, omin = 0, omax = 0, olev = 0, oldtop = 0, oldtot = 0, oldvis = 0;
316 BOOL fc = !(pd->pd_Flags & PDF_READY);
317 WORD dis = GADGET(obj)->Flags & GFLG_DISABLED;
318 IPTR data;
321 * First we let the superclass do it's thing.
323 AsmDoSuperMethodA(cl, obj, (Msg)opu);
326 * Make sure we stay GACT_RELVERIFY.
328 GADGET(obj)->Activation |= GACT_RELVERIFY;
330 if (pd->pd_Flags & PDF_SLIDER)
332 omin = pd->pd_Min;
333 omax = pd->pd_Max;
334 olev = pd->pd_Level;
336 else
338 oldtop = pd->pd_Top;
339 oldtot = pd->pd_Total;
340 oldvis = pd->pd_Visible;
344 * Let's see if we need to change
345 * some known attributes ourselves.
347 while ((tag = NextTagItem(&tstate)))
349 data = tag->ti_Data;
350 switch (tag->ti_Tag)
352 case PGA_Top:
353 pd->pd_Top = data;
354 break;
356 case PGA_Total:
357 pd->pd_Total = data;
358 break;
360 case PGA_Visible:
361 pd->pd_Visible = data;
362 break;
364 case PGA_Freedom:
365 if (data == FREEHORIZ) pd->pd_Flags |= PDF_PROPHORIZ;
366 else pd->pd_Flags &= ~PDF_PROPHORIZ;
367 break;
369 case PGA_Arrows:
370 if (data) pd->pd_Flags |= PDF_ARROWS;
371 else pd->pd_Flags &= ~PDF_ARROWS;
372 break;
374 case PGA_ArrowSize:
375 pd->pd_ArrowSize = data;
376 break;
378 case SLIDER_Level:
379 pd->pd_Level = data;
380 break;
382 case SLIDER_Min:
383 pd->pd_Min = data;
384 break;
386 case SLIDER_Max:
387 pd->pd_Max = data;
388 break;
390 case PGA_XenFrame:
391 if (data) data = FRTYPE_XEN_BUTTON;
392 else data = FRTYPE_BUTTON;
393 goto set_frametype;
395 case PGA_NoFrame:
396 case SLIDER_NoFrame:
397 if (data) data = FRTYPE_NONE;
398 else data = FRTYPE_BUTTON;
400 case FRM_Type:
401 set_frametype:
402 DoMultiSet(FRM_Type, data, 3, bc->bc_Frame, pd->pd_Arrow1, pd->pd_Arrow2);
403 fc = TRUE;
404 break;
406 case PGA_ThinFrame:
407 case SLIDER_ThinFrame:
408 case FRM_ThinFrame:
409 DoMultiSet(FRM_ThinFrame, data, 3, bc->bc_Frame, pd->pd_Arrow1, pd->pd_Arrow2);
410 fc = TRUE;
411 break;
413 case GA_TopBorder:
414 case GA_BottomBorder:
415 case GA_LeftBorder:
416 case GA_RightBorder:
417 DoMultiSet(tag->ti_Tag, data, 4, pd->pd_Arrow1, pd->pd_Arrow2, pd->pd_Knob, pd->pd_Prop);
419 if (data)
421 DoSetMethodNG(bc->bc_Frame, FRM_Type, FRTYPE_BORDER, FRM_EdgesOnly, TRUE, TAG_DONE);
423 DoSetMethodNG(pd->pd_Arrow1, BT_FrameObject, NULL,
424 SYSIA_Which, (pd->pd_Flags & PDF_PROPHORIZ) ? LEFTIMAGE : UPIMAGE, TAG_DONE);
426 DoSetMethodNG(pd->pd_Arrow2, BT_FrameObject, NULL,
427 SYSIA_Which, (pd->pd_Flags & PDF_PROPHORIZ) ? RIGHTIMAGE : DOWNIMAGE, TAG_DONE);
429 fc = TRUE;
430 break;
432 case BT_ParentWindow:
433 case BT_ParentView:
434 DoMultiSet(tag->ti_Tag, data, 3, pd->pd_Arrow1, pd->pd_Arrow2, pd->pd_Knob);
435 break;
439 if (pd->pd_Flags & PDF_SLIDER)
442 * Stupidity tests.
444 if (pd->pd_Min > pd->pd_Max)
446 tmp = pd->pd_Min;
447 pd->pd_Min = pd->pd_Max;
448 pd->pd_Max = tmp;
452 * Calculate the absolute difference between min and max.
454 pd->pd_Total = pd->pd_Max - pd->pd_Min + 1;
455 pd->pd_Visible = 1;
457 val = pd->pd_Level;
459 else
461 pd->pd_Min = 0;
462 pd->pd_Max = max(pd->pd_Total - pd->pd_Visible, 0);
464 val = pd->pd_Top;
467 if (val < pd->pd_Min) val = pd->pd_Min;
468 else if (val > pd->pd_Max) val = pd->pd_Max;
470 if (pd->pd_Flags & PDF_SLIDER)
472 pd->pd_Level = val;
475 * Check if any of these values changed.
477 if ((pd->pd_Min != omin) || (pd->pd_Max != omax) || (pd->pd_Level != olev))
478 redraw = GREDRAW_UPDATE;
480 else
482 pd->pd_Top = val;
485 * Check if any of these values changed.
487 if ((pd->pd_Top != oldtop) || (pd->pd_Total != oldtot) || (pd->pd_Visible != oldvis))
488 redraw = GREDRAW_UPDATE;
491 if (fc)
493 Get_Attr(bc->bc_Frame, FRM_Type, &data);
494 switch (data)
496 case FRTYPE_NONE:
497 ho = vo = 0;
498 case FRTYPE_BORDER:
499 if (GADGET(obj)->Activation & (GACT_LEFTBORDER|GACT_RIGHTBORDER)) { ho = 4; vo = 1; };
500 if (GADGET(obj)->Activation & (GACT_TOPBORDER|GACT_BOTTOMBORDER)) { ho = 2; vo = 2; };
501 DoSetMethodNG(bc->bc_Frame, FRM_Type, FRTYPE_NONE, TAG_DONE);
502 break;
503 default:
504 Get_Attr(bc->bc_Frame, FRM_ThinFrame, &data);
505 vo = 1;
506 ho = data ? 1 : 2;
507 break;
509 DoSuperSetMethodNG(cl, obj, BT_LeftOffset, ho, BT_RightOffset, ho,
510 BT_TopOffset, vo, BT_BottomOffset, vo, TAG_DONE);
512 redraw = GREDRAW_REDRAW;
516 if (pd->pd_Flags & PDF_READY)
519 * Disable state changed?
521 if ((GADGET(obj)->Flags & GFLG_DISABLED) != dis)
522 redraw = GREDRAW_REDRAW;
525 * Re-render the gadget.
527 if (redraw) DoRenderMethod(obj, opu->opu_GInfo, redraw);
530 * Notify our target if the
531 * top value changed.
533 if (pd->pd_Flags & PDF_SLIDER)
535 type = (pd->pd_Level != olev) ? SLIDER_Level : 0;
537 else
539 type = (pd->pd_Top != oldtop) ? PGA_Top : 0;
542 if (type) DoNotifyMethod(obj, opu->opu_GInfo, opu->MethodID == OM_UPDATE ? opu->opu_Flags : 0,
543 GA_ID, GADGET(obj)->GadgetID, type, val, TAG_DONE);
545 return 1;
547 METHOD_END
549 /// BASE_RENDER
551 * Render the gadget.
553 METHOD(PropClassRender, struct bmRender *, bmr)
555 PD *pd = INST_DATA(cl, obj);
556 BC *bc = BASE_DATA(obj);
557 struct BaseInfo *bi = bmr->bmr_BInfo;
558 struct RastPort *rp = bi->bi_RPort;
561 * Render the baseclass.
563 AsmDoSuperMethodA(cl, obj, (Msg)bmr);
566 * Setup the object.
568 CalcPropMuck(cl, obj, bi);
571 * Complete re-render?
573 if (bmr->bmr_Flags == GREDRAW_REDRAW)
576 * Render the arrow images.
578 if (pd->pd_Flags & PDF_ARROWS)
580 AsmDoMethod(pd->pd_Arrow1, GM_RENDER, bi, rp, GREDRAW_REDRAW);
581 AsmDoMethod(pd->pd_Arrow2, GM_RENDER, bi, rp, GREDRAW_REDRAW);
585 * Then the slider body.
587 AsmDoMethod(pd->pd_Prop, GM_RENDER, bi, rp, GREDRAW_REDRAW);
589 else
592 * Any arrow active?
594 if (pd->pd_Flags & PDF_LEFT_UP)
595 AsmDoMethod(pd->pd_Arrow1, GM_RENDER, bi, rp, GREDRAW_REDRAW);
596 else if (pd->pd_Flags & PDF_RIGHT_DOWN)
597 AsmDoMethod(pd->pd_Arrow2, GM_RENDER, bi, rp, GREDRAW_REDRAW);
600 * Only re-render the slider when it isn't active.
602 if (!(pd->pd_Flags & PDF_PROPACTIVE))
603 AsmDoMethod(pd->pd_Prop, GM_RENDER, bi, rp, GREDRAW_UPDATE);
607 * Ghost the gadget hitbox when it is disabled.
609 if (GADGET(obj)->Flags & GFLG_DISABLED)
611 BDisableBox(bi, &bc->bc_HitBox);
612 if (pd->pd_Arrow1) BDisableBox(bi, GADGETBOX(pd->pd_Arrow1));
613 if (pd->pd_Arrow2) BDisableBox(bi, GADGETBOX(pd->pd_Arrow2));
615 return 1;
617 METHOD_END
619 /// OM_GET
621 * They want to know something.
623 METHOD(PropClassGet, struct opGet *, opg)
625 PD *pd = INST_DATA(cl, obj);
626 ULONG rc = 1;
627 IPTR *store = opg->opg_Storage;
629 switch (opg->opg_AttrID)
631 case PGA_Freedom:
632 STORE (pd->pd_Flags & PDF_PROPHORIZ) ? FREEHORIZ : FREEVERT;
633 break;
635 case PGA_Top:
636 STORE pd->pd_Top;
637 break;
639 case SLIDER_Level:
640 STORE pd->pd_Level;
641 break;
643 case SLIDER_Min:
644 STORE pd->pd_Min;
645 break;
647 case SLIDER_Max:
648 STORE pd->pd_Max;
649 break;
651 default:
652 rc = AsmDoSuperMethodA(cl, obj, (Msg)opg);
653 break;
655 return rc;
657 METHOD_END
659 /// GM_HITTEST
661 * Where we hit and if so, what was hit.
663 METHOD(PropClassHitTest, struct gpHitTest *, gph)
665 PD *pd = INST_DATA(cl, obj);
666 BC *bc = BASE_DATA(obj);
667 ULONG rc = 0;
670 * Calculate absolute click position.
672 WORD l = GADGETBOX(obj)->Left + gph->gpht_Mouse.X;
673 WORD t = GADGETBOX(obj)->Top + gph->gpht_Mouse.Y;
675 if (PointInBox(&bc->bc_HitBox, l, t))
678 * Did they click inside the
679 * proportional gadget?
681 rc = ForwardMsg(obj, pd->pd_Prop, (Msg)gph);
683 if (rc == GMR_GADGETHIT) pd->pd_Flags |= PDF_PROPACTIVE;
686 if (!rc && pd->pd_Arrow1)
689 * Clicked in the left/up arrow?
691 rc = ForwardMsg(obj, pd->pd_Arrow1, (Msg)gph);
693 if (rc == GMR_GADGETHIT) pd->pd_Flags |= PDF_LEFT_UP;
696 if (!rc && pd->pd_Arrow2)
699 * Clicked in the down/right arrow?
701 rc = ForwardMsg(obj, pd->pd_Arrow2, (Msg)gph);
703 if (rc == GMR_GADGETHIT) pd->pd_Flags |= PDF_RIGHT_DOWN;
706 if (rc == GMR_GADGETHIT)
708 pd->pd_Reset1 = pd->pd_Top;
709 pd->pd_Reset2 = pd->pd_Level;
711 return rc;
713 METHOD_END
716 STATIC ASM VOID NotifyChange(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct gpInput *gpi, REG(d0) ULONG flags)
718 PD *pd = INST_DATA(cl, obj);
719 ULONG type;
720 LONG val, oldval = (pd->pd_Flags & PDF_SLIDER) ? pd->pd_Level : pd->pd_Top;
721 IPTR tmp;
724 * Obtain top-value.
726 Get_Attr(pd->pd_Prop, PGA_Top, &tmp);
727 val = (LONG)tmp;
729 if (pd->pd_Flags & PDF_SLIDER)
732 * Make it a level.
734 if (pd->pd_Flags & PDF_PROPHORIZ) val = pd->pd_Min + val;
735 else val = pd->pd_Max - val;
737 pd->pd_Level = val;
738 type = SLIDER_Level;
740 else
742 pd->pd_Top = val;
743 type = PGA_Top;
747 * Notify.
749 if ((flags == OPUF_INTERIM) && (val == oldval)) return;
751 DoNotifyMethod(obj, gpi->gpi_GInfo, flags, GA_ID, GADGET(obj)->GadgetID, type, val, TAG_DONE);
755 * Adjust knob position in
756 * whatever direction necessary.
758 STATIC ASM VOID AdjustKnob(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) struct gpInput *gpi)
760 PD *pd = INST_DATA(cl, obj);
761 LONG top, total = max(pd->pd_Total - pd->pd_Visible, 0);
762 IPTR tmp;
764 Get_Attr(pd->pd_Prop, PGA_Top, &tmp);
765 top = (LONG)tmp;
767 if (pd->pd_Flags & PDF_LEFT_UP)
769 top--;
771 else if (pd->pd_Flags & PDF_RIGHT_DOWN)
773 top++;
776 if ((top >= 0) && (top <= total))
778 DoSetMethod(pd->pd_Prop, gpi->gpi_GInfo, PGA_Top, top, TAG_DONE);
779 NotifyChange(cl, obj, gpi, 0L);
783 /// GM_GOACTIVE
785 METHOD(PropClassGoActive, struct gpInput *, gpi)
787 PD *pd = INST_DATA(cl, obj);
788 Object *arrow;
789 ULONG rc = GMR_NOREUSE;
792 * We do not go active when we are disabled or was activated
793 * by Activate gadget.
795 if ((GADGET(obj)->Flags & GFLG_DISABLED) || (!gpi->gpi_IEvent))
797 pd->pd_Flags &= ~(PDF_PROPACTIVE|PDF_LEFT_UP|PDF_RIGHT_DOWN);
798 return rc;
802 * Let the superclass have a go...
804 AsmDoSuperMethodA(cl, obj, (Msg)gpi);
807 * Is the proportional gadget active?
809 if (pd->pd_Flags & PDF_PROPACTIVE)
812 * If so adjust the click
813 * coordinates and route the
814 * message to the proportional gadget.
816 rc = ForwardMsg(obj, pd->pd_Prop, (Msg)gpi);
818 if (rc & GMR_VERIFY) NotifyChange(cl, obj, gpi, 0);
820 else if (pd->pd_Flags & (PDF_LEFT_UP|PDF_RIGHT_DOWN))
823 * Clear timer threshold.
825 pd->pd_RptTicks = 0;
828 * Adjust knob and notify when the knob position changed.
830 AdjustKnob(cl, obj, gpi);
833 * Route the message to the button gadget.
835 arrow = (pd->pd_Flags & PDF_LEFT_UP) ? pd->pd_Arrow1 : pd->pd_Arrow2;
836 rc = ForwardMsg(obj, arrow, (Msg)gpi);
838 return rc;
840 METHOD_END
842 /// GM_HANDLEINPUT
844 * Handle user input.
846 METHOD(PropClassHandleInput, struct gpInput *, gpi)
848 PD *pd = INST_DATA(cl, obj);
849 Object *arrow;
850 WORD l, t, sel = 0;
851 ULONG rc = GMR_MEACTIVE;
854 * Calculate absolute click position.
856 l = GADGETBOX(obj)->Left + gpi->gpi_Mouse.X;
857 t = GADGETBOX(obj)->Top + gpi->gpi_Mouse.Y;
860 * Is the proportional gadget active?
862 if (pd->pd_Flags & PDF_PROPACTIVE)
865 * Right mouse button pressed?
867 if (gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE && gpi->gpi_IEvent->ie_Code == MENUDOWN)
870 * Yep. Say we need to reset to
871 * the initial value.
873 pd->pd_Flags |= PDF_RESET;
874 return GMR_NOREUSE;
877 * If so adjust the click
878 * coordinates and rout the
879 * message to the proportional gadget.
881 rc = ForwardMsg(obj, pd->pd_Prop, (Msg)gpi);
883 NotifyChange(cl, obj, gpi, (rc == GMR_MEACTIVE) ? OPUF_INTERIM : 0);
885 else
887 arrow = (pd->pd_Flags & PDF_LEFT_UP) ? pd->pd_Arrow1 : pd->pd_Arrow2;
890 * Check if the mouse is
891 * still over the active arrow.
893 if (PointInBox(GADGETBOX(arrow), l, t))
894 sel = GFLG_SELECTED;
897 * Evaluate input.
899 if (gpi->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
901 switch (gpi->gpi_IEvent->ie_Code)
903 case SELECTUP:
905 * They released the left
906 * mouse button.
908 rc = GMR_NOREUSE | GMR_VERIFY;
911 * Unselect the arrow.
913 sel = 0;
914 break;
916 case MENUDOWN:
918 * Terminate when they press the menubutton.
920 sel = 0;
921 pd->pd_Flags |= PDF_RESET;
922 rc = GMR_NOREUSE;
923 break;
926 else if (gpi->gpi_IEvent->ie_Class == IECLASS_TIMER)
929 * On every timer event we
930 * increase or decrease the knob
931 * position.
933 if (sel)
936 * We delay with adjusting the knob position for a little while just
937 * like the key-repeat threshold. Probably should use the system prefs
938 * for determing the delay but this is _so_ much easier.
940 if (pd->pd_RptTicks > 3)
943 * Adjust knob and notify when the knob position changed.
945 AdjustKnob(cl, obj, gpi);
947 else
950 * Increase repeat treshold.
952 pd->pd_RptTicks++;
958 * When the selected state
959 * changed show it visually.
961 if ((GADGET(arrow)->Flags & GFLG_SELECTED) != sel)
964 * Flip selected bit and re-render.
966 GADGET(arrow)->Flags ^= GFLG_SELECTED;
967 DoRenderMethod(arrow, gpi->gpi_GInfo, GREDRAW_REDRAW);
970 return rc;
972 METHOD_END
974 /// GM_GOINACTIVE
976 * Abort activity.
978 METHOD(PropClassGoInActive, struct gpGoInactive *, ggi)
980 PD *pd = INST_DATA(cl, obj);
981 ULONG rc;
984 * Is the proportional gadget
985 * active?
987 if (pd->pd_Flags & PDF_PROPACTIVE)
990 * If so route the message to
991 * the proportional gadget and
992 * mark it as not active.
994 AsmDoMethodA(pd->pd_Prop, (Msg)ggi);
998 * Un-activate our arrows and let the super
999 * class see what it can do with this message.
1001 pd->pd_Flags &= ~(PDF_LEFT_UP|PDF_RIGHT_DOWN|PDF_PROPACTIVE);
1002 rc = AsmDoSuperMethodA(cl, obj, (Msg)ggi);
1005 * Reset to the initial value when necessary.
1007 if (pd->pd_Flags & PDF_RESET)
1009 DoSetMethod(obj, ggi->gpgi_GInfo, PGA_Top, pd->pd_Reset1, SLIDER_Level, pd->pd_Reset2, TAG_DONE);
1010 pd->pd_Flags &= ~PDF_RESET;
1012 return rc;
1014 METHOD_END
1016 /// BASE_DIMENSIONS
1018 * Find out our minumum size.
1020 METHOD(PropClassDimensions, struct bmDimensions *, bmd)
1022 PD *pd = INST_DATA(cl, obj);
1023 BC *bc = BASE_DATA(obj);
1024 BOOL vborder = GADGET(obj)->Activation & (GACT_LEFTBORDER|GACT_RIGHTBORDER);
1025 BOOL hborder = GADGET(obj)->Activation & (GACT_TOPBORDER|GACT_BOTTOMBORDER);
1026 BOOL horiz = pd->pd_Flags & PDF_PROPHORIZ;
1027 int arrowsize = pd->pd_ArrowSize;
1028 ULONG rc;
1030 if (pd->pd_Flags & PDF_ARROWS)
1032 if (!arrowsize)
1034 if (vborder) arrowsize = 11;
1035 else if (hborder) arrowsize = 16;
1036 else arrowsize = horiz ? 10 : 9;
1038 pd->pd_ArrowSize = arrowsize;
1040 DoSetMethodNG(bc->bc_Frame, horiz ? FRM_OuterOffsetRight : FRM_OuterOffsetBottom, arrowsize << 1, TAG_DONE);
1044 * Add these to the superclass results.
1046 rc = CalcDimensions(cl, obj, bmd, 8+(horiz ? arrowsize*2 : 0), 8+(horiz ? 0 : arrowsize*2 ));
1048 if (vborder) bmd->bmd_Extent->be_Min.Width = bmd->bmd_Extent->be_Nom.Width = 18;
1049 if (hborder) bmd->bmd_Extent->be_Min.Height = bmd->bmd_Extent->be_Nom.Height = 10;
1051 return rc;
1053 METHOD_END
1055 /// OM_DISPOSE
1057 * Dispose of ourselves.
1059 METHOD(PropClassDispose, Msg, msg)
1061 PD *pd = INST_DATA(cl, obj);
1064 * Dispose of the allocated objects.
1066 if (pd->pd_Arrow1) DisposeObject(pd->pd_Arrow1);
1067 if (pd->pd_Arrow2) DisposeObject(pd->pd_Arrow2);
1068 if (pd->pd_Prop ) DisposeObject(pd->pd_Prop);
1069 if (pd->pd_Knob ) DisposeObject(pd->pd_Knob);
1071 return AsmDoSuperMethodA(cl, obj, msg);
1073 METHOD_END
1075 /// WM_KEYACTIVE
1077 * We are activated by the keyboard.
1079 METHOD(PropClassKeyActive, struct wmKeyInput *, wmki)
1081 PD *pd = ( PD * )INST_DATA( cl, obj );
1082 UWORD qual = wmki->wmki_IEvent->ie_Qualifier, code = wmki->wmki_IEvent->ie_Code;
1083 BOOL sl = pd->pd_Flags & PDF_SLIDER;
1084 LONG otop = sl ? pd->pd_Level : pd->pd_Top, ntop = otop;
1085 LONG inc = pd->pd_Visible - 1;
1087 if (inc < 1) inc = 1;
1090 * Shifted key?
1092 if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
1094 if (ntop > pd->pd_Min) ntop -= inc;
1095 if (ntop < pd->pd_Min) ntop = pd->pd_Min;
1097 else
1099 if (ntop < pd->pd_Max) ntop += inc;
1100 if (ntop > pd->pd_Max) ntop = pd->pd_Max;
1104 * Did the top position change?
1106 if ((ntop != otop) && !(code & IECODE_UP_PREFIX))
1109 * Let the slider know about this change.
1111 DoSetMethod(obj, wmki->wmki_GInfo, sl ? SLIDER_Level : PGA_Top, ntop, TAG_END);
1113 * Skip the ID because the notification
1114 * will handle the change.
1118 * Tell then to ignore this message.
1120 *(wmki->wmki_ID) = WMHI_IGNORE;
1122 return WMKF_VERIFY;
1124 METHOD_END
1127 /// Class initialization,
1129 * Class function table.
1131 STATIC DPFUNC ClassFunc[] = {
1132 { BASE_RENDER, PropClassRender, },
1133 { BASE_DIMENSIONS, PropClassDimensions, },
1135 { OM_NEW, PropClassNew, },
1136 { OM_SET, PropClassSetUpdate, },
1137 { OM_UPDATE, PropClassSetUpdate, },
1138 { OM_GET, PropClassGet, },
1139 { OM_DISPOSE, PropClassDispose, },
1140 { GM_HITTEST, PropClassHitTest, },
1141 { GM_HANDLEINPUT, PropClassHandleInput, },
1142 { GM_GOACTIVE, PropClassGoActive, },
1143 { GM_GOINACTIVE, PropClassGoInActive, },
1144 { WM_KEYACTIVE, PropClassKeyActive, },
1145 { DF_END, NULL },
1149 * Class initialization.
1151 makeproto Class *InitPropClass(void)
1153 return BGUI_MakeClass(CLASS_SuperClassBGUI, BGUI_BASE_GADGET,
1154 CLASS_ObjectSize, sizeof(PD),
1155 CLASS_DFTable, ClassFunc,
1156 TAG_DONE);