wxWebview RunScript howto?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
faradayent
Earned a small fee
Earned a small fee
Posts: 19
Joined: Sat Dec 12, 2009 3:13 am

wxWebview RunScript howto?

Post by faradayent » Sat May 16, 2020 3:25 pm

Hi,
I'd like to render javascript based charts in wxWidgets. An example chart can be found here:
https://www.chartjs.org/samples/latest/ ... basic.html

It seems I should use RunScript() but I can't find any example code on how this should be done for displaying JS created images.

My end goal is to do some scientific plotting. I understand there are wxWidgets compatible c/c++ plotting libraries out there, but there seems to be even more comprehensive javascript based versions, so I'd like to go that route, using wxWebview to display.

If you could point me to an example, I'd really appreciate it!

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2569
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxWebview RunScript howto?

Post by PB » Sat May 16, 2020 5:15 pm

Use RunScript() to access the JS chart and return the saved image.

For example, when I played with ChartJS I tried this
JS code

Code: Select all

        function SaveChartHD()
        {                          
              var chartContainer = document.getElementById("myChartContainer");

              if ( chartContainer == undefined )
              {
                alert("Could not find chart container!");
                return "";
              }                         
                                                       
              var oldWidth = chartContainer.style.width;
              var oldHeight = chartContainer.style.height;
              
              chartContainer.style.width = "2000px";
              chartContainer.style.height = "2000px";
              chart.resize();
              chart.update();                                          
              
              var base64chart = chart.toBase64Image();
              
              chartContainer.style.width = oldWidth;
              chartContainer.style.height = oldHeight;
              chart.resize();
              chart.update(); 
              
              return base64chart;          
        }
C++ code

Code: Select all

    void OnSaveChart(wxCommandEvent&)
    {        
        wxString result;
        
        if (  m_browser->RunScript("SaveChartHD()", &result) )
        {
            wxString base64str;

            if ( !result.StartsWith("data:image/png;base64,", &base64str) )
            {
                wxLogError("Invalid data URL.");
                return;
            }
            
            wxMemoryBuffer data = wxBase64Decode(base64str);
            if ( data.IsEmpty() )
            {
                wxLogError("Could not decode the data.");
                return;
            }

            wxString fileName("chart.png");
            wxFFile file(fileName, "wb");

            if ( file.Write(data.GetData(), data.GetDataLen()) )            
                wxLogMessage("Saved chart as \"%s\".", fileName);
        }
        else
            wxLogError("Could not save chart.");
    }        
Unfortunately, there is limit on how much bytes can RunScript() return, but this can be worked around, getting it in chunks if needed.

EDIT
Oops, sorry I misread the OP, for some reason I thought only the code for saving the chart is needed.

FWIW, I attach the experimental code (C++ and HTML) I wrote a couple years ago, which uses wxWebView to interact with chartjs. Basically JS in it (ab)uses navigation resulting in wxEVT_WEBVIEW_NAVIGATING to communicate with C++ code with the data passed as URL query. It only shows how to notify C++ code when a chart element is clicked, how to save the chart as PNG image, and how to invoke wxWidgets context menu. But this should give one idea how to do it, it's pretty much all the same...
Attachments
wxchartjs.zip
(64.74 KiB) Downloaded 19 times

faradayent
Earned a small fee
Earned a small fee
Posts: 19
Joined: Sat Dec 12, 2009 3:13 am

Re: wxWebview RunScript howto?

Post by faradayent » Sat May 16, 2020 9:07 pm

Thanks, the code in the zip may be close to what I'm looking for. It built using mingw after adding libwxmsw31ud_webview.a (has to be before core) and libwxregexud.a to the project.

And it almost runs... But when it comes up I got a rather unusual warning:

"Failed to find web view emulation level in the registry". This error is found in wxWidgets source file webview_ie.cpp.

I searched the forum for "emulation level" and wound up setting the registry key using regedit, and that warning went away:
viewtopic.php?f=19&t=46176&p=193181&hil ... el#p193181

Once I put the HTML sample file where the application expected it, the application now comes up fine. Many thanks!

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2569
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxWebview RunScript howto?

Post by PB » Sat May 16, 2020 9:48 pm

If you are on MSW and do not mind using a recent version of wxWidgets, perhaps you could look into using the Chromium-based wxWebViewEdge backend.

I remember that even 2+ years ago, JS libraries were not happy with even MSIE 11 being rather outdated feature-wise and considering dropping its support. Edit: I see that you are using MinGW, so no wxWebViewEdge.

faradayent
Earned a small fee
Earned a small fee
Posts: 19
Joined: Sat Dec 12, 2009 3:13 am

Re: wxWebview RunScript howto?

Post by faradayent » Sat May 16, 2020 9:55 pm

Yes, on MSW and using wxWidgets 3.1.3, but I think I read the Chrome backend requires VS2015 to build and I'm still on VS2012 and mingw.

Too bad there's not a Firefox version.

I don't suppose there's any way to do this with a self contained browser, not crazy about the dependency. But the chart sure looks nice.

Post Reply