B4J Tutorial [ABMaterial] - ABMCustomComponent - Google Charts

Discussion in 'B4J Tutorials' started by Harris, Nov 13, 2016.

  1. Harris

    Harris Well-Known Member Licensed User

    Requires ABM version 2.0 or above...

    Google Charts - LineChart

    My second stab at using a custom component ( which generally means adding js script into the project).
    This is a bit more complicated - yet truly easy when you see how it flows...

    Since we are adding Google Charts, we need to add the loader - in BuildPage sub add...
    page.AddExtraJavaScriptFile("custom/loader.js")


    Now, building a chart and displaying it is very easy - using Google charts API.
    As I have found, all other chart libs require you to set properties depending on what is to be rendered. Google charts does this automatically (huge code savings!). Being able to use Google Charts in ABMaterial is a big bonus. Thank you @alwaysbusy for providing the examples.

    My example: Show time on X axis (or as Google calls it - hAxis) - hours, minutes and seconds.


    Code:
    Sub PutChartdata

        myLineChart.Rows.Clear   
    ' clear rows and cols since we will rebuild these lists
        myLineChart.Columns.Clear
       
        
    Dim num As Int = selpid.Size    ' Determine how many lines to diplay from the map size
        myLineChart.Title = "ECM PID Values (for each hour)"
       
        myLineChart.Subtitle = 
    "by the second"  ' only valid in material charts (not used)
       
        myLineChart.AddColumn(
    "timeofday""Time of Day"'use timeofday data type for XAxis
       
        
    If num = 0 Then
            
    page.Resume
           Toast(
    " At Least 1 PID Must Be Selected",5000)
           
    Return   
        
    End If
       
        
    Select num  ' sets the legend titles
       
        
    Case 1
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(0)) )

        
    Case 2
           myLineChart.AddColumn(
    "number",  getIDname(selpid.GetKeyAt(0)) )
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(1)))

        
    Case 3
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(0)) )
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(1)))
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(2)))

        
    Case 4
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(0)) )
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(1)))
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(2)))
           myLineChart.AddColumn(
    "number", getIDname(selpid.GetKeyAt(3)))

        
    End Select
       
        
    For i = 0 To splist.Size-1
            
    Dim dt As Long
            dt = rngdate.Get(i)
            
    Dim hour, mins, sec  As Int
            hour = 
    DateTime.GetHour(dt)
            mins = 
    DateTime.GetMinute(dt)
            sec  = 
    DateTime.GetSecond(dt)
            
    ' pass array of hours, minutes and seconds
           
            
    Select num ' using the same AddRow sub, pass up to 4 lists

              
    Case 1
               myLineChart.AddRow(
    Array As Int(hour,mins,sec) , splist.Get(i), 0.00.00.0,num)
                 
              
    Case 2
               myLineChart.AddRow(
    Array As Int(hour,mins,sec) , splist.Get(i), rpmlist.Get(i)/1000.00.0,num)
                 
              
    Case 3
               myLineChart.AddRow(
    Array As Int(hour,mins,sec) , splist.Get(i), rpmlist.Get(i)/100, thlist.Get(i), 0.0,num)
                 
              
    Case 4
               myLineChart.AddRow(
    Array As Int(hour,mins,sec) , splist.Get(i), rpmlist.Get(i)/100, thlist.Get(i), gpslist.Get(i),num)
                           
            
    End Select
           
        
    Next
       
        
    page.Cell(2,2).Refresh  ' this will cause the custom refresh event to fire - producing the chart
       
        
    page.Resume   
       
    End Sub
    The AddRow sub, in the CustomGoogleChart class was modified to handle my needs. I didn't even bother to change the param names...

    Code:
    public Sub AddRow(Day() As Int , Guardians As Double, Avengers As Double, Transformers As Double, Lastcol As Double, numcols As Int)

    Select numcols
        
    Case 1
            
    If Rows.Size > 0 Then ' with comma
                Rows.Add($",[ [${Day(0)},${Day(1)},${Day(2)}], ${Guardians} ]"$)
            
    Else ' first one, does not need a comma
                Rows.Add($"[ [${Day(0)},${Day(1)},${Day(2)}], ${Guardians}  ]"$)
            
    End If
           
        
    Case 2
            
    If Rows.Size > 0 Then ' with comma
                Rows.Add($",[ [${Day(0)},${Day(1)},${Day(2)}], ${Guardians}, ${Avengers} ]"$)
            
    Else ' first one, does not need a comma
                Rows.Add($"[ [${Day(0)},${Day(1)},${Day(2)}], ${Guardians}, ${Avengers} ]"$)
            
    End If
           
        
    Case 3
            
    If Rows.Size > 0 Then ' with comma
                Rows.Add($",[ [${Day(0)},${Day(1)},${Day(2)}], ${Guardians}, ${Avengers}, ${Transformers} ]"$)
            
    Else ' first one, does not need a comma
                Rows.Add($"[ [${Day(0)},${Day(1)},${Day(2)}], ${Guardians}, ${Avengers}, ${Transformers} ]"$)
            
    End If
           
        
    Case 4
            
    If Rows.Size > 0 Then ' with comma
                Rows.Add($",[ [${Day(0)},${Day(1)},${Day(2)}], ${Guardians}, ${Avengers}, ${Transformers}, ${Lastcol} ]"$)
            
    Else ' first one, does not need a comma
                Rows.Add($"[ [${Day(0)},${Day(1)},${Day(2)}], ${Guardians}, ${Avengers}, ${Transformers}, ${Lastcol} ]"$)
            
    End If
                       
    End Select


    End Sub
    This sub (ABMComp_Refresh) actually draws the chart. Took awhile to figure this one out.

    Code:
    Sub ABMComp_Refresh(InternalPage As ABMPage, internalID As String)
       
        
    ' use these methods to adjust the object
        'ABM.HasClass
        ' ABM.AddClass
        ' ABM.RemoveClass
        ' ABM.AddHTML
        ' ABM.InsertHTMLAfter
        ' ABM.RemoveHTML
        ' ABM.GetProperty
        ' ABM.SetProperty
        ' ABM.RemoveProperty
        ' ABM.GetStyleProperty
        ' ABM.SetStyleProperty
       
        
    ' do some script stuff like you do in RunJavaScript   
        'Dim script As String = $""$   
       
        
    Dim script As String = $"
             // Define the chart To be drawn.
             var data = new google.visualization.DataTable();
             ${
    GetColumns}
              data.addRows([${
    GetRows}]);
         
              var options = { 
                  width: '100%',
                  height: 750,
                backgroundColor:  'transparent',
                  chartArea: {backgroundColor    :  '#E3F2FD'},

                title: '${
    Title}',  
                vAxis: {title: "ECM Data Collected", minValue:0, gridlines: {count:20, color: 'gray'} },
                  hAxis: {title: "Time of Day", gridlines: {count:20,  color: 'gray'} },       
                lineWidth: 1.3,               
                explorer: {
                    actions: ['dragToZoom', 'rightClickToReset'],
                    axis: 'horizontal',
                    keepInBounds: true,
                    maxZoomIn: 100.0
                },           
                  legend: { position: 'bottom' },
               
              };

              // Instantiate And draw the chart.
              var chart = new google.visualization.LineChart(document.getElementById('${
    internalID}'));
              chart.draw(data, options);     
         "$

       
        InternalPage.ws.Eval(script, 
    Null)   
       
    End Sub
    Select items for each line. Max 4 so chart doesn't get too busy.

    main2.jpg

    The Main form...
    Each page shows 1 hours worth of data. Note how the hAxis labels automatically adjust (rotate) for best fit.

    main1.jpg

    Zooming in was easy using the explorer actions. Simply right-click to zoom out to full view.
    Tooltips are automatic and show up for each data point, for each line in chart!

    main4.jpg


    Have fun with your Google Charts project in ABMaterial.
     
    Don Oso, Erel, alwaysbusy and 3 others like this.
  2. Harris

    Harris Well-Known Member Licensed User

    Further to above, I have added GPS lat/lon to a list so we can show a Google Map - plotting various points.

    map1.jpg

    This image shows 4 points we have selected and defined as exceptions (when the value exceeds our definition).
    Note: Google Maps will NOT show additional markers that contain the same lat.lon.
    In this example, I added 0.0003 (.0006, .0009, etc) to each (original) longitude point so Google would include it as a new Marker.


    maps2.jpg

    This is where we have defined what the exceptions shall be for each PID Flag value. Setting this value to "0" will ignore it.


    maps3.jpg
    Here we set what the map resolution will be. Set it from 1 to 60 seconds.
    The checkbox (checked) will ONLY show exceptions on the map. Un-checked - it will show each data point (for the defined resolution) as well as any exceptions found.

    All accomplished easily in pure ABM and B4J.
    I can't imagine what I would have to pay for some 'guru' to accomplish the same in some other language(s)!
     
Loading...