MultiTrackBarGadget Version 0.7 (Windows+Linux)
Posted: Thu Feb 11, 2016 3:56 pm
Hi,
I created this track bar gadget sometime back and found it as I was starting a spring clean on my hard disk. Horizontal version only.
Version 0.7 ~ I took a laptop on holiday and to keep sane I made a number of improvements. I only need to add a few more items before it gets to Rev1.0 and incorporated into a speech processor I'm working on for an amateur radio transceiver. At present the speech processor includes an Automatic Level Control, which works well, you can whisper or shout, the output amplitude remains much the same. The processor also includes record and playback features. My next step is to add frequency domain shaping with the user able to adjust the profile with something similar to the '10-slider' demo code. This will use FFT / IFFT and the key elements are in place. Finally I'm going to add dynamic amplitude shaping to increase the average 'talk power'.
Changes / additions are documented at the top of the code.
Please try / play. Comments welcome.
RichardL
I created this track bar gadget sometime back and found it as I was starting a spring clean on my hard disk. Horizontal version only.
Version 0.7 ~ I took a laptop on holiday and to keep sane I made a number of improvements. I only need to add a few more items before it gets to Rev1.0 and incorporated into a speech processor I'm working on for an amateur radio transceiver. At present the speech processor includes an Automatic Level Control, which works well, you can whisper or shout, the output amplitude remains much the same. The processor also includes record and playback features. My next step is to add frequency domain shaping with the user able to adjust the profile with something similar to the '10-slider' demo code. This will use FFT / IFFT and the key elements are in place. Finally I'm going to add dynamic amplitude shaping to increase the average 'talk power'.
Changes / additions are documented at the top of the code.
Please try / play. Comments welcome.
RichardL
Code: Select all
; This is like a one or two axis TrackBarGadget() with multiple sliders so MTrackBarGadget()
; Part of concept study for TTx-1101. (c) Richard Leman (G8CDD). Use, plunder or ignore at your own risk.
;{ Admin and TO DO list
; Some ideas for providing a multiple slider trackbar to allow bandwidth and notch width to be specified graphically.
; Clicking 'NEAR' a slider automatically jumps the mouse to the slider. What is NEAR? Within 5 pixels.
; (This is a 'good style' thing... merely selecting an item should not change it.)
; Multiple MTrackBarGadgets use just one handler. (Raided my KnobGadget() for that.)
; Slider moves are POSTed to the event manager as #MT_EventSliderMove.
; Version 0.7 - A holiday update! 18th May 2016
; DONE : Option to apply a smoothing operation to the lines between points. (Chickened out with Bezier!)
; DONE : Option to have X and/or Y lines showing while dragging
; DONE: : Option to join drag balls with lines. Table of Y values produced.**
; DONE : Option to produce a smoothed line between drag balls, also makes table. **
; DONE : Dispensed with MinVal and MaxVal (Sorry PB). I never used them and perform scaling based on pixel co-ords.
; DONE : Made drag bar width configurable.
; DONE : Simplification - Dispensed with #NarrowSlider option. Slider widths from 1 now valid.
; DONE : Single slider uses an almost MS look alike button... added option flag.
; DONE : Switch to turn vertical lines on/off
; DONE : Optional horizontal lines and on/off switch
; I sense a 1.0 is not far off!
; ** Tables can be scaled to control other processes. ie: Control FFT / IFFT frequency shaping / Machine tool.
; TO DO : Add X lock and Y lock on a per slider basis?
; : Think about a proper VERTICAL identity. VSCROLL style?
; : Two speed?
;}
; ------------------ Clip starting here and save as MTrackBar.pbi -------------------------
; MTrack_0.7
;{ Procedure Declarations
Declare MTrack_Service()
Declare SetGadgetMouseXY(Win,Gadget,MX,MY)
Declare MTrack_Refresh(Dragging)
Declare MTrack_GetIndex(Gadnum)
Declare MakeMSButton(BM)
Declare MakeMSArrow(BM,LR_Switch)
;}
;{ Variables and structures
;{ Define colours for our Linux friends
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
ImportC ""
gdk_device_manager_get_client_pointer(*device_manager); Gtk3
gdk_device_warp(*device.GdkDevice, *screen.GdkScreen, X, Y); Gtk3
gdk_display_get_default()
gdk_display_get_device_manager(*display.GdkDisplay); Gtk3
gdk_display_warp_pointer(*display.GdkDisplay, *screen.GdkScreen, X, Y); Gtk2
gdk_screen_get_default()
EndImport
#Red = $0000FF
#Green = $008000
#Cyan = $FFFF00
#Yellow= $00FFFF
#White = $FFFFFF
#Black = $0
#Blue = $FF0000
CompilerEndIf
;}
; ** [Maximum number of sliders] ... adjust to suit application. Must be literal value.
; [.....................|.................|........|.....|........]
; ^ ^ ^ ^ ^ ^
; Min S0 S1 S2 S1 Max
; Variables specific to multi-trackbargadgets
Structure MULTITRACKBAR
MT_Win.l ; Window in which the gadget resides
MT_GadNum.l ; Gadget number
MT_X.l ; Gadget X,Y,W and H
MT_Y.l
MT_W.l
MT_H.l
; _MinVal.l ; Slider range - Min
; _MaxVal.l ; Slider range - Max
MT_BorderWidth.l
MT_GratSpace.f ; Flag / Number of divisions in graticule
MT_NumSliders.l ; Number of sliders
MT_SlideWid.l
MT_SlideMode.l ; See 'Styles of pointer sliding'
MT_SlideProx.l ; Click proximity to grab a slider
MT_BackImage.l ; Bitmap# for backdrop.
MT_BackColour.l ; Backdrop colour
MT_ProgBarCol.l
MT_ProgBarTextCol.l
MT_ProgBarFontID.l
; Maximum number of sliders on an MTrack gadget = 10
MT_SlideX.l[10] ; ** Position of sliders in pixels from left
MT_Colour.l[10] ; ** Colours of sliders
MT_X_SlideBMP.l[10] ; ** Bitmaps for individual VERTICAL sliders.
MT_Y_SlideBMP.l[10] ; ** HORIZONTAL
MT_SlideY.l[10] ; ** Y position of capture ball
; Maximum width of an MTrack = 1000
MT_LineBuf.w[1000] ; Buffer: Y values for line plot
MT_SmoothBuf.w[1000]; Buffer: Smoothed Y values
EndStructure
; Styles of pointer sliding
EnumerationBinary
; Slider collision type... set one bit in Least Significant four bits
#SlideThro ; All sliders full range ** DEFAULT **
#Caged ; Slider constrained between neighbours
#Push ; Slider can shove neighbours along the road
#NoSlide ; Prevent user moving sliders, still allows programatic movements
; Misc flags
#Graticule = %100000; 05
#Balls ; 06 Sliders have small ball to aid identification when overlapped.
#UseMSStyle ; 07
#Borderless ; 08 Gadget does NOT have a border.
#ProgressBar ; 09 Fill to left of slider and show percentage display.
#BallYDrag ; 10 Drag balls may be slid vertically.
#BallJoin ; 11 Drag balls are joined with a line.
#BallJoinSmooth ; 12 Drag balls determine shape of a smoothed curve between them.
#Vert_LineSwitch ; 13 Turn vertical cursor lines on/off.
#Horiz_LineSwitch ; 14 Turn horizontal cursor lines on/off.
#LinesWhenDragging ; 15 Show vert and horiz lines ONLY when ball is being dragged.
EndEnumeration
; Define custom events
Enumeration #PB_Event_FirstCustomValue
#MT_EventSliderMove
#MT_EventRedrawSmooth
EndEnumeration
; Private
Global NumBarSlides = 1 ; Number of slider gadgets created
Global Dim MSlide.MULTITRACKBAR(1) ; Array of structures, one structure per gadget
Global MSDefs.MULTITRACKBAR ; Default values. Adjust these before creating a gadget.
Global BW.l = 2 ; Border width. 0 or 2
With MSDefs
\MT_BorderWidth = 2
\MT_SlideProx = 5
\MT_BackColour = GetSysColor_(#COLOR_BTNHILIGHT)
\MT_ProgBarCol = #Blue
\MT_ProgBarTextCol = #White
\MT_ProgBarFontID = FontID(LoadFont(#PB_Any,"Calibri",10))
\MT_NumSliders = 1
\MT_SlideWid = 3
For n = 0 To 9
\MT_SlideY[n] = (n+1)*4
\MT_Colour[n] = #White
Next
\MT_Colour[0] = #Red
\MT_Colour[1] = #Green
\MT_Colour[2] = #Cyan
\MT_Colour[3] = #Yellow
EndWith
;}
EnableExplicit
; To create a new MTrackBarGadget adjust the default values then call this procedure
Procedure MTrackBarGadget(Gadnum,GadX,GadY,GadW,GadH,NumSliders,SlideMode = #SlideThro | #Vert_LineSwitch,WindowNum = -1)
Protected F.f,Result.l,n.l,T.l,X
; Create storage for a new MTrackBarGadget
If MSlide(NumBarSlides)\MT_W <> 0
NumBarSlides + 1
Redim MSlide(NumBarSlides)
EndIf
T = #PB_Canvas_Border
If SlideMode & #Borderless : T = 0 : EndIf
Result = CanvasGadget(Gadnum,GadX,GadY,GadW,GadH,#PB_Canvas_ClipMouse | T )
If Result
If Gadnum = #PB_Any : Gadnum = Result : EndIf
CopyStructure(@MSDefs,@MSlide(NumBarSlides),MULTITRACKBAR)
With MSlide(NumBarSlides)
If WindowNum = -1
\MT_Win = GetActiveWindow()
Else
\MT_Win = WindowNum
EndIf
\MT_GadNum = Gadnum
\MT_X = GadX
\MT_Y = GadY
\MT_W = GadW
\MT_H = GadH
\MT_SlideMode = SlideMode
\MT_GratSpace = \MT_W / 32
\MT_BackImage = CreateImage(#PB_Any,GadW,GadH,32,\MT_BackColour)
\MT_NumSliders = NumSliders
For n = 0 To NumSliders - 1
\MT_SlideX.l[n] = (n+1) * GadW / (NumSliders +1)
Next
; Create optional graticule.
If \MT_SlideMode & #Graticule
If StartDrawing(ImageOutput(\MT_BackImage))
F = 0
While F < \MT_W
LineXY(F,\MT_H,F,\MT_H-\MT_H>>2,#White)
F + \MT_GratSpace
Wend
StopDrawing()
EndIf
EndIf
; Set global border margin width
If \MT_SlideMode & #Borderless
\MT_BorderWidth = 0
Else
\MT_BorderWidth = 2
EndIf
; Images for each slider bar.
; Vertical...
For n = 0 To \MT_NumSliders - 1
\MT_X_SlideBMP[n] = CreateImage(#PB_Any,\MT_SlideWid,\MT_H-(2*\MT_BorderWidth ),32,\MT_Colour[n])
If \MT_NumSliders = 1 And \MT_SlideMode & #UseMSStyle
MakeMSArrow(\MT_X_SlideBMP[n],2)
EndIf
Next
; Horizontal...
For n = 0 To \MT_NumSliders - 1
\MT_Y_SlideBMP[n] = CreateImage(#PB_Any,\MT_W-(2*\MT_BorderWidth ),\MT_SlideWid,32,\MT_Colour[n])
Next
EndWith
; Each gadget calls the same service routine
BindGadgetEvent(Gadnum,@MTrack_Service())
MTrack_Refresh(NumBarSlides)
EndIf
ProcedureReturn Gadnum
EndProcedure
; Use these two calls to set or get the position of a gadget's 'X' cursor/s
Procedure MTrack_SetCursor(Gadnum,Cursor,XPosition,YPosition=-1) ; Set a cursor position
Protected GadIndex.l
; Find the index to the data for the chosen gadget
GadIndex = MTrack_GetIndex(Gadnum)
; Quit if index not found
If GadIndex = 0
ProcedureReturn -1
EndIf
MSlide(GadIndex)\MT_SlideX[Cursor] = XPosition ; Set the cursor X position
If YPosition > -1
MSlide(GadIndex)\MT_SlideY[Cursor] = YPosition ; Set the cursor Y position
EndIf
MTrack_Refresh(GadIndex) ; Refresh the MTBG
EndProcedure
Procedure MTrack_GetCursor(Gadnum,Cursor) ; Return cursor position
Protected GadIndex.l
; Find the index to the data for the chosen gadget
GadIndex = MTrack_GetIndex(Gadnum)
; Quit if index not found
If GadIndex = 0
ProcedureReturn -1
EndIf
ProcedureReturn MSlide(GadIndex)\MT_SlideX[Cursor] - MSlide(GadIndex)\MT_BorderWidth
EndProcedure
; Keep out!
Procedure MTrack_Service() ; An Event has occurred on a MultiTrackBarGadget()...
Global Dragging
Static LastX
Protected EGad.l,n.l,DragX.l,DragY.l,T.l,GadIndex.l,X.l
; Get the Gadget# that was tickled...
EGad = EventGadget()
; Find the index to the data for the chosen gadget
GadIndex = MTrack_GetIndex(EGad)
If GadIndex = 0
ProcedureReturn - 1
EndIf
; Event manager for left mouse button down/up and mouse slide
With MSlide(GadIndex)
Select EventType()
Case #PB_EventType_LeftButtonDown ;{ Left mouse button went DOWN, start dragging a pointer...
DragX = GetGadgetAttribute(\MT_GadNum, #PB_Canvas_MouseX) + \MT_BorderWidth
DragY = GetGadgetAttribute(\MT_GadNum, #PB_Canvas_MouseY) + \MT_BorderWidth
; Find a slider position that is 'close' and jump to it.
; (This neat trick ensures that real time variables
; only change when the user moves the cursor.)
Dragging = 0
For n = 0 To \MT_NumSliders - 1 ; For each of the cursors
T = DragX - \MT_SlideX[n] ; Find how close the mouse is to the slider...
T - \MT_BorderWidth
If T < 0 : T = -T : EndIf ; regardless of side.
If T < \MT_SlideProx ; If close enough in 'X'
If \MT_SlideMode & #Balls ; If drag balls enabled...
T = DragY - \MT_SlideY[n] ; Find how close mouse is to ball...
If T<0 : T=-T : EndIf ; regardless of height.
If T >= \MT_SlideProx ; If NOT close enough
Continue ; Check the next slider...
EndIf
DragY = \MT_SlideY[n]+\MT_BorderWidth ; Mouse 'Y' position = vertical centre of ball
EndIf
SetGadgetMouseXY(\MT_Win,\MT_GadNum,\MT_SlideX[n] + \MT_BorderWidth,DragY); Jump mouse to cursor
Dragging = n+1 ; and set flag for 'dragging' (=Cursor+1)
; Nice comforting sound!
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
beep_(2500,50)
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
RunProgram("beep", "-f 2500 -l 50", ""); 'beep' must be installed on Linux
CompilerEndIf
Break
EndIf
Next
;}
Case #PB_EventType_MouseMove ;{ A pointer is being dragged, update position
If Dragging
X = GetGadgetAttribute(\MT_GadNum, #PB_Canvas_MouseX)
T = \MT_SlideMode & %11111
Select (T) ; Five bits that define the slider type ...
Case #SlideThro ; Free to roam over whole gadget
\MT_SlideX[Dragging-1] = X
PostEvent(#MT_EventSliderMove,\MT_Win,\MT_GadNum,Dragging-1,X) ; x-2
MTrack_Refresh(GadIndex)
Case #Caged ; Restricted to space between neighbours / ends
If (Dragging = \MT_NumSliders) Or (X <= \MT_SlideX[Dragging])
If (Dragging = 1) Or (X >= \MT_SlideX[Dragging-2])
\MT_SlideX[Dragging-1] = X
PostEvent(#MT_EventSliderMove,\MT_Win,\MT_GadNum,Dragging-1,X)
MTrack_Refresh(GadIndex)
EndIf
EndIf
Case #Push ; Able to push neighbours
\MT_SlideX[Dragging-1] = X
For n = Dragging-2 To 0 Step -1
If X < \MT_SlideX[n]
\MT_SlideX[n] = X
PostEvent(#MT_EventSliderMove,\MT_Win,\MT_GadNum,n,X)
EndIf
Next
For n = Dragging To \MT_NumSliders - 1
If X > \MT_SlideX[n]
\MT_SlideX[n] = X
PostEvent(#MT_EventSliderMove,\MT_Win,\MT_GadNum,n,X-\MT_BorderWidth)
EndIf
Next
PostEvent(#MT_EventSliderMove,\MT_Win,\MT_GadNum,Dragging-1,X-\MT_BorderWidth)
MTrack_Refresh(GadIndex)
Case #NoSlide ; User cannot move sliders on this gadget
If \MT_SlideMode & #ProgressBar
beep_(2500,55)
EndIf
Default
MessageRequester("MTrackBar","Flag error (%"+Bin(T)+")")
EndSelect
If \MT_SlideMode & #BallYDrag
\MT_SlideY[Dragging-1] = GetGadgetAttribute(\MT_GadNum, #PB_Canvas_MouseY)
EndIf
EndIf
;}
Case #PB_EventType_LeftButtonUp ;{ Button went UP, stop dragging pointer
Dragging = #False
;}
EndSelect
EndWith
EndProcedure
Procedure MTrack_GetIndex(Gadnum) ; Find the index to the data for the chosen gadget
Protected n.l, GadIndex.l
GadIndex = 0
For n = 1 To NumBarSlides
If MSlide(n)\MT_GadNum = Gadnum
GadIndex = n
Break
EndIf
Next
ProcedureReturn GadIndex
EndProcedure
Procedure MTrack_Refresh(Index) ; Redraw a MTBG referenced by table index (order of creation). Base 1
Protected n.l, r.l,k$, DyDx.f, X.l,Y.f,T.l, FirstX.l, LastX.l, Sw.l, U1.f, Y1.f, F.f, Z.l
With MSlide(Index)
StartDrawing(CanvasOutput(\MT_GadNum))
DrawImage(ImageID(\MT_BackImage),0,0) ; Redraw backdop
FirstX = \MT_SlideX[0]
For n = 0 To \MT_NumSliders - 1
; Redraw...
If \MT_SlideMode & #ProgressBar ;{ Progress bar
DrawingMode(#PB_2DDrawing_Transparent)
Box(0,0,\MT_SlideX[n],\MT_H,\MT_ProgBarCol)
k$ = StrF((\MT_SlideX[n] / (\MT_W-2*\MT_BorderWidth)) *100,1) + "%" ; Percent full
DrawingFont(\MT_ProgBarFontID) ; Set font
DrawText((\MT_W - TextWidth(k$))/2,(\MT_H-(\MT_BorderWidth*2)-TextHeight("0"))/2,k$,\MT_ProgBarTextCol)
;}
Else ;{ Vertical sliders
If (\MT_SlideMode & #Vert_LineSwitch) Or ((\MT_SlideMode & #LinesWhenDragging) And n=Dragging-1 And \MT_GadNum = EventGadget())
DrawImage(ImageID(\MT_X_SlideBMP[n]),\MT_SlideX[n] - \MT_SlideWid>>1,0) ; Image
EndIf
r = 3
;}
EndIf
;{ Draw optional drag ball and horizontal line/slider
If \MT_SlideMode & #Balls
If \MT_SlideMode & #Horiz_LineSwitch Or ((\MT_SlideMode & #LinesWhenDragging) And n=Dragging-1 And \MT_GadNum = EventGadget())
DrawImage(ImageID(\MT_Y_SlideBMP[n]),0,\MT_SlideY[n]-(\MT_SlideWid>>1))
EndIf
Circle(\MT_SlideX[n], \MT_SlideY[n],r+1,#Black) ; +++
Circle(\MT_SlideX[n], \MT_SlideY[n],r,\MT_Colour[n]) ; +++
EndIf
;}
;{ Draw optionalal lines joining drag balls together (N balls ... N-1 lines)
If n And (\MT_SlideMode & #BallJoin Or \MT_SlideMode & #BallJoinSmooth)
If \MT_SlideX[n]-\MT_SlideX[n-1] = 0 ; Special case if X1=X2. ie: vertical line
Else
; Make table of points for drawing LINEs between points
; Calculate slope of LINE to next point
DyDx = (\MT_SlideY[n]-\MT_SlideY[n-1]) / (\MT_SlideX[n]-\MT_SlideX[n-1])
; Initial values
X = \MT_SlideX[n-1]
Y = \MT_SlideY[n-1]
; Fill the table...
While X < \MT_SlideX[n]
\MT_LineBuf[X] = Round(Y,#PB_Round_Nearest)
Y + DyDx
X + 1
Wend
LastX = X-1
EndIf
EndIf
;}
Next
;{ Optional create smoothed table.
; The straight lines joining drag points are 'smoothed' by averaging the 'LineBuf' points
; in the range + / - 'Sw' either side of each point.
; The smoothed values are written to 'SmoothBuf' so Line and Smooth values are available
; for displaying and experiment control.
If LastX
Sw = 10 ; Semi-smoothing width
; Calculate sum of Y values for first group.
T = 0
For X = FirstX To FirstX + (2*Sw)
T + \MT_LineBuf[X]
Next
; Smoothing...
U1 = 1 + (2*Sw) ; Number of samples in smoothing group
Y1 = T / U1
For X = FirstX + Sw To LastX - Sw
\MT_SmoothBuf[X] = Round(T / U1,#PB_Round_Nearest); New Y is average of group.
T - \MT_LineBuf[X-Sw] ; Remove left group member
T + \MT_LineBuf[X+Sw+1] ; Add new right member
Next
; First 'Sw' width
F = \MT_SlideY[0]
DyDx = (Y1 - F) / Sw
For X = FirstX To FirstX + Sw
\MT_SmoothBuf[X] = Round(F,#PB_Round_Nearest)
F + DyDx
Next
; Last 'Sw' width
F = \MT_SmoothBuf[LastX - Sw]
DyDx = (\MT_LineBuf[LastX] - F) / Sw
For X = LastX - Sw To LastX
\MT_SmoothBuf[X] = Round(F,#PB_Round_Nearest)
F + DyDx
Next
EndIf
;}
;{ Plot smoothed lines
If \MT_SlideMode & #BallJoinSmooth
Plot(FirstX,\MT_SmoothBuf[FirstX],#Cyan)
For X = FirstX + 1 To LastX
LineXY(X-1,\MT_SmoothBuf[X-1],X,\MT_SmoothBuf[X],#Cyan)
Next
EndIf
;}
;{ Plot straight connecting lines
If \MT_SlideMode & #BallJoin
For X = FirstX + 1 To LastX
LineXY(X-1,\MT_LineBuf[X-1],X,\MT_LineBuf[X],#Red)
Next
EndIf
;}
StopDrawing()
EndWith
EndProcedure
Procedure MTrack_GetBackdropBitmap(Index)
ProcedureReturn MSlide(Index)\MT_BackImage
EndProcedure
Procedure MakeMSButton(BM)
Protected Result,IW.w,IH.w
Result = #False
IW = ImageWidth(BM)
IH = ImageHeight(BM)
If IW > 5
If StartDrawing(ImageOutput(BM))
Box(0,0,IW,IH,GetSysColor_(#COLOR_SCROLLBAR))
LineXY(IW-1,0,IW-1,IH-1, GetSysColor_(#COLOR_3DDKSHADOW))
LineXY(IW-2,1,IW-2,IH-2, GetSysColor_(#COLOR_3DSHADOW))
LineXY(1, 1,IW-3,1, GetSysColor_(#COLOR_3DHIGHLIGHT))
LineXY(0,IH-1,IW-1,IH-1, GetSysColor_(#COLOR_3DDKSHADOW))
LineXY(1,IH-2,IW-2,IH-2, GetSysColor_(#COLOR_3DSHADOW))
LineXY(1,1, 1, IH-3, GetSysColor_(#COLOR_3DHIGHLIGHT))
StopDrawing()
Result = #True
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Enumeration
#Left
#Right
#LeftRight
#Up
#Down
#UpDown
EndEnumeration
Procedure MakeMSArrow(BM,LR_Switch)
Protected Result,T,IW.w,IH.w
Protected Y.w,Y1.w,Y2.w,X.w,X1.w,X2.w
Result = #False
IW = ImageWidth(BM)
IH = ImageHeight(BM)
If (IH<6) Or (IW<6)
ProcedureReturn #False
Else
If MakeMSButton(BM)
If StartDrawing(ImageOutput(BM))
Select LR_Switch
Case #Left ;{
Y1 = (IH/2)-1 : Y2 = Y1 : X = 4
Repeat
For Y = Y2 To Y1
Plot(X,Y,#Black)
Next
X+1 : Y1+1 : Y2-1
Until Y2 < 4
;}
Case #Right ;{
Y1 = (IH/2)-1 : Y2 = Y1 : X = IW - 4
Repeat
For Y = Y2 To Y1
Plot(X,Y,#Black)
Next
X-1 : Y1+1 : Y2-1
Until Y2 < 4
;}
Case #LeftRight ;{
Y1 = (IH/2)-1 : Y2 = Y1 : X = 3
Repeat
For Y = Y2 To Y1
Plot(X,Y,#Black)
Next
X+1 : Y1+1 : Y2-1
Until Y2 < 4
Y1 = (IH/2)-1 : Y2 = Y1 : X = IW - 4
Repeat
For Y = Y2 To Y1
Plot(X,Y,#Black)
Next
X-1 : Y1+1 : Y2-1
Until Y2 < 4
;}
Case #Up ;{
X1 = (IW/2) : X2 = X1 : Y = 3
Repeat
For X = X1 To X2
Plot(X,Y,#Black)
Next
X1-1 : X2+1 : Y+1
Until X1 < 4
;}
Case #Down ;{
X1 = (IW/2) : X2 = X1 : Y = IH - 4
Repeat
For X = X1 To X2
Plot(X,Y,#Black)
Next
X1-1 : X2+1 : Y-1
Until X1 < 4
;}
Case #UpDown ;{
X1 = (IW/2) : X2 = X1 : Y = 3
Repeat
For X = X1 To X2
Plot(X,Y,#Black)
Next
X1-1 : X2+1 : Y+1
Until X1 < 4
X1 = (IW/2) : X2 = X1 : Y = IH - 4
Repeat
For X = X1 To X2
Plot(X,Y,#Black)
Next
X1-1 : X2+1 : Y-1
Until X1 < 4
;}
EndSelect
StopDrawing()
EndIf
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure SetGadgetMouseXY(Win,Gadget,MX,MY) ; Position mouse pointer at specified co-ordinated within a gadget
MX + WindowX(Win,#PB_Window_InnerCoordinate) + GadgetX(Gadget)
MY + WindowY(Win,#PB_Window_InnerCoordinate) + GadgetY(Gadget)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
SetCursorPos_(MX,MY)
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux
gdk_display_warp_pointer(gdk_display_get_default (), gdk_screen_get_default(), MX, MY); Gtk2, officialy deprecated
;-> replace the line above with the following line, if 'gdk_display_warp_pointer' is finally deprecated on newer gtk3-systems...
; gdk_device_warp (gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default ())), gdk_screen_get_default(), MX, MY)
CompilerEndIf
EndProcedure
DisableExplicit
; ------------------ End of Clip -----------------------------------------------------------
;{ ------------- TEST AND DEMO CODE -------------
CompilerIf #PB_Compiler_IsMainFile
Dim XDat(10): Dim YDat(10) ; Needed for demo only...
OpenWindow(1,0,0,600,400,"MultiBar_Test Rev 0.7", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
SetActiveWindow(1)
StickyWindow(1,#True)
; Create some MTrackBarGadgets.
;(They all use BindGadget() to call MTrack_Service, so are not serviced by EventGadget() in the Event Manager)
; 1 Slider
MSDefs\MT_SlideWid = 25
MTrackBarGadget(5, 10,25,512+4,20,1, #SlideThro | #Graticule | #Vert_LineSwitch | #UseMSStyle) ;+4? Two borders...
TextGadget(#PB_Any,10,10,512,15,"Code: MTrackBarGadget(5, 10,25,512+4,20,1, #SlideThro | #Graticule | #Vert_LineSwitch| #UseMSStyle)")
TextGadget(35,532,25,50,15,"")
; 2 Sliders
MSDefs\MT_SlideWid = 3
MTrackBarGadget(6, 10,65,512,30,2,#SlideThro | #Borderless | #Balls | #Vert_LineSwitch)
TextGadget(#PB_Any,10,50,560,15,"Code: MTrackBarGadget(6, 10,65,512,30,2,#SlideThro | #Borderless | #Balls | #Vert_LineSwitch)")
TextGadget(36,532,65,50,15,"")
TextGadget(37,532,80,50,15,"")
; 3 Sliders
MSDefs\MT_BackColour = $B0B080
MTrackBarGadget(7, 10,115,512+4,50,3,#Caged | #Graticule | #Balls | #Vert_LineSwitch)
TextGadget(#PB_Any,10,100,540,15,"Code: MTrackBarGadget(7, 10,135,512+4,50,3,#Caged | #Graticule | #Balls | #Vert_LineSwitch) ")
TextGadget(38,532,115,50,15,"")
TextGadget(39,532,130,50,15,"")
TextGadget(40,532,145,50,15,"")
; 10 Sliders
MSDefs\MT_SlideWid = 1
MTrackBarGadget(8, 10,185,512,150,10,#Push | #Borderless | #Balls | #BallYDrag | #BallJoinSmooth | #LinesWhenDragging); 10 Sliders
TextGadget(#PB_Any,10,170,580,15,"Code: MTrackBarGadget(8, 10,185,512,150,9,#Push | #Borderless | #Balls | #BallYDrag | #BallJoin)")
For n = 0 To 9
TextGadget(41+n,532,185+(n*15),60,15,"")
Next
; Buttons to turn options on/off
CheckBoxGadget(20,10, 335,80,15,"Lines")
CheckBoxGadget(21,110,335,80,15,"Smoothed")
In = MTrack_GetIndex(8)
SetGadgetState(20,MSlide(In)\MT_SlideMode & #BallJoin)
SetGadgetState(21,MSlide(In)\MT_SlideMode & #BallJoinSmooth)
; Example: Set some initial positions
For n = 0 To 9
MTrack_SetCursor(8,n,25+(n*50),50+((n&1)*50))
Next
; Example: Progress bar
TextGadget(#PB_Any,10,355,512,15,"Code: MTrackBarGadget((9, 12,325,250,20,1,#NoSlide | #ProgressBar)")
MTrackBarGadget(9, 12,370,260,20,1, #ProgressBar | #NoSlide )
; Example: Put a gradient backdrop on a MTrack.
In = MTrack_GetIndex(6) ; Get index of MTrack gadget (Order of creation)
With MSlide(In) ; Use the structure for the MTrack gadget
If StartDrawing(ImageOutput(\MT_BackImage)) ; Draw on its backdrop bitmap
Box(0,0,\MT_W,\MT_H,GetSysColor_(#COLOR_BTNFACE)) ; Rectangle, same colour as Window
DrawingMode(#PB_2DDrawing_Gradient) ; Draw the backdrop image...
BackColor($B0B080)
FrontColor($FF8080)
LinearGradient(0,0,\MT_W,\MT_H)
RoundBox(0,0,\MT_W,\MT_H,8,8)
DrawingMode(#PB_2DDrawing_Outlined) ; Detail line... looks good!
RoundBox(0,0,\MT_W,\MT_H,8,8,#Black)
StopDrawing()
MTrack_Refresh(In) ; Update the gadget
EndIf
EndWith
; Skeleton Event Manager... all the usual stuff.
Repeat
Select WaitWindowEvent(15) ; Timeout purely for convenience in this demo
Case #PB_Event_CloseWindow
Break
Case #MT_EventSliderMove ; Arrive here when an MTrack is accessed.
Debug "Window " + Str(EventWindow())
Debug "Gadget " + Str(EventGadget())
Debug "Slider " + Str(EventType())
Debug "X Value " + Str(EventData())
Debug ""
Select EventGadget()
Case 5
SetGadgetText(35,Str(EventData()))
Case 6
If EventType() = 0 : SetGadgetText(36,Str(EventData())) : EndIf
If EventType() = 1 : SetGadgetText(37,Str(EventData())) : EndIf
Case 7
In = MTrack_GetIndex(7)
X = EventData()
Y = MSlide(In)\MT_SlideY[EventType()]
SetGadgetText(38+EventType(),RSet(Str(X),3,"0") )
Case 8
In = MTrack_GetIndex(8)
X = MSlide(In)\MT_SlideX[EventType()] ; or: use EventData()
Y = MSlide(In)\MT_SlideY[EventType()]
SetGadgetText(41+EventType(),"X"+RSet(Str(X),3,"0")+", Y"+RSet(Str(Y),3,"0") )
EndSelect
Case #PB_Event_Gadget
EGad = EventGadget()
Select EGad
Case 20 : In = MTrack_GetIndex(8) : MSlide(In)\MT_SlideMode ! #BallJoin : SetGadgetState(20,MSlide(In)\MT_SlideMode & #BallJoin)
Case 21 : In = MTrack_GetIndex(8) : MSlide(In)\MT_SlideMode ! #BallJoinSmooth : SetGadgetState(21,MSlide(In)\MT_SlideMode & #BallJoinSmooth)
; All the usual stuff...
EndSelect
EndSelect
; Simulate sending data to the progress bar.
MTrack_SetCursor(9,0,(ElapsedMilliseconds()/32)& $FF)
; == ACTIVE BACKDROP DEMO ==============================================
; One way to update the backdrop to a MTrackBarGadget() periodically... not the best,
; WaitWindowEvent(n) MUST include the optional TimeOut.
; Make a dynamic data display... this would be the output from your 'machine'.
; I just made a random noise base line, simulating a spectrum display.
In = MTrack_GetIndex(8) ; Get the index of the gadget to be refreshed
Bd = MTrack_GetBackdropBitmap(In) ; Get the BitMap number for the gadget
If StartDrawing(ImageOutput(Bd)) ; Draw the new backdrop on the gadget's Bitmap
DrawingFont(#PB_Default )
Box(0,0,512,150, RGB($08,$21,$3)) ; Clear the display
; Make some spoof noise data.
For X = 0 To 511 Step 2
Y = 149-Random(10)
If X
LineXY(LastX,LastY,X,Y,#White)
EndIf
LastY = Y : LastX = X
Next
StopDrawing()
MTrack_Refresh(In) ; Redraw the 'spectrum display baseline noise' onto the Canvas()
EndIf
ForEver
; ----------- END OF TEST AND DEMO --------------------------------
CompilerEndIf
;}