wxDataViewListCtrl and wxVariant Topic is solved

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.
refaelsh
Earned a small fee
Earned a small fee
Posts: 20
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh » Thu Feb 07, 2019 9:07 am

doublemax wrote:When does it crash? Directly at the start?

I tested with this code and it worked fine:

Code: Select all

#include <wx/wxprec.h>
#include <wx/dataview.h>
#include <wx/wx.h>

class MyCustomRenderer : public wxDataViewCustomRenderer
{
public:

  MyCustomRenderer(const wxString &varianttype = "string", wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT )
    :wxDataViewCustomRenderer(varianttype, mode, align )
  {
  };

  bool SetValue(const wxVariant& value)
  {
     if (value.IsNull() == true)
     {
        return false;
     }

     return true;
  }

  bool GetValue(wxVariant& value) const
  {
     return true;
  }

  wxSize GetSize() const
  {
     return wxSize(42, 42);
  }

  bool Render(wxRect cell, wxDC* dc, int state)
  {
     // Do lots of stuff here ...   

     return true;
  }
};


class MyApp : public wxApp
{
public:
   virtual bool OnInit();
};

class MyFrame : public wxFrame
{
public:
   MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
   MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
   frame->Show(true);
   return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
   : wxFrame(NULL, wxID_ANY, title, pos, size)
{
   wxDataViewListCtrl* data_view_list_ctrl = new wxDataViewListCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxDV_ROW_LINES | wxDV_SINGLE);

   MyCustomRenderer* custom_renderer = new MyCustomRenderer();
   wxDataViewColumn* data_view_column = new wxDataViewColumn("Some title goes here", custom_renderer,0);
   data_view_list_ctrl->AppendColumn(data_view_column);
   data_view_list_ctrl->AppendTextColumn("Some cool column title goes here");

   wxVector<wxVariant> data;
   data.push_back(wxVariant(42));
   data.push_back(wxVariant("row 1"));
   data_view_list_ctrl->AppendItem(data);

   data.clear();
   data.push_back(wxVariant(43));
   data.push_back(wxVariant("row 3"));
   data_view_list_ctrl->AppendItem(data);
}
In `MyCustomRenderer::SetValue()`, the statement `value.IsNull()` is always true. In the original code (I simplified it for the mcve), this part looked like this:

Code: Select all

bool MyCustomRenderer::SetValue(const wxVariant& value)
{
	MyClass* temp = static_cast<MyClass*>(value.GetWxObjectPtr());

	m_my_class = MyClass(temp->m_nodes, m_radius);

	return true;
}
It would crash on the first line `MyClass* temp = static_cast<MyClass*>(value.GetWxObjectPtr());`.

User avatar
doublemax
Moderator
Moderator
Posts: 14316
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewListCtrl and wxVariant

Post by doublemax » Thu Feb 07, 2019 9:39 am

I don't have a working sample that uses a wxObject type (do you actually need this?).

But here's one that uses void* as data, maybe this helps:

Code: Select all

#include <wx/wxprec.h>
#include <wx/dataview.h>
#include <wx/wx.h>

class MyCustomRenderer : public wxDataViewCustomRenderer
{
public:

  MyCustomRenderer(const wxString &varianttype = "void*", wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT )
    :wxDataViewCustomRenderer(varianttype, mode, align )
  {
  };

  bool SetValue(const wxVariant& value)
  {
    m_value = static_cast<void *>(value.GetVoidPtr());
    wxLogDebug("temp=%p", m_value );

    return true;
  }

  bool GetValue(wxVariant& value) const
  {
     value = (void*)NULL;
     return true;
  }

  wxSize GetSize() const
  {
     return wxSize(42, 42);
  }

  bool Render(wxRect rect, wxDC* dc, int state)
  {
    dc->SetBrush( *wxLIGHT_GREY_BRUSH );
    dc->SetPen( *wxTRANSPARENT_PEN );

    rect.Deflate(2);
    dc->DrawRoundedRectangle( rect, 5 );

    wxString s;
    s.Printf("%p", m_value );
    RenderText(s,
                0, // no offset
                wxRect(dc->GetTextExtent(s)).CentreIn(rect),
                dc,
                state);
    return true;
  }

protected:
  void *m_value;
};


class MyApp : public wxApp
{
public:
   virtual bool OnInit();
};

class MyFrame : public wxFrame
{
public:
   MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
   MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
   frame->Show(true);
   return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
   : wxFrame(NULL, wxID_ANY, title, pos, size)
{
   wxDataViewListCtrl* data_view_list_ctrl = new wxDataViewListCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxDV_ROW_LINES | wxDV_SINGLE);

   MyCustomRenderer* custom_renderer = new MyCustomRenderer();
   wxDataViewColumn* data_view_column = new wxDataViewColumn("Some title goes here", custom_renderer,0);
   data_view_list_ctrl->AppendColumn(data_view_column);
   data_view_list_ctrl->AppendTextColumn("Some cool column title goes here");

   wxVector<wxVariant> data;
   data.push_back(wxVariant((void*)0x12345678));
   data.push_back(wxVariant("row 1"));
   data_view_list_ctrl->AppendItem(data);

   data.clear();
   data.push_back(wxVariant((void*)0x87654321));
   data.push_back(wxVariant("row 3"));
   data_view_list_ctrl->AppendItem(data);
}
Use the source, Luke!

refaelsh
Earned a small fee
Earned a small fee
Posts: 20
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh » Thu Feb 07, 2019 2:40 pm

doublemax wrote:I don't have a working sample that uses a wxObject type (do you actually need this?).

But here's one that uses void* as data, maybe this helps:

Code: Select all

#include <wx/wxprec.h>
#include <wx/dataview.h>
#include <wx/wx.h>

class MyCustomRenderer : public wxDataViewCustomRenderer
{
public:

  MyCustomRenderer(const wxString &varianttype = "void*", wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT )
    :wxDataViewCustomRenderer(varianttype, mode, align )
  {
  };

  bool SetValue(const wxVariant& value)
  {
    m_value = static_cast<void *>(value.GetVoidPtr());
    wxLogDebug("temp=%p", m_value );

    return true;
  }

  bool GetValue(wxVariant& value) const
  {
     value = (void*)NULL;
     return true;
  }

  wxSize GetSize() const
  {
     return wxSize(42, 42);
  }

  bool Render(wxRect rect, wxDC* dc, int state)
  {
    dc->SetBrush( *wxLIGHT_GREY_BRUSH );
    dc->SetPen( *wxTRANSPARENT_PEN );

    rect.Deflate(2);
    dc->DrawRoundedRectangle( rect, 5 );

    wxString s;
    s.Printf("%p", m_value );
    RenderText(s,
                0, // no offset
                wxRect(dc->GetTextExtent(s)).CentreIn(rect),
                dc,
                state);
    return true;
  }

protected:
  void *m_value;
};


class MyApp : public wxApp
{
public:
   virtual bool OnInit();
};

class MyFrame : public wxFrame
{
public:
   MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
   MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
   frame->Show(true);
   return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
   : wxFrame(NULL, wxID_ANY, title, pos, size)
{
   wxDataViewListCtrl* data_view_list_ctrl = new wxDataViewListCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxDV_ROW_LINES | wxDV_SINGLE);

   MyCustomRenderer* custom_renderer = new MyCustomRenderer();
   wxDataViewColumn* data_view_column = new wxDataViewColumn("Some title goes here", custom_renderer,0);
   data_view_list_ctrl->AppendColumn(data_view_column);
   data_view_list_ctrl->AppendTextColumn("Some cool column title goes here");

   wxVector<wxVariant> data;
   data.push_back(wxVariant((void*)0x12345678));
   data.push_back(wxVariant("row 1"));
   data_view_list_ctrl->AppendItem(data);

   data.clear();
   data.push_back(wxVariant((void*)0x87654321));
   data.push_back(wxVariant("row 3"));
   data_view_list_ctrl->AppendItem(data);
}
That worked!
I've made the following changes:

Code: Select all

MyCustomRenderer::MyCustomRenderer() : wxDataViewCustomRenderer("void*", wxDATAVIEW_CELL_INERT, wxALIGN_CENTER)
And this:

Code: Select all

item.push_back(wxVariant(static_cast<void*>(/*Raw pointer to an instance of MyClass*/)));
And now it works in version 3.1.2.

Thank you and every other responder very much!

Post Reply