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.
     
  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)!
     
  3. Anser

    Anser Well-Known Member Licensed User

    Dear Harris,

    Your sample code looks promising, unfortunately I can't figure out from where to start. I believe that Google Charts are fast in loading time.

    Would you mind showing the BuildPage() or ConnectPage() to see, how the graphs are defined in the page.
    For eg something like the code shown just below. What I have shown below is creating an ABMChart. To use GoogleChart, how do I define the graphs on the ConnectPage()
    Code:
    Dim chartSales As ABMChart
    chartSales.Initialize(
    page"chartSales", ABM.CHART_TYPEBAR, ABM.CHART_RATIO_GOLDENSECTION, "chart4theme")
    ' set some options
    'chartSales.OptionsBar.AxisXOnlyInteger=True
    chartSales.OptionsBar.StackBars = True
    chartSales.OptionsBar.HorizontalBars = 
    False
    You have mentioned that in BuildPage sub add page.AddExtraJavaScriptFile("custom/loader.js")
    Do I need any other library files to use GoogleCharts ?

    I am really stuck with showing a graph on the page, started with ABMChart but the delay to load the graph is bit time consuming, then tried FrappeChart. It is very fast to load the chart, unfortunately the FrappeChart class requires few more options to make it really useful. My skill level in Java and wrapping is zero. So now wanted to experiment with Google charts
     
    Last edited: Mar 27, 2018
  4. Harris

    Harris Well-Known Member Licensed User

    Charts are fun - aren't they?
    You have fooled around with the rest, so this shouldn't be that difficult.

    Sometimes, when your need is simple, use Erel's Chart class. It simply builds bar or line on a canvas..
    I used it to produce the attached...


    Code:
    public Sub BuildPage()
        
    ' initialize the global vars
        Dim cnt1 As ABMContainer
        
    Dim tblCases As ABMTable
        
    Dim myLineChart As CustomGoogleChart2    ' the class for the google chart
        Dim pagination, pagination1  As ABMPagination
        
    Dim gm1 As ABMGoogleMap
        
        BuildTheme
        
    DateTime.TimeFormat = "HH:mm"
        

        
    page.AddExtraJavaScriptFile("custom/loader.js")
        
        
    ' initialize this page using our theme
        page.InitializeWithTheme(Name, "/ws/" & ABMShared.AppName & "/" & Name, False, ABMShared.SessionMaxInactiveIntervalSeconds, theme)
        
        
        
    page.ShowLoader=True
        
    page.ShowLoaderType=ABM.LOADER_TYPE_MANUAL ' NEW
        
        
        
    page.PageTitle = "ECM Data Viewer"
        
    page.PageDescription = "The pdf viewer component "   
        
    page.PageHTMLName = "index.html"
        
    page.PageKeywords = "ABMaterial, material design, B4X, B4J, SEO, framework, search engine optimization"
        
    page.PageSiteMapPriority = "0.50"
        
    page.PageSiteMapFrequency = ABM.SITEMAP_FREQ_MONTHLY
        
    'page.UseGoogleAnalytics(ABMShared.TrackingID, Null) ' IMPORTANT Change this to your own TrackingID !!!!!!!
            
        ABMShared.BuildNavigationBar(
    page,  Page_name, "../images/logo.png""""Apps", Page_name)
        
        
        
    page.AddRowsM( 1,False,  1,  1"").AddCells12(1,""'.AddCellsOSMP(1,0,0,0, 2,2,2,   5 , 5, 0,0,"cnter").AddCellsOSMP(1,0,0,0,3,3,3,  5,5,30,10,"cnter").AddCellsOSMP(1,0,0,0,3,3,3,  5 ,  5,30,10,"cnter").AddCellsOSMP(1,0,0,0,2,2,2 ,   15,   5,30, 10,"cnter").AddCellsOSMP(1,0,0,0,2,2,2 ,   10,   5,30, 10,"cnter")
        page.AddRowsM2(2False10,1020,20,"").AddCells12(1,"")
        
    page.BuildGrid 'IMPORTANT once you loaded the complete grid AND before you start adding components
        
        
    ' add paragraph   

        cnt1.Initialize( 
    page"cnt1","cntth")
        
        cnt1.AddRowsM( 
    1True , 5,  0,  "").AddCellsOSMP(100,   0,  12121215 ,10,  20 ,20""'.AddCellsOS(1,0,0,0,0,8,8, "")
        cnt1.AddRowsM( 4False00"") .AddCellsOSMP(1,0,0,0 ,66,61010,15,0,  "").AddCellsOSMP(1,0,0,06,6,6,10,10,15,0,  "")
        cnt1.AddRowsM2(
    1 ,False , 1,   1010,10"").AddCellsOS(1,00,0,121212""'"cellc") '.AddCellsOS(1,0,0,0,0,8,8, "")
        cnt1.AddRowsM(3False,  0,   10,  "").AddCellsOS(1,00,0,121212""'.AddCellsOS(1,0,0,0,0,8,8, "")
        cnt1.BuildGrid' IMPORTANT
        
        
        tblCases.Initialize(
    page  , "tblCases",   False,   TrueTrue"tbltheme")
        tblCases.SetHeaders(         
    Array As String"SD""ED""FN" ,"Date""Unit #" , "Driver","DRVID"   ))
        tblCases.SetHeaderThemes(    
    Array As String(  "bgb" , "bgb" , "bgb" , "bgc""bgc"    , "bgc" ,  "bgc"     ))
        tblCases.SetColumnVisible(    
    Array As Boolean( False,False,False,  True , TrueTrueFalse    ))
        
        pagination.Initialize(
    page"pagination",  3,   TrueTrue"")
        pagination.SetTotalNumberOfPages(
    3)

        pagination1.Initialize(
    page"pagination1",    15,   True,  True"")
        pagination1.SetTotalNumberOfPages(
    10)

     
     
    Log("    BuildPage was built")
    End Sub



    Sub ConnectPage
        
        ABMShared.ConnectNavigationBar(
    page)
    '    page.GoogleMapsAPIExtras="key=AIzaSyCZMltM-eGgnIhPbiFsogjNIvhKgWMk-34&libraries=geometry,places"
        
        gm1.Initialize(
    page,"gm1",  68.069423,-162.850616,  14,  850 ,ABM.GOOGLEMAPTYPE_SATELLITE,0)

        gm1.Draggable = 
    True
        gm1.HasMapTypeControl = 
    True
        gm1.HasStreetViewControl = 
    True
        gm1.HasZoomControl = 
    True
        gm1.AddMapType(ABM.GOOGLEMAPTYPE_ROADMAP)
        gm1.AddMapType(ABM.GOOGLEMAPTYPE_TERRAIN)
        gm1.AddMapType(ABM.GOOGLEMAPTYPE_HYBRID)
        gm1.AddMapType(ABM.GOOGLEMAPTYPE_SATELLITE)
        
        
        MakePIDMap   

        
    Dim combdrv As ABMCombo
        combdrv.Initialize(
    page"combdrv","Select Driver",500"")
        
        combdrv.AddItem(  
    "0""ALL", BuildSimpleItem(""&"0""mdi-action-star-rate""{NBSP}{NBSP}"&"ALL"))

        
    Dim sql As SQL = DBM.GetSQL
        
    Dim users As List = DBM.SQLSelect(sql"SELECT * FROM emp where comp_id = "&Main.comp_id&" Order by Last_name"' WHERE userId=" & SelectedRowId)
        If users.Size > 0 Then
            
    For i = 0 To users.Size -1
               
    Dim user As Map = users.Get(i)
             
    '  Log(" driver map: "&user)
               Dim id As String = user.Get("pk")
               
    Dim val As String = user.Get("last_name")&", "&user.Get("first_name")
              
    ' Log(" Driver: "&val)
               combdrv.AddItem(  id, val, BuildSimpleItem(""&id"mdi-action-star-rate"""&val))
            
    Next   
        
    End If
        DBM.CloseSQL(
    sql)
        combdrv.SetActiveItemId(
    "0")


        
    Dim combtrk As ABMCombo
        combtrk.Initialize(
    page"combtrk","Select Vehicle",500"")
        
        combtrk.AddItem(  
    "0""ALL", BuildSimpleItem(""&"0""mdi-action-star-rate""{NBSP}{NBSP}"&"ALL"))

        
    Dim sql As SQL = DBM.GetSQL
        
    Dim users As List = DBM.SQLSelect(sql"SELECT * FROM vehicle where comp_id = "&Main.comp_id&" AND unit_type = "&veh_type &" Order by unit_number"' WHERE userId=" & SelectedRowId)
        If users.Size > 0 Then
            
    For i = 0 To users.Size -1
               
    Dim user As Map = users.Get(i)
             
    '  Log(" trk map: "&user)
               Dim id As String = user.Get("unit_number")
               
    Dim val As String = user.Get("unit_number")
              
    ' Log(" truck: "&val)
               combtrk.AddItem(  id, val, BuildSimpleItem(""&id"mdi-action-star-rate""{NBSP}{NBSP}"&val))
            
    Next   
        
    End If
        DBM.CloseSQL(
    sql)
        combtrk.SetActiveItemId(
    "0")


        
    Dim startdate As ABMDateTimePicker
        startdate.Initialize(
    page"startdate",ABM.DATETIMEPICKER_TYPE_DATE ,qsd,"Start Date ",""' ABM.INPUT_TEXT, "Plate #", False, "lightblue")
        startdate.ClearText = ""

        
    Dim enddate As ABMDateTimePicker
        enddate.Initialize(
    page"enddate",ABM.DATETIMEPICKER_TYPE_DATE , qed,"End Date ",""' ABM.INPUT_TEXT, "Plate #", False, "lightblue")
    '    enddate.SetDate(qed)
        enddate.ClearText = ""

        
    Dim cbfilt As ABMCheckbox
        cbfilt.Initialize (
    page,"cbfilt""Exceptions Only",False,"")
        cbfilt.IsFilled = 
    True
        
        
    Dim btnshowus As ABMCheckbox
        btnshowus.Initialize( 
    page ,  "btnshowus""US MILES"True,"")
        btnshowus.IsFilled = 
    True

        
    Dim btnrefresh As ABMButton
        btnrefresh.InitializeFlat(  
    page ,  "btnrefresh",  "mdi-action-autorenew", ABM.ICONALIGN_LEFT,"Refresh Map""amber")

        
    Dim btnpids As ABMButton
        btnpids.InitializeFlat( 
    page ,  "btnpids""mdi-action-settings", ABM.ICONALIGN_LEFT,"Select/View PIDs","amber")

        
    Dim hist As ABMLabel
        hist.Initialize(
    page,"hist","Using CURRENT Data",ABM.SIZE_H5,False"")
        
    If Main.ecmFolder <> Main.histecmFolder Then
            hist.UseTheme(
    "sred")
            usinghist = 
    True
            hist.Text = 
    "Using HISTORIC Data"
        
    Else
            usinghist = 
    False   
        
    End If


        
    Dim chbgps As ABMCheckbox
        chbgps.Initialize( 
    page ,  "chbgps""GPS DATA ONLY"False"chbox")
        chbgps.IsFilled = 
    True
        
        cnt1.Cell(
    1,1).AddComponent(chbgps)

        cnt1.Cell(
    2,1).AddComponent(startdate)
        cnt1.Cell(
    2,2).AddComponent(enddate)
        
        cnt1.Cell(
    3,1).AddComponent(btnpids)
        cnt1.Cell(
    3,2).AddComponent(btnrefresh)

        cnt1.Cell(
    4,1).AddComponent(cbfilt)
        cnt1.Cell(
    4,2).AddComponent(btnshowus)

        cnt1.Cell(
    5,1).AddComponent(combdrv)
        cnt1.Cell(
    5,2).AddComponent(combtrk)


        cnt1.Cell(
    61).AddComponent(tblCases)
        cnt1.Cell(
    7,1).AddComponent(pagination)
        cnt1.Cell(
    8,1).AddComponent(hist)
        cnt1.Cell(
    8,1).UseTheme("cellc")
        
        myLineChart.Initialize(
    page,  "myLinechart")
        
    page.Cell(2,1).AddComponent(pagination1)
        
        
        
    page.Cell(2,1).AddComponent(myLineChart.ABMComp)
        
    page.Cell(3,1).AddComponent(gm1)

        
    page.AddModalSheetTemplate(BuildpidBox)


        
    page.FinishedLoading 'IMPORTANT   
        
        
    Log(" Finished loading and connecting page")

        
        
    page.RestoreNavigationBarPosition
        
        
    page.NavigationBar.Title = "ECM Data Viewer" 'page.ws.Session.GetAttribute2( "UserAction", "")
        
        
    Dim extraSideBar As ABMSideBar
        extraSideBar.InitializeasPanel(
    page"extrasidebar",   580,   60,   Null"nav3theme""pnl1",  "")

        
    '  extraSideBar.InitializeAsPanel(page1, "extrasidebar", 450,  130,   Null,   "nav2theme", "extrasidebarcontent",  "")
        extraSideBar.Content.AddRowsM(2False00"").AddCells12MP(1,   1010,  1010"")
        extraSideBar.Content.BuildGrid
      
        extraSideBar.Content.Cell(
    1,1).AddComponent( cnt1)
        
    page.NavigationBar.AddTopItemWithSideBar( "SideBar",  "Setup Graph",    "mdi-editor-insert-chart",  ""True, extraSideBar)
        
        CallSubDelayed2(Me, 
    "LoadInspects"1)
    '    LoadInspects(1)
        page.Refresh

    '    page.ShowSideBar("SideBar")



    End Sub
     

    Attached Files:

    Anser likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice