Is it possible to have a gnuplot plot in wxFrame window.

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.
User avatar
doublemax@work
Super wx Problem Solver
Super wx Problem Solver
Posts: 474
Joined: Wed Jul 29, 2020 6:06 pm
Location: NRW, Germany

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by doublemax@work »

Can you try setting the whole SVG as source with wxWebView::SetPage()?
lr83
Knows some wx things
Knows some wx things
Posts: 34
Joined: Sat Nov 28, 2020 2:15 pm
Location: France

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by lr83 »

Humm, SetPage() need an html code in a string.
So in a first try, I put the stream in a wxString like that :

Code: Select all

  wxChar* buffer=new wxChar[mos->GetSize()];

  mos->SeekO(0);
  mos->CopyTo(buffer, mos->GetSize());

  wxString page = wxString(buffer);

  m_plotWindow->SetPage(page, "");
  delete buffer;
Result is pretty funny :lol:
Attachments
funny.png
funny.png (67.3 KiB) Viewed 1662 times
User avatar
doublemax@work
Super wx Problem Solver
Super wx Problem Solver
Posts: 474
Joined: Wed Jul 29, 2020 6:06 pm
Location: NRW, Germany

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by doublemax@work »

Code: Select all

wxChar * buffer=new wxChar[mos->GetSize()];
Don't use wxChar here.

Use a char or unsigned char buffer and then:

Code: Select all

wxString page = wxString::From8BitData(buffer, mos->GetSize());
lr83
Knows some wx things
Knows some wx things
Posts: 34
Joined: Sat Nov 28, 2020 2:15 pm
Location: France

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by lr83 »

Ok, I try :

Code: Select all

  char * buffer = new char[mos->GetSize()];
  mos->SeekO(0);
  mos->CopyTo(buffer, mos->GetSize());
  wxString page = wxString::From8BitData((const char *)buffer, mos->GetSize());

//  std::cout << "Page:  " << page <<  std::endl;
  m_plotWindow->SetPage(page, "");
and I have a blank page.
Note : I have verified that page string contain well the svg code.
User avatar
doublemax@work
Super wx Problem Solver
Super wx Problem Solver
Posts: 474
Joined: Wed Jul 29, 2020 6:06 pm
Location: NRW, Germany

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by doublemax@work »

Sorry, i'm out of ideas for now. I'll need to make some tests myself, but i won't have time for that until i get home in a few hours.
lr83
Knows some wx things
Knows some wx things
Posts: 34
Joined: Sat Nov 28, 2020 2:15 pm
Location: France

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by lr83 »

Thanks :wink:
In summary :
- if I get page from the stream with LoadURL("memory:a.svg") => not work
- if I store the stream into a file and after load that file with LoadURL("path to the file") => work
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by New Pagodi »

It works on windows 10, but it may not work on windows 7. You can maybe try calling

Code: Select all

wxWebViewIE::MSWSetEmulationLevel(wxWEBVIEWIE_EMU_IE11);
That should set the IE rendering engine to use the latest version available. Maybe that latest version can render the SVG.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by doublemax »

I tested this under Windows 7 with the IE7 backend and both the "memory:a.svg" version and the "SetPage" version worked.

Is it possible that you made the calls too early? E.g. the documentation for SetPage says:
When using wxWEBVIEW_BACKEND_IE you must wait for the current page to finish loading before calling SetPage().
For my tests i put the loading code into one of the menu event handlers, and loaded the SVG from there and it worked for both variants.
Use the source, Luke!
lr83
Knows some wx things
Knows some wx things
Posts: 34
Joined: Sat Nov 28, 2020 2:15 pm
Location: France

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by lr83 »

And the winner is ... New Pagodi :lol:
I add

Code: Select all

wxWebViewIE::MSWSetEmulationLevel(wxWEBVIEWIE_EMU_IE11);
with the include <wx/msw/webview_ie.h>
and now it work :D :D
Note : I am on Win7 and have IE11 installed (but not used, I use Firefox). WxWidgets is 3.1.4

Note 2 : @doublemax : the load of the svg is complete (my modification from the first version of New Pagodi) so the call can not be too early.
BlakJak888
In need of some credit
In need of some credit
Posts: 9
Joined: Tue Mar 02, 2021 12:54 pm

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by BlakJak888 »

Could you post your final working version please.

I am getting spurious characters at the end of my SVG data which would indicate that the stream is either reading data past the EOD or ... ?
lr83
Knows some wx things
Knows some wx things
Posts: 34
Joined: Sat Nov 28, 2020 2:15 pm
Location: France

Re: Is it possible to have a gnuplot plot in wxFrame window.

Post by lr83 »

Hello

Here is the last code. Sorry I not clean it but it work :)

Code: Select all

 // For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#include <wx/webview.h>
#include <wx/process.h>
#include <wx/timer.h>
#include <wx/wfstream.h>
#include <wx/mstream.h>
#include <wx/sstream.h>
#include <wx/app.h>
#include <wx/txtstrm.h>
//#include <wx/webview.h>
#include <wx/msw/webview_ie.h>
#include <wx/webviewfshandler.h>
#include <wx/fs_mem.h>

class MainWindow : public wxFrame
{
    public:
        MainWindow(wxWindow* parent, int id = wxID_ANY,
                   wxString title = "demo",
                   wxPoint pos = wxDefaultPosition, wxSize size = wxSize(700,600),
                   int style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL);
        ~MainWindow();
        void SendCommand(const wxString&);
        void GnuDraw();
    private:
        void OnCommandEntered(wxCommandEvent& event);
        void OnIdleTimer(wxTimerEvent& event);
        void OnIdle(wxIdleEvent& event);
        void OnProcessTerminated(wxProcessEvent& event);

        bool HasInput();

        wxWebView* m_plotWindow;
        wxTextCtrl* m_log;
        wxTimer m_timerIdleWakeUp;
        wxProcess m_process;
        bool m_isRunning;
        bool m_svgLoaded;


        wxMemoryOutputStream* mos;
        bool HasGnuDraw = false;

        int count = 0;
};

MainWindow::MainWindow(wxWindow* parent, int id, wxString title, wxPoint pos,
                       wxSize size, int style)
           :wxFrame(parent, id, title, pos, size, style),
            m_process(this)
{
    wxPanel* panel = new wxPanel(this,wxID_ANY);

    m_plotWindow = wxWebView::New(panel, wxID_ANY, wxWebViewDefaultURLStr);

//    wxWebView* itemHtmlWindow3 = wxWebView::New(panel, ID_HTMLWINDOW, str, wxDefaultPosition,
//						wxSize(800, 600),wxWebViewBackendDefault, 0);



    m_log = new wxTextCtrl(panel, wxID_ANY, wxEmptyString,
                           wxDefaultPosition, wxDefaultSize,
                           wxTE_MULTILINE|wxTE_DONTWRAP|wxTE_READONLY);

    wxTextCtrl* commandWindow =
        new wxTextCtrl(panel, wxID_ANY, "plot sin(x)",
                       wxDefaultPosition,wxDefaultSize,
                       wxTE_MULTILINE|wxTE_DONTWRAP|wxTE_PROCESS_ENTER);

    wxBoxSizer* szr = new wxBoxSizer(wxVERTICAL);
    szr->Add(commandWindow,wxSizerFlags(1).Expand().Border(wxALL));
    szr->Add(m_log,wxSizerFlags(1).Expand().Border(wxALL));
    szr->Add(m_plotWindow,wxSizerFlags(4).Expand().Border(wxALL));

    panel->SetSizer(szr);
    panel->Layout();

    Bind(wxEVT_IDLE, &MainWindow::OnIdle, this);
    Bind(wxEVT_TIMER, &MainWindow::OnIdleTimer, this);
    Bind(wxEVT_END_PROCESS, &MainWindow::OnProcessTerminated, this);
    commandWindow->Bind(wxEVT_TEXT_ENTER,&MainWindow::OnCommandEntered, this);

    m_process.Redirect();
    if ( !wxExecute("gnuplot", wxEXEC_ASYNC, &m_process) )
    {
        m_log->AppendText("Unable to gnuplot.\n");
        m_isRunning = false;
    }
    else
    {
        m_isRunning = true;
        int pid = m_process.GetPid();
        m_log->AppendText(
            wxString::Format("Process spawned with PID %d.\n", pid));
        SendCommand("set terminal svg mouse standalone");  //
        commandWindow->SetFocus();
    }

    m_svgLoaded = false;
    wxFileSystem::AddHandler(new wxMemoryFSHandler);
    m_plotWindow->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));

    mos = new wxMemoryOutputStream();

    wxWebViewIE::MSWSetEmulationLevel(wxWEBVIEWIE_EMU_IE11);
}

MainWindow::~MainWindow()
{
    SendCommand("quit");
}

void MainWindow::OnCommandEntered(wxCommandEvent& event)
{
    wxTextCtrl* commandWin = wxDynamicCast(event.GetEventObject(), wxTextCtrl);
    if ( commandWin )
    {
        wxString s = commandWin->GetValue();
        commandWin->Clear();

	count = 0;
	// Delete and recreate a Memory Output Stream
	// because a don't know how to clear the existing
	delete mos;
	mos = new wxMemoryOutputStream();
	HasGnuDraw = false;

        SendCommand(s);
    }
}

void MainWindow::OnIdleTimer(wxTimerEvent& WXUNUSED(event))
{
    wxWakeUpIdle();
}

void MainWindow::OnIdle(wxIdleEvent& event)
{
    if ( HasInput() )
    {
        event.RequestMore();
    }
    else
      {
	if (HasGnuDraw)
	{
	    HasGnuDraw = false;
//	  std::cout << "DRAW:  " << count <<  std::endl;
	  GnuDraw();
	}
      }
}

void MainWindow::OnProcessTerminated(wxProcessEvent& event)
{
    if ( event.GetPid() == m_process.GetPid() )
    {
        while ( HasInput() )
            ;

        m_timerIdleWakeUp.Stop();
        m_isRunning = false;
        m_log->AppendText("gnuplot has terminated.\n");
    }
}

bool MainWindow::HasInput()
{
    bool readMore = false;

    int sz = 10*1024*1024;
    unsigned char* buffer = new unsigned char[sz];

    if ( m_process.IsErrorAvailable() )
    {
        wxTextInputStream tis(*(m_process.GetErrorStream()));

        wxString msg = tis.ReadLine();
        msg << "\n";

        m_log->AppendText(msg);

        readMore = true;
    }

    if ( m_process.IsInputAvailable() )
    {
//        wxFile css_file("output.svg", wxFile::write_append);

        int lastRead = -1;
        bool tryAgain = true;

        while ( tryAgain )
        {
            m_process.GetInputStream()->Read(buffer,sz);
            lastRead = m_process.GetInputStream()->LastRead();
            mos->Write(buffer,lastRead);
//            css_file.Write(buffer,lastRead);
            tryAgain = ( lastRead == sz );
        }

//        css_file.Close();


        count++;
//        std::cout << "Receive:  " << count <<  std::endl;

        readMore = true;
        HasGnuDraw = true;
    }

    delete[] buffer;

    return readMore;
}

void MainWindow::GnuDraw()
{
//  unsigned char buffer[] = "\r\n";
//  mos->Write(buffer,2);

  int fullSize = mos->GetOutputStreamBuffer()->GetBufferSize();
  void* fullBuffer = mos->GetOutputStreamBuffer()->GetBufferStart();

  if ( m_svgLoaded )
  {
      wxMemoryFSHandler::RemoveFile("a.svg");  // svg
  }

  wxMemoryFSHandler::AddFile("a.svg", fullBuffer, fullSize);

  m_plotWindow->LoadURL("memory:a.svg");  //   E:/Logiciel/Eclipse/workspace/gnuTest/output.svg
//
//  wxString page = m_plotWindow->GetPageText();


//  wxChar* buffer=new wxChar[mos->GetSize()];
//
//  mos->SeekO(0);
//  mos->CopyTo(buffer, mos->GetSize());
//
//  wxString page = wxString(buffer);
//
////
////  std::cout << "Page:  " << page <<  std::endl;
//
//  m_plotWindow->SetPage(page, "");
//  m_plotWindow->Update();

//  const char *buffer = (const char *)mos->GetOutputStreamBuffer();  //->GetBufferStart();

//  char * buffer = new char[mos->GetSize()];
//  mos->SeekO(0);
//  mos->CopyTo(buffer, mos->GetSize());
//  wxString page = wxString::From8BitData((const char *)buffer, mos->GetSize());
////  page = page + "\r\n\r\n";
//  std::cout << "Page:  " << page <<  std::endl;
//  m_plotWindow->SetPage(page, "");
//  m_plotWindow->Update();
//
//  delete buffer;


  m_svgLoaded = true;
}


void MainWindow::SendCommand(const wxString& s)
{
    if ( m_isRunning )
    {
        wxString copyS = s;
        copyS << "\n";
        wxStringInputStream sis(copyS);
        m_process.GetOutputStream()->Write(sis);
    }
    m_log->AppendText(s+"\n");
}


class MyApp : public wxApp
{
    public:
        virtual bool OnInit()
        {
            MainWindow* frame = new MainWindow(NULL);
            frame->Show();
            return true;
        }
};

wxIMPLEMENT_APP(MyApp);
Post Reply