B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Class
Version=9.85
@EndOfDesignText@
#Region Shared Files
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True
#End Region

'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=\%PROJECT_NAME%.zip

'B4A ide://run?file=%WINDIR%\System32\cmd.exe&Args=/c&Args=start&Args=..\..\B4A\%PROJECT_NAME%.b4a 
'B4i ide://run?file=%WINDIR%\System32\cmd.exe&Args=/c&Args=start&Args=..\..\B4i\%PROJECT_NAME%.b4i 
'B4J ide://run?file=%WINDIR%\System32\cmd.exe&Args=/c&Args=start&Args=..\..\B4J\%PROJECT_NAME%.b4j

Sub Class_Globals
	Private Root As B4XView
	Private xui As XUI
	
	'B4X objects
	Private xpnlGraph As B4XView
	Private xcvsGraph As B4XCanvas
	Private rectGraph As B4XRect		' Graph rectangle
	Private rectGrid As B4XRect			' Grid rectangle
	Private ScaleTextFont As B4XFont
	Private CurveTextFont As B4XFont
	
	' Common variables
	Public ProgName = "Graph" As String
	Public ProgVersion = "V 1.0" As String
	
	' Graph variables
	Public GraphX0 As Int						' left position of the Graph
	Public GraphY0 As Int						' top position of the Graph
	Public GraphX1 As Int						' right position of the Graph
	Public GraphY1 As Int						' bottom position of the Graph
	Public GraphW As Int						' width of the Graph
	Public GraphH As Int						' height of the Graph
	Public GraphColor As Int				' Graph background color
	
	' Grid variables
	Public GridX0 As Int						' left position of the Grid
	Public GridY0 As Int						' top position of the Grid
	Public GridX1 As Int						' right position of the Grid
	Public GridY1 As Int						' bottom position of the Grid
	Public GridW As Int							' width of the Grid
	Public GridH As Int							' height of the Grid
	Public GridNbDivX As Int				' number of Grid X divisions
	Public GridNbDivY As Int				' number of Grid Y divisions
	Public GridDeltaX As Int				' Grid X division
	Public GridDeltaY As Int				' Grid Y division
	Public GridColor As Int					' Grid background color
	Public GridLineColor As Int			' Grid line color
	Public GridFrameColor As Int		' Grid frame color

	' Curve variables
	Public CurveNb = 3 As Int				' number of curves
	Public CurveNbPoints = 100 As Int			' number of points in the curve

	' array of curve point values,
	' first index, curve index
	' second index, point index
	Public Curve(CurveNb, CurveNbPoints + 1) As Double
	Public CurveLineColor(CurveNb) As Int
	Public CurveLineStroke(CurveNb) As Float
	Public CurveName(CurveNb) As String
	Public CurveUnit(CurveNb) As String
	Public CurveTextSize As Float
	Public CurveTextHeight As Float
	
	' Scale variables
	Public ScaleX As Double					' X scale, ratio pixels / physic unit
	Public ScaleY As Double					' Y scale, ratio pixels / physic unit
	Public ScaleXDelta As Double		' width of one X division in physic units
	Public ScaleYDelta As Double		' width of one Y division in physic units
	Public ScaleXMin As Double			' min X physical scale value
	Public ScaleYMin As Double			' min Y physical scale value
	Public ScaleXMax As Double			' max X physical scale value
	Public ScaleYMax As Double			' max Y physical scale value
	Public ScaleTextColor As Int
	Public ScaleTextSize As Float
	Public ScaleTextHeight As Float
	
	'Screen variables
	Public ScreenWidth As Int
	Public ScreenHeight As Int
End Sub

Public Sub Initialize

End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
	Root = Root1
	Root.LoadLayout("MainPage")
	
	ScreenWidth = xpnlGraph.Width
	ScreenHeight = xpnlGraph.Height
	xcvsGraph.Initialize(xpnlGraph)

	InitCurves
	InitCurveValues
	
	InitGraph
	InitGrid
	InitScale
	
	Private i As Int
	
	B4XPages.SetTitle(Me, ProgName & " " & ProgVersion)
	ClearGraph
	DrawGrid
	For i = 0 To CurveNb - 1
		DrawCurves(i)
	Next
	xcvsGraph.Invalidate
End Sub

Private Sub ClearGraph
	' clear the graph, draw a rectangle with the background color
	xcvsGraph.DrawRect(rectGraph, GraphColor, True, 1)
End Sub

Sub InitGraph
	' initialize the Graph variables

	' all dimensions are expressed in % of height
	GraphX0 = .03 * ScreenHeight
	GraphW = ScreenWidth - 2 * GraphX0
	GraphX1 = GraphX0 + GraphW

	GraphY0 = GraphX0
	GraphH = ScreenHeight - 2 * GraphY0
	GraphY1 = GraphY0 + GraphH
	
	xpnlGraph.Left = GraphX0
	xpnlGraph.Top = GraphY0
	xpnlGraph.Width = GraphW
	xpnlGraph.Height = GraphH
	xcvsGraph.Resize(GraphW, GraphH)
	
	' get the min value of the xcvsGraph canvas width or height
	Private GraphSize As Int
	GraphSize = Min(xcvsGraph.TargetRect.Width, xcvsGraph.TargetRect.Height)
	GraphSize = GraphSize / xui.Scale	'needed for B4A, adapts to dip values

	' set curve text size according to the screen size
	CurveTextSize = (1 + (GraphSize - 250)/1000) * 14
	CurveTextFont = xui.CreateDefaultFont(CurveTextSize)
	CurveTextHeight = MeasureTextHeight("Ag",  CurveTextFont) + 2dip
	
	' set scale text size according to the screen size
	ScaleTextSize = (1 + (GraphSize - 250)/1000) * 14
	ScaleTextFont = xui.CreateDefaultFont(ScaleTextSize)
	ScaleTextHeight = MeasureTextHeight("Ag", ScaleTextFont) + 2dip
	
	rectGraph.Initialize(0, 0, GraphW, GraphH)
	GraphColor = xui.Color_RGB(244, 239, 228)
End Sub

Private Sub InitGrid
	' initialize the Grid variables
	' all dimensions are expressed proportional to the curves text height

	' define the number of divisions for each axis
	If ScreenWidth > ScreenHeight Then
		GridNbDivX = 10
		GridNbDivY = 6
	Else
		GridNbDivX = 5
		GridNbDivY = 12
	End If
	
	' horzontal dimensions
	GridX0 = 2 * CurveTextHeight
	GridW = GraphW - 2 * GridX0
	
	' calculate the division dimensions in pixels
	GridDeltaX = GridW / GridNbDivX
	GridW = GridDeltaX * GridNbDivX
	GridX0 = (GraphW - GridW) / 2
	GridX1 = GridX0 + GridW
	
	' verical dimensions
	GridY0 = 4 * CurveTextHeight
	GridH = GraphH - GridY0 - 1.5 * CurveTextHeight
	GridDeltaY = GridH / GridNbDivY
	GridH = GridDeltaY * GridNbDivY
	GridY1 = GridY0 + GridH
	

	
	' calculate the division dimensions in pixels
	GridDeltaX = GridW / GridNbDivX
	GridDeltaY = GridH / GridNbDivY
	
	' assign the grid rectangle
	rectGrid.Initialize(GridX0, GridY0, GridX1, GridY1)

	' set the different colors
	GridColor = xui.Color_White
	GridLineColor = xui.Color_LightGray
	GridFrameColor = xui.Color_Black
	
	ScaleTextColor = xui.Color_Black
End Sub

Private Sub InitScale
	' initilize the scales according to the grid dimensions.
	ScaleXDelta = ScaleXMax / GridNbDivX
	ScaleX = GridW / (ScaleXMax - ScaleXMin)

	ScaleYDelta = (ScaleYMax - ScaleYMin) / GridNbDivY
	ScaleY = GridH / (ScaleYMax - ScaleYMin)
End Sub

Private Sub InitCurves
	' set curve line color
	CurveLineColor(0) = xui.Color_Red
	CurveLineColor(1) = xui.Color_Blue
	CurveLineColor(2) = xui.Color_RGB(10, 140, 0)

	' set curve line width (stroke)
	CurveLineStroke(0) = 3dip
	CurveLineStroke(1) = 2dip
	CurveLineStroke(2) = 1dip
End Sub

Private Sub DrawGrid
	' draw the Grid
	Private i As Int
	Private x0, y0 As Float
	
	' draw vertical lines
	For i = 1 To GridNbDivX - 1
		x0 = GridX0 + i * GridDeltaX
		xcvsGraph.DrawLine(x0, GridY0, x0, GridY1, GridLineColor, 1dip)
	Next

	' draw horizontal lines
	For i = 1 To GridNbDivY - 1
		y0 = GridY0 + i * GridDeltaY
		xcvsGraph.DrawLine(GridX0, y0, GridX1, y0, GridLineColor, 1dip)
	Next
	
	' draw the frame
	xcvsGraph.DrawRect(rectGrid, GridFrameColor, False, 1dip)
	
	' draw the scales
	DrawScaleY
	DrawScaleX

	' invalidate (update) the Graph
	xcvsGraph.Invalidate
End Sub

Private Sub DrawScaleX
	' draw X scale
	Private i As Int
	Private txt As String
	Private x, y As Float
	
	y = GridY1 + ScaleTextHeight
	For i = 0 To GridNbDivX
		txt = (ScaleXMin + i * ScaleXDelta)
		x = GridX0 + i * GridDeltaX
		xcvsGraph.DrawText(txt, x, y, ScaleTextFont, ScaleTextColor, "CENTER")
	Next
End Sub

Private Sub DrawScaleY
	' draw Y scale
	Private i As Int
	Private txt As String
	Private x, y As Float
	
	x = GridX0 - ScaleTextHeight / 3
	For i = 0 To GridNbDivY
		txt = (ScaleYMax - i * ScaleYDelta)
		y = GridY0 + ScaleTextHeight/3 + i * GridDeltaY
		xcvsGraph.DrawText(txt, x, y, ScaleTextFont, ScaleTextColor, "RIGHT")
	Next
End Sub

Private Sub DrawCurves(i As Int)
	' draw the curve of index i
	Private n  As Int
	Private d, x0, y0, x1, y1 As Float
	
	' draw the curve
	x0 = GridX0
	y0 = GridY0 + (ScaleYMax - Curve(i, 0)) * ScaleY
	d = GridW / CurveNbPoints
	For n = 1 To CurveNbPoints
		x1 = GridX0 + n * d
		y1 = GridY0 + (ScaleYMax - Curve(i, n)) * ScaleY
		xcvsGraph.DrawLine(x0, y0, x1, y1, CurveLineColor(i), CurveLineStroke(i))
		x0 = x1
		y0 = y1
	Next
	
	' draw curve name
	y0 = GridY0 - CurveTextHeight / 2
	xcvsGraph.DrawText(CurveName(i) & " " & CurveUnit(i), GridX0, y0 - i * CurveTextHeight, CurveTextFont, CurveLineColor(i), "LEFT")
End Sub

Private Sub InitCurveValues
	Private i, n As Int
	Private t As Double
	Private Amplitude(CurveNb) As Double
	Private Offset(CurveNb) As Double
	Private Omega(CurveNb) As Double
	
	' set curve amplitude
	Amplitude(0) = 2.5
	Amplitude(1) = 1.5
	Amplitude(2) = .02
	
	' set curve offset
	Offset(0) = 0
	Offset(1) = 1
	Offset(2) = -1
	
	' set curve omega
	Omega(0)= 2.4 * cPI
	Omega(1)= 8 * cPI
	
	' calculate curve point values
	For i = 0 To CurveNb - 1
		For n = 0 To CurveNbPoints
			t = n / 100
			If i = 2 Then
				Curve(i, n) = Offset(i) + Amplitude(i) * Rnd(-100, 100)
			Else
				Curve(i, n) = Offset(i) + Amplitude(i) * Sin(Omega(i) * t)
			End If
		Next
	Next
	
	' set curve names and units
	CurveName(0) = "Voltage"
	CurveUnit(0) = "[V]"
	CurveName(1) = "Current"
	CurveUnit(1) = "[A]"
	CurveName(2) = "Acceleration"
	CurveUnit(2) = "[m/s2]"
	
	' set scale values
	ScaleXMax = CurveNbPoints / 10
	ScaleXMin = 0
	
	ScaleYMax = 3
	ScaleYMin = -3
End Sub

Private Sub MeasureTextWidth(Text As String, Font1 As B4XFont) As Int
	Private rct As B4XRect
	rct = xcvsGraph.MeasureText(Text, Font1)
	Return rct.Width
End Sub

Private Sub MeasureTextHeight(Text As String, Font1 As B4XFont) As Int
	Private rct As B4XRect
	rct = xcvsGraph.MeasureText(Text, Font1)
	Return rct.Width
End Sub
