2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
7 #include <proto/graphics.h>
8 #include <proto/intuition.h>
9 #include <proto/cybergraphics.h>
10 #include <proto/layers.h>
11 #include <graphics/gfxmacros.h>
12 #include <intuition/cghooks.h>
13 #include <intuition/intuition.h>
14 #include <intuition/imageclass.h>
15 #include <intuition/windecorclass.h>
16 #include <cybergraphx/cybergraphics.h>
17 #include <graphics/rpattr.h>
18 #include "intuition_intern.h"
19 #include "propgadgets.h"
21 #include "intuition_customize.h"
22 #include "intuition_customizesupport.h"
23 #include "morphos/proprender.h"
27 extern ULONG
HookEntry();
31 # include <aros/debug.h>
33 // static data moved to intuibase - Piru
34 //static WORD clickoffset_x, clickoffset_y;
35 #define clickoffset_x GetPrivIBase(IntuitionBase)->prop_clickoffset_x
36 #define clickoffset_y GetPrivIBase(IntuitionBase)->prop_clickoffset_y
38 BOOL
isonborder(struct Gadget
*gadget
,struct Window
*window
);
40 static void RenderPropBackground(struct Gadget
*gad
, struct Window
*win
, struct DrawInfo
*dri
,
41 struct Rectangle
*rect
, struct Rectangle
*proprect
,
42 struct Rectangle
*knobrect
, struct PropInfo
*pi
,
43 struct RastPort
*rp
, BOOL onborder
,
44 struct IntuitionBase
*IntuitionBase
)
48 struct wdpDrawBorderPropBack msg
;
50 msg
.MethodID
= WDM_DRAW_BORDERPROPBACK
;
54 msg
.wdp_RenderRect
= rect
;
55 msg
.wdp_PropRect
= proprect
;
56 msg
.wdp_KnobRect
= knobrect
;
59 LOCKSHARED_WINDECOR(dri
);
60 DoMethodA(((struct IntDrawInfo
*)dri
)->dri_WinDecorObj
, (Msg
)&msg
);
65 static UWORD pattern
[] = {0x5555,0xAAAA};
69 if (pi
->Flags
& PROPNEWLOOK
)
71 SetAfPt(rp
, pattern
, 1);
72 SetAPen(rp
, dri
->dri_Pens
[SHADOWPEN
]);
73 SetBPen(rp
, dri
->dri_Pens
[BACKGROUNDPEN
]);
75 RectFill(rp
, rect
->MinX
, rect
->MinY
, rect
->MaxX
, rect
->MaxY
);
80 SetAPen(rp
, dri
->dri_Pens
[BACKGROUNDPEN
]);
81 RectFill(rp
, rect
->MinX
, rect
->MinY
, rect
->MaxX
, rect
->MaxY
);
87 VOID
HandlePropSelectDown(struct Gadget
*gadget
, struct Window
*w
, struct Requester
*req
,
88 UWORD mouse_x
, UWORD mouse_y
, struct IntuitionBase
*IntuitionBase
)
94 pi
= (struct PropInfo
*)gadget
->SpecialInfo
;
99 CalcBBox (w
, req
, gadget
, &knob
);
101 /* This func gets mouse coords relative to gadget box */
103 mouse_x
+= knob
.Left
;
106 if (!CalcKnobSize (gadget
, &knob
))
109 clickoffset_x
= mouse_x
- knob
.Left
;
110 clickoffset_y
= mouse_y
- knob
.Top
;
115 if (pi
->Flags
& FREEHORIZ
)
117 if (mouse_x
< knob
.Left
)
119 if (dx
> pi
->HPotRes
)
124 else if (mouse_x
>= knob
.Left
+ knob
.Width
)
126 if (dx
< MAXPOT
- pi
->HPotRes
)
133 if (pi
->Flags
& FREEVERT
)
135 if (mouse_y
< knob
.Top
)
137 if (dy
> pi
->VPotRes
)
142 else if (mouse_y
>= knob
.Top
+ knob
.Height
)
144 if (dy
< MAXPOT
- pi
->VPotRes
)
153 /* jDc: when clicked on frame, prop gadget also gets activated! */
154 if (!(flags
& PROPBORDERLESS
))
156 if (pi
->Flags
& FREEVERT
)
166 if (mouse_x
>= knob
.Left
&&
167 mouse_y
>= knob
.Top
&&
168 mouse_x
< knob
.Left
+ knob
.Width
&&
169 mouse_y
< knob
.Top
+ knob
.Height
)
178 gadget
->Flags
|= GFLG_SELECTED
;
180 D(bug("New HPot: %d, new VPot: %d\n", dx
, dy
));
182 NewModifyProp(gadget
, w
, req
, flags
, dx
, dy
, pi
->HorizBody
, pi
->VertBody
, 1);
187 VOID
HandlePropSelectUp(struct Gadget
*gadget
, struct Window
*w
,
188 struct Requester
*req
, struct IntuitionBase
*IntuitionBase
)
190 struct PropInfo
* pi
;
192 pi
= (struct PropInfo
*)gadget
->SpecialInfo
;
194 gadget
->Flags
&= ~GFLG_SELECTED
;
195 if (pi
) pi
->Flags
&= ~KNOBHIT
;
197 if (pi
) RefreshPropGadget (gadget
, w
, req
, IntuitionBase
);
200 NewModifyProp (gadget
203 , pi->Flags &= ~KNOBHIT
214 VOID
HandlePropMouseMove(struct Gadget
*gadget
, struct Window
*w
,struct Requester
*req
,
215 LONG dx
, LONG dy
, struct IntuitionBase
*IntuitionBase
)
220 pi
= (struct PropInfo
*)gadget
->SpecialInfo
;
222 /* Has propinfo and the mouse was over the knob */
223 if (pi
&& (pi
->Flags
& KNOBHIT
))
225 CalcBBox (w
, req
, gadget
, &knob
);
227 if (!CalcKnobSize (gadget
, &knob
))
230 /* Move the knob the same amount, ie.
231 knob.Left += dx; knob.Top += dy;
233 knob.Left = knob.Left
234 + (pi->CWidth - knob.Width)
235 * pi->HorizPot / MAXPOT;
237 ie. dx = (pi->CWidth - knob.Width)
238 * pi->HorizPot / MAXPOT;
242 pi->HorizPot = (dx * MAXPOT) /
243 (pi->CWidth - knob.Width);
246 /* stegerg: dx and dy are not delta values
247 anymore but relative to gadget
250 dx
= dx
- clickoffset_x
;
251 dy
= dy
- clickoffset_y
;
253 if (pi
->Flags
& FREEHORIZ
254 && pi
->CWidth
!= knob
.Width
)
257 dx
= (dx
* MAXPOT
) / (pi
->CWidth
- knob
.Width
);
262 else if (dx
> MAXPOT
)
269 if (pi
->Flags
& FREEVERT
270 && pi
->CHeight
!= knob
.Height
)
272 dy
= (dy
* MAXPOT
) / (pi
->CHeight
- knob
.Height
);
278 else if (dy
> MAXPOT
)
285 if ( ((pi
->Flags
& FREEHORIZ
) && (dx
!= pi
->HorizPot
)) ||
286 ((pi
->Flags
& FREEVERT
) && (dy
!= pi
->VertPot
)) )
289 NewModifyProp (gadget
, w
, req
, pi
->Flags
, dx
, dy
, pi
->HorizBody
, pi
->VertBody
, 1);
292 } /* Has PropInfo and Mouse is over knob */
297 int CalcKnobSize (struct Gadget
* propGadget
, struct BBox
* knobbox
)
302 pi
= (struct PropInfo
*)propGadget
->SpecialInfo
;
304 //dprintf("CalcKnobSize(%lx,%d,%d,%d,%d)\n", propGadget,
305 // propGadget->LeftEdge, propGadget->TopEdge, propGadget->Width, propGadget->Height);
306 //dprintf("knob(%d,%d,%d,%d)\n", knobbox->Left, knobbox->Top, knobbox->Width, knobbox->Height);
308 if (pi
->Flags
& PROPBORDERLESS
)
319 knobbox
->Width
-= x
* 2;
320 knobbox
->Height
-= y
* 2;
324 //dprintf("knob(%d,%d,%d,%d)\n", knobbox->Left, knobbox->Top, knobbox->Width, knobbox->Height);
326 pi
->CWidth
= knobbox
->Width
;
327 pi
->CHeight
= knobbox
->Height
;
329 if ((!(pi
->Flags
& AUTOKNOB
)) && propGadget
->GadgetRender
)
331 struct Image
*im
= propGadget
->GadgetRender
;
333 knobbox
->Width
= im
->Width
;
334 knobbox
->Height
= im
->Height
;
337 if (pi
->Flags
& FREEHORIZ
)
339 if (pi
->Flags
& AUTOKNOB
)
341 knobbox
->Width
= pi
->CWidth
* pi
->HorizBody
/ MAXBODY
;
342 if (knobbox
->Width
< KNOBHMIN
) knobbox
->Width
= KNOBHMIN
;
345 knobbox
->Left
= knobbox
->Left
+ (pi
->CWidth
- knobbox
->Width
)
346 * pi
->HorizPot
/ MAXPOT
;
350 if (pi
->HorizBody
< MAXBODY
/2)
351 pi
->HPotRes
= MAXPOT
* 32768 / ((MAXBODY
* 32768 / pi
->HorizBody
) - 32768);
353 pi
->HPotRes
= MAXPOT
;
359 if (pi
->Flags
& FREEVERT
)
361 if (pi
->Flags
& AUTOKNOB
)
363 knobbox
->Height
= pi
->CHeight
* pi
->VertBody
/ MAXBODY
;
364 if (knobbox
->Height
< KNOBVMIN
) knobbox
->Height
= KNOBVMIN
;
367 knobbox
->Top
= knobbox
->Top
+ (pi
->CHeight
- knobbox
->Height
)
368 * pi
->VertPot
/ MAXPOT
;
372 if (pi
->VertBody
< MAXBODY
/2)
373 pi
->VPotRes
= MAXPOT
* 32768 / ((MAXBODY
* 32768 / pi
->VertBody
) - 32768);
375 pi
->VPotRes
= MAXPOT
;
380 //dprintf("knob(%d,%d,%d,%d)\n", knobbox->Left, knobbox->Top, knobbox->Width, knobbox->Height);
386 void RefreshPropGadget (struct Gadget
* gadget
, struct Window
* window
,
387 struct Requester
* req
, struct IntuitionBase
* IntuitionBase
)
390 struct DrawInfo
*dri
;
391 struct GadgetInfo gi
;
392 struct RastPort
*rp
= 0;
393 struct BBox bbox
, kbox
;
396 D(bug("RefreshPropGadget(gad=%p, win=%s, req=%p)\n", gadget
, window
->Title
, req
));
398 onborder
= (IS_BORDER_GADGET(gadget
) || isonborder(gadget
,window
));
400 if ((dri
= GetScreenDrawInfo(window
->WScreen
)))
403 SetupGInfo(&gi
, window
, req
, gadget
, IntuitionBase
);
405 if ((rp
= ObtainGIRPort(&gi
)))
409 CalcBBox (window
, req
, gadget
, &bbox
);
412 if (bbox
.Width
<= 0 || bbox
.Height
<= 0)
415 if (CalcKnobSize (gadget
, &kbox
))
417 pi
= (struct PropInfo
*)gadget
->SpecialInfo
;
424 if (!(pi
->Flags
& PROPBORDERLESS
))
426 SetAPen(rp
,dri
->dri_Pens
[SHADOWPEN
]);
427 drawrect(rp
,bbox
.Left
,
429 bbox
.Left
+ bbox
.Width
- 1,
430 bbox
.Top
+ bbox
.Height
- 1,
433 bbox
.Left
++; bbox
.Top
++;
434 bbox
.Width
-= 2; bbox
.Height
-= 2;
437 RefreshPropGadgetKnob (gadget
, &bbox
, &kbox
, window
, req
, IntuitionBase
);
442 pi
= (struct PropInfo
*)gadget
->SpecialInfo
;
449 if (!(pi
->Flags
& PROPBORDERLESS
))
451 SetAPen(rp
,dri
->dri_Pens
[SHADOWPEN
]);
452 drawrect(rp
,bbox
.Left
,
454 bbox
.Left
+ bbox
.Width
- 1,
455 bbox
.Top
+ bbox
.Height
- 1,
458 bbox
.Left
++; bbox
.Top
++;
459 bbox
.Width
-= 2; bbox
.Height
-= 2;
464 struct Rectangle tmprect
;
466 tmprect
.MinX
= bbox
.Left
;
467 tmprect
.MaxX
= bbox
.Left
+ bbox
.Width
- 1;
468 tmprect
.MinY
= bbox
.Top
;
469 tmprect
.MaxY
= bbox
.Top
+ bbox
.Height
- 1;
471 RenderPropBackground(gadget
, window
, dri
, &tmprect
, &tmprect
, NULL
,
472 pi
, rp
, onborder
, IntuitionBase
);
478 } /* if ((rp = ObtainGIRPort(&gi))) */
480 if (rp
&& gadget
->Flags
& GFLG_DISABLED
)
482 CalcBBox (window
, req
, gadget
, &bbox
);
484 RenderDisabledPattern(rp
, (struct DrawInfo
*)dri
, bbox
.Left
,
486 bbox
.Left
+ bbox
.Width
- 1,
487 bbox
.Top
+ bbox
.Height
- 1,
491 if (rp
) ReleaseGIRPort(rp
);
493 FreeScreenDrawInfo(window
->WScreen
, (struct DrawInfo
*)dri
);
495 } /* if ((dri = GetScreenDrawInfo(window->WScreen))) */
497 ReturnVoid("RefreshPropGadget");
498 } /* RefreshPropGadget */
501 void RefreshPropGadgetKnob (struct Gadget
* gadget
, struct BBox
* clear
,
502 struct BBox
* knob
, struct Window
* window
, struct Requester
* req
,
503 struct IntuitionBase
* IntuitionBase
)
505 struct DrawInfo
*dri
;
508 struct GadgetInfo gi
;
512 D(bug("RefresPropGadgetKnob(flags=%d, clear=%p, knob = %p, win=%s)\n",
513 flags
, clear
, knob
, window
->Title
));
515 onborder
= (IS_BORDER_GADGET(gadget
) || isonborder(gadget
,window
));
517 pi
= (struct PropInfo
*)gadget
->SpecialInfo
;
520 if ((dri
= GetScreenDrawInfo(window
->WScreen
)))
522 SetupGInfo(&gi
, window
, req
, gadget
, IntuitionBase
);
524 if ((rp
= ObtainGIRPort(&gi
)))
527 struct Rectangle brect
;
528 struct Rectangle krect
;
530 CalcBBox (window
, req
, gadget
, &bbox
);
531 brect
.MinX
= bbox
.Left
;
532 brect
.MinY
= bbox
.Top
;
533 brect
.MaxX
= bbox
.Left
+ bbox
.Width
- 1;
534 brect
.MaxY
= bbox
.Top
+ bbox
.Height
- 1;
536 krect
.MinX
= knob
->Left
;
537 krect
.MinY
= knob
->Top
;
538 krect
.MaxX
= knob
->Left
+ knob
->Width
- 1;
539 krect
.MaxY
= knob
->Top
+ knob
->Height
- 1;
545 struct Rectangle a
, b
, clearrects
[4];
548 #if (!(PROP_RENDER_OPTIMIZATION))
549 if (!(flags
& PROPBORDERLESS
))
551 clear
->Left
++; clear
->Top
++;
552 clear
->Width
-= 2; clear
->Height
-= 2;
557 D(bug("RefresPropGadgetKnob: clear Left %d Top %d Width %d Height %d\n",
563 D(bug("RefresPropGadgetKnob: knob Left %d Top %d Width %d Height %d\n",
570 a
.MinX
= clear
->Left
;
572 a
.MaxX
= clear
->Left
+ clear
->Width
- 1;
573 a
.MaxY
= clear
->Top
+ clear
->Height
- 1;
577 b
.MaxX
= knob
->Left
+ knob
->Width
- 1;
578 b
.MaxY
= knob
->Top
+ knob
->Height
- 1;
581 D(bug("RefresPropGadgetKnob: a MinX %d MinY %d MaxX %d MaxY %d\n",
587 D(bug("RefresPropGadgetKnob: a MinX %d MinY %d MaxX %d MaxY %d\n",
594 nrects
= SubtractRectFromRect(&a
, &b
, clearrects
);
596 D(bug("RefresPropGadgetKnob: nrects %d\n",
599 D(bug("RefresPropGadgetKnob: clearrects[0] MinX %d MinY %d MaxX %d MaxY %d\n",
603 clearrects
[0].MaxY
));
605 D(bug("RefresPropGadgetKnob: clearrects[1] MinX %d MinY %d MaxX %d MaxY %d\n",
609 clearrects
[1].MaxY
));
611 D(bug("RefresPropGadgetKnob: clearrects[2] MinX %d MinY %d MaxX %d MaxY %d\n",
615 clearrects
[2].MaxY
));
617 D(bug("RefresPropGadgetKnob: clearrects[3] MinX %d MinY %d MaxX %d MaxY %d\n",
621 clearrects
[3].MaxY
));
624 /*kprintf("\n=== oldknob = %d,%d-%d,%d newknob = %d,%d-%d,%d\n",
634 for(i
= 0; i
< nrects
; i
++)
636 RenderPropBackground(gadget
, window
, dri
, &clearrects
[i
], &brect
, &krect
,
637 pi
, rp
, onborder
, IntuitionBase
);
642 if (flags
& AUTOKNOB
)
644 int hit
= ((flags
& KNOBHIT
) != 0);
646 D(bug("RefresPropGadgetKnob: draw knob Left %d Top %d Width %d Height %d\n",
654 struct wdpDrawBorderPropKnob msg
;
655 struct Rectangle knobrect
;
657 knobrect
.MinX
= knob
->Left
;
658 knobrect
.MinY
= knob
->Top
;
659 knobrect
.MaxX
= knob
->Left
+ knob
->Width
- 1;
660 knobrect
.MaxY
= knob
->Top
+ knob
->Height
- 1;
662 msg
.MethodID
= WDM_DRAW_BORDERPROPKNOB
;
663 msg
.wdp_Window
= window
;
665 msg
.wdp_Gadget
= gadget
;
666 msg
.wdp_RenderRect
= &knobrect
;
667 msg
.wdp_PropRect
= &brect
;
668 msg
.wdp_Flags
= hit
? WDF_DBPK_HIT
: 0;
670 LOCKSHARED_WINDECOR(dri
);
671 DoMethodA(((struct IntDrawInfo
*)dri
)->dri_WinDecorObj
, (Msg
)&msg
);
672 UNLOCK_WINDECOR(dri
);
674 } /* gadget inside window border */
680 stdlook
= RenderPropKnob(window
,dri
,rp
,pi
,knob
,hit
,IntuitionBase
);
685 if (flags
& PROPBORDERLESS
)
687 SetAPen(rp
,dri
->dri_Pens
[SHADOWPEN
]);
689 /* paint black right and bottom edges */
691 RectFill(rp
,knob
->Left
+ knob
->Width
- 1,
693 knob
->Left
+ knob
->Width
- 1,
694 knob
->Top
+ knob
->Height
- 1);
696 RectFill(rp
,knob
->Left
,
697 knob
->Top
+ knob
->Height
- 1,
698 knob
->Left
+ knob
->Width
- 2,
699 knob
->Top
+ knob
->Height
- 1);
704 } /* propborderless */
707 SetAPen(rp
,dri
->dri_Pens
[SHADOWPEN
]);
709 if (flags
& FREEHORIZ
)
711 /* black line at the left and at the right */
713 RectFill(rp
,knob
->Left
,
716 knob
->Top
+ knob
->Height
- 1);
718 RectFill(rp
,knob
->Left
+ knob
->Width
- 1,
720 knob
->Left
+ knob
->Width
- 1,
721 knob
->Top
+ knob
->Height
- 1);
726 if (flags
& FREEVERT
)
728 /* black line at the top and at the bottom */
730 RectFill(rp
,knob
->Left
,
732 knob
->Left
+ knob
->Width
- 1,
735 RectFill(rp
,knob
->Left
,
736 knob
->Top
+ knob
->Height
- 1,
737 knob
->Left
+ knob
->Width
- 1,
738 knob
->Top
+ knob
->Height
- 1);
744 } /* not propborderless */
747 SetAPen(rp
, dri
->dri_Pens
[SHINEPEN
]);
750 RectFill(rp
,knob
->Left
,
752 knob
->Left
+ knob
->Width
- 1,
753 knob
->Top
+ knob
->Height
- 1);
756 } /* gadget not inside window border */
758 } /* if (flags & AUTOKNOB) */
761 struct Image
*image
= (struct Image
*)gadget
->GadgetRender
;
764 if (knob
->Top
+ image
->Height
<= bbox
.Top
+ bbox
.Height
&&
765 knob
->Left
+ image
->Width
<= bbox
.Left
+ bbox
.Width
)
769 image
->LeftEdge
= knob
->Left
- bbox
.Left
;
770 image
->TopEdge
= knob
->Top
- bbox
.Top
;
771 // image->Width = knob->Width;
772 // image->Height = knob->Height;
779 (struct DrawInfo
*)dri
);
789 (struct DrawInfo
*)dri
);
794 if (gadget
->Flags
& GFLG_DISABLED
)
796 RenderDisabledPattern(rp
, (struct DrawInfo
*)dri
,
797 brect
.MinX
, brect
.MinY
,
798 brect
.MaxX
, brect
.MaxY
, IntuitionBase
);
803 } /* if ((rp = ObtainGIRPort(&gi))) */
805 FreeScreenDrawInfo(window
->WScreen
, (struct DrawInfo
*)dri
);
807 } /* if ((dri = GetScreenDrawInfo(window->WScreen))) */
809 ReturnVoid("RefreshPropGadgetKnob");
811 } /* RefreshPropGadgetKnob */
813 BOOL
isonborder(struct Gadget
*gadget
, struct Window
*window
)
815 if ((window
->BorderBottom
> 2) && (gadget
->Flags
& GFLG_RELBOTTOM
))
816 if (window
->Height
+ gadget
->TopEdge
>= window
->Height
- window
->BorderBottom
) return TRUE
;
818 if ((window
->BorderRight
> 2) && (gadget
->Flags
& GFLG_RELRIGHT
))
819 if (window
->Width
+ gadget
->LeftEdge
>= window
->Width
- window
->BorderRight
) return TRUE
;