Page 1 of 1

Need Syntax for setting a "choice" inside wxDataViewListCtrl

Posted: Wed Jul 12, 2017 10:23 pm
by ColleenKobe
Hi. I am creating a wxDataViewListCtrl object using wxCrafter in CodeLite. My wxDataViewListCtrl object contains three columns of different types:

Column 0 is type int.
Column 1 is type "check".
Column 2 is type "choice." The possible values are: apple;banana;cantaloupe;date;eggplant;fig;grape

I have two questions.

1. I have set Column 1's Cell Mode to wxDATAVIEW_CELL_EDITABLE. However, the cell is grayed during execution. Does another flag have to be set for it to be editable? See the screen shot below.
wxDataViewListCtrl.jpg
2. I can't figure out how to initialize the values in Column 2 to anything. I can display a number in that column, but I want to display the text string corresponding to that number in the choices list. I.e. display "apple" instead of 0; display "banana" instead of 1; and so on.

What is the syntax to assign a value to a "choice" column in a wxDataViewListCtrl? See my attempts to figure out syntax in the code below.

Code: Select all

#include "MainFrame.h"
#include <wx/aboutdlg.h>

MainFrame::MainFrame(wxWindow* parent)
    : MainFrameBaseClass(parent)
{

#define QTY_ROWS    16
#define QTY_FRUITS   7

    bool        b       = false;
    int         i       = 0;
    int         j       = 0;
    unsigned int    row = 0;
    unsigned int    col = 0;
    wxString    Row_St  = "";
    wxString    Msg_St  = "";

    wxVector<wxVariant> cols;

    // This is a wxDataViewListCtrl with three columns:
    //
    //    0            1               2
    //  Index | Check or Uncheck |  Fruits
    //        |                  |
    //        |                  |
    //
    //  where the type of each is:
    //      Index: int
    //      Check or Uncheck: check
    //      Fruits is a choice. Its values are:
    //
    //          apple
    //          banana
    //          cantaloupe
    //          date
    //          eggplant
    //          fig
    //          grape

    for (i = 0; i < QTY_ROWS; i++)
    {

        cols.clear  ();                 // Clear this buffer.

                                        // Column 0: Index
        Row_St  = wxString::Format  ("%2d", i);
        cols.push_back   (Row_St);

                                        // Column 1: Check or Uncheck
        b   = (bool) ((i % 3) < 2);
        row = (unsigned int) i + 1;     // row 0 is the column header row, so skip it
        col = (unsigned int) 1;
//        m_dvListCtrl11->SetToggleValue (b, row, col);
        cols.push_back   (b);

                                        // Column 2: Fruits
                                        // What is the syntax to access a specific column's choice value?
        j = i % QTY_FRUITS;

        Row_St  = wxString::Format ("What is the syntax to display choice #%d?", j);
        cols.push_back   (b);

        m_dvListCtrl11->AppendItem  (cols);
        m_dvListCtrl11->Refresh     (true);
    }

    // Practice editing fields manually....
    m_dvListCtrl11->SetValue 	(false, (unsigned int)  1,	(unsigned int)  1);
    m_dvListCtrl11->SetValue 	(false, (unsigned int)  2,	(unsigned int)  1);
    m_dvListCtrl11->SetValue 	(false, (unsigned int)  3,	(unsigned int)  1);
    m_dvListCtrl11->SetValue 	(true,  (unsigned int)  4,	(unsigned int)  1);
    m_dvListCtrl11->SetValue 	(false, (unsigned int)  5,	(unsigned int)  1);
    m_dvListCtrl11->SetValue 	(false, (unsigned int)  6,	(unsigned int)  1);
    m_dvListCtrl11->SetValue 	(false, (unsigned int)  7,	(unsigned int)  1);


    // m_dvListCtrl11->SetValue ((Fruits) 3,                    (unsigned int)  7,	(unsigned int)  2);  // syntax error
    // m_dvListCtrl11->SetValue ((m_dvListCtrl11->Fruits) 3,    (unsigned int)  7,	(unsigned int)  2);  // syntax error
    m_dvListCtrl11->SetValue (3,                                (unsigned int)  7,	(unsigned int)  2);  // prints "3", not "date"

}

MainFrame::~MainFrame()
{
}

void MainFrame::OnExit(wxCommandEvent& event)
{
    wxUnusedVar(event);
    Close();
}

void MainFrame::OnAbout(wxCommandEvent& event)
{
    wxUnusedVar(event);
    wxAboutDialogInfo info;
    info.SetCopyright(_("My MainFrame"));
    info.SetLicence(_("GPL v2 or later"));
    info.SetDescription(_("Short description goes here"));
    ::wxAboutBox(info);
}
void MainFrame::OnDvlistctrl11DataviewItemValueChanged(wxDataViewEvent& event)
{
}
void MainFrame::OnDvlistctrl11DataviewSelectionChanged(wxDataViewEvent& event)
{
}
I can also run the program, and double-click the field, and change its value in the drop-down. But I don't know how to give the field a value in code.

To solve this problem, I looked at the sample code in C:\wxWidgets\samples\dataview\dataview.cpp. I am using wxCrafter, though, and I don't know if I'm supposed to create a wxDataViewChoiceRenderer, or if that's done inside wxCrafter.

Thanks in advance for your help.

Colleen

Code: Select all

Software Versions
CodeLite    10.0.6
MinGW       hard to tell the version I have, but I downloaded it "fresh" on July 10, 2017.
Windows 10  Pro, 64-bit
wxWidgets    3.0.2
wxCrafter    2.6
Target platform   32-bit
Target build   debug

Re: Need Syntax for setting a "choice" inside wxDataViewList

Posted: Wed Jul 12, 2017 11:03 pm
by eranif
As you guessed, you should look at the dataview.cpp sample.
There are multiple examples there, you need the one that uses wxDataViewListCtrl (the renderer is needed for custom drawings)
Specifically, look at the function "BuildDataViewCtrl()" where nPanel=2 (should be around line 701)

Eran

Re: Need Syntax for setting a "choice" inside wxDataViewList

Posted: Thu Jul 13, 2017 5:48 pm
by ColleenKobe
Eran, thanks for responding so quickly.

In dataview.cpp, I believe the code that builds the second tab--which is the tab showing the wxDataViewListCtrl--is this:

Code: Select all

    case 2:
        {
            wxASSERT(!m_ctrl[2]);
            wxDataViewListCtrl* lc =
                new wxDataViewListCtrl( parent, wxID_ANY, wxDefaultPosition,
                                        wxDefaultSize, style );
            m_ctrl[2] = lc;

            MyListStoreDerivedModel* page2_model = new MyListStoreDerivedModel();
            lc->AssociateModel(page2_model);
            page2_model->DecRef();

            lc->AppendToggleColumn( "Toggle" );
            lc->AppendTextColumn( "Text" );
            lc->AppendProgressColumn( "Progress" );

            wxVector<wxVariant> data;
            for (unsigned int i=0; i<10; i++)
            {
                data.clear();
                data.push_back( (i%3) == 0 );
                data.push_back( wxString::Format("row %d", i) );
                data.push_back( long(5*i) );

                lc->AppendItem( data );
            }
        }
        break;
Regarding building the row values.

I see how the row entries for column 0, the "toggle" column, is built by feeding a boolean into the data.push_back statement, and the renderer translates the boolean into either an empty or a full checkbox.

I see how the row entries for column 1, a text field, is built by sending a string into push_back.

And column 2's string is a progress column, so sending a number into push_back makes sense because a progress column essentially displays a number, rendered as a progress bar.

But I'm asking about what to enter if one of those columns had been a choice field. A choice is essentially a number, too, with the choice being desired selection number. I had thought that by sending an integer into the push_back statement, I'd see the desired choice selection appear in the field. But what actually appears is the number I sent in.

What do I need to send into the push_back to select and display the desired choice selection?

Also, in the example, in column 1, the last two rows, the "toggle" field values are grayed. I studied the code, but I can't see where that happened. How did the two last rows of the checkbox get grayed?
Grayed Toggles.jpg
The reason I ask is because all my checkboxes are grayed, and I don't know why. I'm hoping that by finding out how the example's were grayed, I can use the same technique to un-gray mine.

Re: Need Syntax for setting a "choice" inside wxDataViewList

Posted: Thu Jul 20, 2017 11:21 pm
by ColleenKobe
I found answers to my concerns above. I'm recording them here hoping that someone else may find these answers useful someday.

1. Question: how do I set an initial value in a wxDataViewListCtrl "choice" field?

Answer: I could not find an argument for the x.push_back statement that would display the text in the choices list. So, I displayed the text manually.

From an overview perspective: I created a database in the "background" that contained all the values I wanted to display. When it was time to format and display them, I transferred the data into the wxWidgets screen fields.

The details. First, I made an enumerated type for the "choice" field.

Code: Select all

#define QTY_TTS   9
    enum    t_TT_Type
    {
        tt_Pressure_Gauge,
        tt_Ref_Temp,
        tt_Resistance,
        tt_RTD,
        tt_Strain_Gauge,
        tt_Thermistor,
        tt_Thermocouple,
        tt_Thin_Film_RTD,
        tt_Other
    };
The enumerated type was part of a larger structure (#2):

Code: Select all

    typedef struct  t_Channel_Data
    {
        t_CH_Type   Ch_Number;                                          //  0
        bool        Do_Capture_Data;                                    //  1
        t_TT_Type   TT;                                                 //  2
        wxString    Name_st;                                            //  3
   // [snip]
        int         Spare02;              // Placeholder for growth.    // 16
        int         Spare01;              // Placeholder for growth.    // 17
    }   t_Channel_Record;   // structure_type_Channel_Data
And the larger structure was an array. Each array element corresponded to one row in the wxDataViewListCtrl.

Code: Select all

#define QTY_CHANNELS 120

static Global_Data_Class::t_Channel_Record Edited_Ch_Data [QTY_CHANNELS];
Then I made a lookup table of wxStrings corresponding to each element in the choices list.

Code: Select all

// -----------------------------------------------------------------------------
wxString Global_Data_Class::Get_TRANSDUCERS_AS_STRINGS (int i)
// -----------------------------------------------------------------------------
{
    static  wxString TRANSDUCERS_AS_STRINGS [QTY_TTS]    =
       {"Pressure Gauge",
        "Reference Temp",
        "Resistance",
        "RTD",
        "Strain Gauge",
        "Thermistor",
        "Thermocouple",
        "Thin Film RTD",
        "Other"};

    return  (TRANSDUCERS_AS_STRINGS  [i]);
}
When it came time to display the text in the field, I called the lookup table routine, using the current value as the argument.

Code: Select all

void Edit_Channels_Class::Build_One_Ch_Cfg_Row (int ch)
{
    int         j       = 0;
   // [snip]
    Global_Data_Class::t_Channel_Data  T;

    static wxVector<wxVariant> cols;

    cols.clear  ();                     // Clear the buffer.

    // -------------------------------------------------------------------------
    //  Load the Channel Configuration Data row.
    //  Enter these values in the sequence in which they appear on the screen.
    // -------------------------------------------------------------------------

    T.Ch_Number  = Local_GD_Ptr->Get_Edited_Ch_Data_Ch_Number (ch);
    cols.push_back  (Local_GD_Ptr->Get_CHANNELS_AS_STRINGS ((int) T.Ch_Number));    //     0      Channel #           choice

    cols.push_back  (Local_GD_Ptr->Get_Edited_Ch_Data_Do_Capture_Data(ch));         //     1      Data Capture On?    toggle

    T.TT            = Local_GD_Ptr->Get_Edited_Ch_Data_TT (ch);
    cols.push_back  (Local_GD_Ptr->Get_TRANSDUCERS_AS_STRINGS ((int) T.TT));        //     2      Transducer Type     choice

   // [snip]

    m_dvListCtrl_Channel_Data->AppendItem   (cols);

   // [snip]
Yes, it was a ton of overhead just to consistently display the values of a choice field. But this approach appeared to produce the fastest executable code, which is critical for this application.

Here is a screen shot of the page:
Edit_Channel_Page.jpg
2. Question: what made my checkboxes initially grayed (which I did not want)?

Answer: The checkboxes were initially grayed because I was using the wrong Cell Mode flag. I was using wxDATAVIEW_CELL_EDITABLE. I *should* have been using wxDATAVIEW_CELL_ACTIVATABLE.

I hope this helps out someone else.

Colleen