Type=Class
Version=4.7
ModulesStructureVersion=1
B4J=true
@EndOfDesignText@
'Custom View class LimitBar

'Events declaration
#Event: ValuesChanged(LimitLeft As Int, LimitRight As Int)
#RaisesSynchronousEvents: ValuesChanged

'Designer property declarations
#DesignerProperty: Key: Max, DisplayName: Max, FieldType: Int, DefaultValue: 100, Description: Sets the max value.
#DesignerProperty: Key: LimitLeft, DisplayName: Left limit, FieldType: Int, DefaultValue: 0, Description: Sets the left limit value.
#DesignerProperty: Key: LimitRight, DisplayName: Right limit, FieldType: Int, DefaultValue: 100, Description: Sets the right limit value.
#DesignerProperty: Key: Radius, DisplayName: Radius, FieldType: Int, DefaultValue: 5, Description: Sets the corner radius.
#DesignerProperty: Key: BackgroundColor, DisplayName: BackgroundColor, FieldType: Color, DefaultValue: 0xFF0000FF, Description: Sets the background color.
#DesignerProperty: Key: BackLineColor, DisplayName: BackLineColor, FieldType: Color, DefaultValue: 0xFFFF0000, Description: Sets the back line color.
#DesignerProperty: Key: FrontLineColor, DisplayName: FrontLineColor, FieldType: Color, DefaultValue: 0xFF33B5E5, Description: Sets the front line color.

'LimitBar CustomView class.
'This CustomView allows the user to set two limits with two cursors.
'The Min value is 0 and the Max value is 100.
'The Max value can be changed by the programmer.
Sub Class_Globals
	Private fx As JFX										' B4J specific
	Private mCallback As Object					' calling module
	Private mEventName As String				' event name
	Private mWidth, mHeight, mRadius As Double

	Private ltbPanelBack As Pane				' the background pane
	Private cvsBack As Canvas						' the background canvas
	Private cvsFront As Canvas					' the foreground canvas
	
	Private mBackgroundColor As Paint		' color for the background
	Private mBackLineColor As Paint			' color for the background line
	Private mFrontLineColor As Paint		' color for the foreground line
	Private mMargin As Double						' left and right margins for the line
	Private x0, y0, x1, y1, y2 As Double	' backline and cursor coordinates
	Private mMaxValue As Int						' value of the Max property
	Private mScale As Double						' scale between position value and pixels
	Private mLimit(2) As Int						' value of the limits
	Private PositionPixels(2) As Double	' left and right positions in pixels
	Private PosIndex As Int
																			' 0 = left   1 = right
	Private Graph, jCanvasFront As JavaObject		' B4J specific used to draw the cursors
End Sub

'Initializes the object.
'Callback = name of the calling module
'EventName = event name
'Example if added in the code: 
'<Code>ltbTest.Initialize(Me, "ltbTest")</Code>
Public Sub Initialize(Callback As Object, EventName As String)
	mCallback = Callback
	mEventName = EventName
	
	' initialize default values
	mBackgroundColor = fx.Colors.Blue
	mBackLineColor = fx.Colors.Black
	mFrontLineColor = fx.Colors.RGB(51, 181, 229)
	mMargin = 15
	mMaxValue = 100
	mLimit(0) = 0
	mLimit(1) = mMaxValue
End Sub

Public Sub DesignerCreateView(Base As Pane, Lbl As Label, Props As Map)
	' we use the Base panel as the background panel
	ltbPanelBack = Base

	' we memorize the Base Width and Height properties
	mWidth = Base.Width
	mHeight = Base.Height
	
	' we memorize the custom properties
	mMaxValue = Props.Get("Max")
	mLimit(0) = Props.Get("LimitLeft")
	mLimit(0) = Max(0, mLimit(0))					' we check the min value, not less than 0
	
	mLimit(1) = Props.Get("LimitRight")
	mLimit(1) = Min(mMaxValue, mLimit(1))	' we check the max value, not higher than Max
	
	mRadius = Props.Get("Radius")
	mBackgroundColor = Props.Get("BackgroundColor")
	mBackLineColor = Props.Get("BackLineColor")
	mFrontLineColor = Props.Get("FrontLineColor")
End Sub

Private Sub Base_Resize (Width As Double, Height As Double)
	mWidth = ltbPanelBack.Width
	mHeight = ltbPanelBack.Height
	
	If cvsBack.IsInitialized = False Then
		InitClass		' initializes the common parts for Designer and code
	End If
	setWidth(Width)
End Sub

'Adds the LimitBar to the Parent object
'Parent = parent view, the Activity or a Panel
'Left, Right, Width, Height = position and dimensions properties of the LimitBar
'Height min = 30, Height min = 60
'BackgroundColor = background color of the LimitBar
'Radius = corner radius of the LimitBar
Public Sub AddToParent(Parent As Pane, Left As Int, Top As Int, Width As Int, Height As Int, BackgroundColor As Paint, Radius As Int)
	mWidth = Width
	mHeight = Max(Height, 30)					' limits the height to min 30 pixels
	mHeight = Min(Height, 60)					' limits the height to max 60 pixels
	mRadius = Min(Radius, Height / 2)	' limits the max radius to half the height
	mBackgroundColor = BackgroundColor
	
	' initialize the background panel ltbPanelBack and add it onto the parent view
	ltbPanelBack.Initialize("")
	Parent.AddNode(ltbPanelBack, Left, Top, Width, Height)
	
	InitClass		' initializes the common parts for Designer and code
End Sub

Private Sub InitClass
	' set the background color and the radius for the background panel
	CSSUtils.SetBackgroundColor(ltbPanelBack, mBackgroundColor)
	CSSUtils.SetBorder(ltbPanelBack, 0, mBackgroundColor, mRadius)
	
	' initialize the background canvas and draw the background line
	cvsBack.Initialize("cvsBack")
	ltbPanelBack.AddNode(cvsBack, 0, 0, mWidth, mHeight)
'	DrawBackGround
	
	' initialize the foreground canvas
	cvsFront.Initialize("cvsFront")
	ltbPanelBack.AddNode(cvsFront, 0, 0, mWidth, mHeight)
	
	' set a JavaObject for CanvasFront, needed for the drawing of the cursors
	jCanvasFront = cvsFront
	Graph = jCanvasFront.RunMethod("getGraphicsContext2D", Null)

	' set the limit max value, which calculates also the scale limit values <> pixels
	setMax(mMaxValue)
	
	DrawBackGround
End Sub

Private Sub InitCursors
	x0 = mMargin
	x1 = mWidth - mMargin
	mScale = (x1 - x0) / mMaxValue
	PositionPixels(0) = mLimit(0) * mScale + x0
	PositionPixels(1) = mLimit(1) * mScale + x0

	y0 = 0.2 * mHeight
	y1 = y0 + 8dip + 0.05 * mHeight
	y2 = 0.9 * mHeight
End Sub

Private Sub DrawBackGround
	cvsBack.ClearRect(0, 0, mWidth, mHeight)
	cvsBack.DrawLine(x0, y0, x1, y0, mBackLineColor, 2)
End Sub

Private Sub DrawCursors
	' draw a transparent rectangle to erase the foreground panel
	cvsFront.ClearRect(0, 0, cvsFront.Width, cvsFront.Height)
	
	' draw the left cursor
	Graph.RunMethod("setFill", Array As Object(mFrontLineColor))		
	Graph.RunMethod("beginPath", Null)	
	Graph.RunMethod("moveTo", Array As Object(PositionPixels(0), y0))		
	Graph.RunMethod("lineTo", Array As Object(PositionPixels(0), y2))		
	Graph.RunMethod("lineTo", Array As Object(PositionPixels(0) - 12,  y2))		
	Graph.RunMethod("lineTo", Array As Object(PositionPixels(0) - 12, y1))		
	Graph.RunMethod("fill", Null)					

	' draw the right cursor
	Graph.RunMethod("setFill", Array As Object(mFrontLineColor))		
	Graph.RunMethod("beginPath", Null)	
	Graph.RunMethod("moveTo", Array As Object(PositionPixels(1), y0))		
	Graph.RunMethod("lineTo", Array As Object(PositionPixels(1), y2))		
	Graph.RunMethod("lineTo", Array As Object(PositionPixels(1) + 12dip,  y2))		
	Graph.RunMethod("lineTo", Array As Object(PositionPixels(1) + 12dip, y1))		
	Graph.RunMethod("fill", Null)				
	
	' draw the front line
	cvsFront.DrawLine(PositionPixels(0), y0, PositionPixels(1), y0, mFrontLineColor, 3dip)
End Sub

Private Sub cvsFront_MousePressed (EventData As MouseEvent)
	cvsFront_Touch (0, EventData.X)
End Sub

Private Sub cvsFront_MouseDragged (EventData As MouseEvent)
	cvsFront_Touch (2, EventData.X)
End Sub

Private Sub cvsFront_MouseReleased (EventData As MouseEvent)
	cvsFront_Touch (1, EventData.X)	
End Sub

Private Sub cvsFront_Touch (Action As Int, X As Double)
	' check if the cursor is outsides the limits
	X = Max(x0, X)
	X = Min(x1, X)
	
	' select the Action type
	Select Action
	Case 0  				'DOWN (mouse pressed)
		If X < Abs(PositionPixels(0) + PositionPixels(1)) / 2 Then
			' if X is closer to the left cursor we choose it
			PosIndex = 0
		Else
			' otherwise we choose the right cursor
			PosIndex = 1
		End If
		mLimit(PosIndex) = Floor((X - x0) / mScale + .5)
		PositionPixels(PosIndex) = X
		DrawCursors			
	Case 2				' MOVE (mouse dragged)
		mLimit(PosIndex) = Floor((X - x0) / mScale + .5)
		PositionPixels(PosIndex) = X
		DrawCursors		
	Case 1				' UP (mouse released)
		' when Action is UP (mouse released) check if mLimit(0) > mLimit(1) 
		' if yes we invert the limit values and redraw the cursors
		If mLimit(0) > mLimit(1) Then
			Private val As Int
			val = mLimit(0)
			mLimit(0) = mLimit(1)
			mLimit(1) = val
			PositionPixels(0) = mLimit(0) * mScale + x0
			PositionPixels(1) = mLimit(1) * mScale + x0
			DrawCursors
		End If
	End Select
	
	' if a callback routine exists in the calling module we call it
	If SubExists(mCallback, mEventName & "_ValuesChanged") Then
		CallSub3(mCallback, mEventName & "_ValuesChanged", mLimit(0), mLimit(1))
	End If
End Sub

'gets or sets the max value
Public Sub setMax(MaxValue As Int)
	mMaxValue = MaxValue
	InitCursors	
	DrawCursors
End Sub

Public Sub getMax As Int
	Return mMaxValue
End Sub

'gets or sets the left limit
Public Sub setLimitLeft(Pos As Int)
	' if Pos is lower than 0 set cLimitLeft to 0
	mLimit(0) = Max(0, Pos)
	InitCursors
	DrawCursors
End Sub

Public Sub getLimitLeft As Int
	Return mLimit(0)
End Sub

'gets or sets the right limit
Public Sub setLimitRight(Pos As Int)
	' if Pos is higher than mMaxValue set mLimitRight to mMaxValue
	mLimit(1) = Min(mMaxValue, Pos)
	InitCursors
	DrawCursors
End Sub

Public Sub getLimitRight As Int
	Return mLimit(1)
End Sub

'gets or sets the Left property
Public Sub setLeft(Left As Int)
	ltbPanelBack.Left = Left
End Sub

Public Sub getLeft As Int
	Return ltbPanelBack.Left
End Sub

'gets or sets the Top property
Public Sub setTop(Top As Int)
	ltbPanelBack.Top = Top
End Sub

Public Sub getTop As Int
	Return ltbPanelBack.Top
End Sub

'gets or sets the Width property
Public Sub setWidth(Width As Int)
	mWidth = Width
	ltbPanelBack.PrefWidth = mWidth
	cvsBack.PrefWidth = mWidth
	cvsFront.PrefWidth = mWidth
	
	InitCursors
	DrawBackGround
	setMax(mMaxValue)
End Sub

Public Sub getWidth As Int
	Return ltbPanelBack.Width
End Sub

'gets or sets the Height property
Public Sub setHeight(Height As Int)
	mHeight = Max(Height, 30)
	ltbPanelBack.PrefHeight = mHeight
	cvsBack.PrefHeight = mHeight
	cvsFront.PrefHeight = mHeight
	
	InitCursors
	DrawBackGround
	DrawCursors
End Sub

Public Sub getHeight As Int
	Return ltbPanelBack.Height
End Sub

'gets or sets the Visible property
Public Sub setVisible(IsVisible As Boolean)
	ltbPanelBack.Visible = IsVisible
End Sub

Public Sub getVisible As Boolean
	Return ltbPanelBack.Visible
End Sub

'gets or sets the back line color
Public Sub setBackLineColor(BackLineColor As Paint)
	mBackLineColor = BackLineColor
	If ltbPanelBack.IsInitialized Then
		DrawBackGround
	End If
End Sub

Public Sub getBackLineColor As Paint
	Return mBackLineColor
End Sub

'gets or sets the front line color
Public Sub setFrontLineColor(FrontLineColor As Paint)
	mFrontLineColor = FrontLineColor
	If ltbPanelBack.IsInitialized Then
		DrawCursors	
	End If
End Sub

Public Sub getFrontLineColor As Paint
	Return mFrontLineColor
End Sub
