wxGridCellEnumRenderer not working

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
mbeardsley
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Sep 25, 2014 7:40 pm

wxGridCellEnumRenderer not working

Post by mbeardsley »

I can't seem to get wxGridCellEnumRenderer to do anything. Perhaps I am missing an important step?

I want to have the user choose between options of "Left", "Right", "Up", or "Down", and have the cell rendered as such (with the "actual" cell values being 0,1,2, or 3. This seems to be what the wxGridCellEnumRenderer and wxGridCellEnumEditor are for.

The wxGridCellEnumEditor seems to work fine, the user is presented with the "wordy" choices when the cell is selected. However, when the user selects a different cell, the selection is shown as 0 through 3 instead of the words.

I see the same problem in the wxGrid sample if I add my code to it (the sample does not have an example of wxGridCellEnumEditor / wxGridCellEnumRenderer).

I added the following lines to the Frame's constructor (at line 555):

grid->SetCellEditor(8, 0, new wxGridCellEnumEditor("Left,Right,Up,Down"));
grid->SetCellRenderer(8, 0, new wxGridCellEnumRenderer("Left,Right,Up,Down"));
grid->SetCellValue(8, 0, "0");

I don't know what else would be required to make the renderer operate. The second line above seems to do nothing (if I comment it out I get the exact same behavior).

Any ideas?

I am using VisualStudio 2010 with wxWidgets 3.02 on Win7.
mbeardsley
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Sep 25, 2014 7:40 pm

Re: wxGridCellEnumRenderer not working

Post by mbeardsley »

After further investigation, I have found what I think to be the problem.

The code for wxGridCellEnumRenderer::GetString is as follows:

Code: Select all

wxString wxGridCellEnumRenderer::GetString(const wxGrid& grid, int row, int col)
{
    wxGridTableBase *table = grid.GetTable();
    wxString text;
    if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
    {
        int choiceno = table->GetValueAsLong(row, col);
        text.Printf(wxT("%s"), m_choices[ choiceno ].c_str() );
    }
    else
    {
        text = table->GetValue(row, col);
    }

    //If we faild to parse string just show what we where given?
    return text;
}
The problem here is the CanGetValueAs() call is failing, as the wxGridTableBase class says that it can only get values as strings.
I suspect that if I derive a new wxGrid class and override CanGetValueAs() and GetValueAsLong(), then this would work.

This seems like a lot of work just to get functionality that should be present already.

I would think that a better implementation of wxGridCellEnumRenderer::GetString would be something like :

Code: Select all

wxString wxGridCellEnumRenderer::GetString(const wxGrid& grid, int row, int col)
{
    wxGridTableBase *table = grid.GetTable();
    wxString text;
    long choiceno;

    if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
    {
        choiceno = table->GetValueAsLong(row, col);
    }
    else
    {
        table->GetValue(row, col).ToLong( &choiceno );
    }

    text.Printf(wxT("%s"), m_choices[ choiceno ].c_str() );

    return text;
}
This would still allow custom handling for those that want/need to override GetValueAsLong(), but would allow the wxGridCellEnumRenderer to work on a "standard" wxGrid.

Even if this is not acceptable for some reason, at minimum, the documentation for wxGridCellEnumRenderer should mention that it will not work on a "standard" wxGrid, but only on a derived type that has CanGetValueAs() and GetValueAsLong() overridden to provide useful values.

I think what I will do is create a new class derived from wxGridCellEnumRenderer with the GetString() function overridden as I have shown above. This will be simpler for me (I think) than deriving a new class from wxGrid.
mbeardsley
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Sep 25, 2014 7:40 pm

Re: wxGridCellEnumRenderer not working

Post by mbeardsley »

Well, I thought that I could simply override GetString(), unfortunately, GetString is not defined as virtual in wxGridCellEnumRenderer.

So, I guess that I will have to override the whole Draw() method instead. This is getting messier each step of the way.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxGridCellEnumRenderer not working

Post by doublemax »

Can you use wxGridCellChoiceEditor? The "grid" demo shows it in action.
Use the source, Luke!
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxGridCellEnumRenderer not working

Post by doublemax »

Code: Select all

    const wxString choices = "left,right,up,down";
    grid->SetCellEditor(4, 0, new wxGridCellEnumEditor(choices));
    grid->SetCellRenderer(4, 0, new wxGridCellEnumRenderer(choices));
    grid->SetCellSize(4, 0, 1, 2);
    grid->SetCellValue(4, 0, "up");
    grid->SetCellOverflow(4, 0, false);
This works for me when replacing the part with the wxGridChoiceEditor from the "grid" sample.
Use the source, Luke!
mbeardsley
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Sep 25, 2014 7:40 pm

Re: wxGridCellEnumRenderer not working

Post by mbeardsley »

No, that doesn't really work, I think you need to examine that a bit more closely.

The editor part works fine, but once you edit the cell (and then move on to some other cell), you are left with a "digit" in the cell instead of the actual words. In your case, the cell starts out with a word, only because you "cheated" and initialized the cell with "up" (instead of the value "2" which would be expected).

And if you notice, you'll get the exact same behavior if you comment out the SetCellRenderer() call - which shows that the Renderer is not really accomplishing anything useful.

And yes, I COULD use wxGridCellChoiceEditor/Renderer, but then I would have to do the manual conversion between enums and their words - which is exactly what wxGridCellEnum is supposed to be for.

I did override the Draw of wxGridCellEnumRenderer (as I described above) and that makes it all work as expected. It just seems that this should be done in the wxWidgets source (or at least explained in the documentation that there are additional hoops that need to be jumped through).

In any case, thanks for the input - I do appreciate it.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxGridCellEnumRenderer not working

Post by doublemax »

Yes, you're right. Sorry about that.

This looks like a bug to me. Maybe you should open a ticket at http://trac.wxwidgets.org
Use the source, Luke!
mbeardsley
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Sep 25, 2014 7:40 pm

Re: wxGridCellEnumRenderer not working

Post by mbeardsley »

Ticket #18336 created for this issue.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7458
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxGridCellEnumRenderer not working

Post by ONEEYEMAN »

Hi.
mbeardsley wrote: No, that doesn't really work, I think you need to examine that a bit more closely.

The editor part works fine, but once you edit the cell (and then move on to some other cell), you are left with a "digit" in the cell instead of the actual words. In your case, the cell starts out with a word, only because you "cheated" and initialized the cell with "up" (instead of the value "2" which would be expected).
doublemax didn't cheat.
wxGreidChoiceEditor works just like wxComboBox.

In this control you initialize it with the actual choice and not the numeric value.

Now, the behavior you describe with the CellEnumRenderer is also correct.
In C++ (and C) there is no actual enum type/variable. All enum keyword does is set the number 0,1,2,... to become some meaningful constants that are somehow connected to each other.

This works exactly the same way.
mbeardsley wrote: And if you notice, you'll get the exact same behavior if you comment out the SetCellRenderer() call - which shows that the Renderer is not really accomplishing anything useful.
The renderer does do something useful - it knowsd how to display the data in a cell, especially if you define your own grid table.
mbeardsley wrote: And yes, I COULD use wxGridCellChoiceEditor/Renderer, but then I would have to do the manual conversion between enums and their words - which is exactly what wxGridCellEnum is supposed to be for.
No, you don't. You have access to the underlying wxComboBox, and then all you do is call GetSelection() (or something like this).
I don't think there is a bug, just a documentation issue, but I will let Vadim decide.

Thank you.
mbeardsley wrote: I did override the Draw of wxGridCellEnumRenderer (as I described above) and that makes it all work as expected. It just seems that this should be done in the wxWidgets source (or at least explained in the documentation that there are additional hoops that need to be jumped through).

In any case, thanks for the input - I do appreciate it.
mbeardsley
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Sep 25, 2014 7:40 pm

Re: wxGridCellEnumRenderer not working

Post by mbeardsley »

It doesn't seem like you quite understand the issue.

wxGridCellEnumRenderer does NOT work correctly on a wxGrid, UNLESS you either :
1) derive a new class from wxGrid and override the CanGetValueAs() and GetValueAsLong() methods
2) derive a new class from wxGridCellEnumRenderer and override the Draw() method (which is what I did in my case)

wxGridCellEnumEditor DOES work correctly, mainly because it is derived from wxGridCellChoiceEditor (which is doing most of the work here), but wxGridCellEnumRenderer does not.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7458
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxGridCellEnumRenderer not working

Post by ONEEYEMAN »

Hi,
As I tried to explain it - wxGridCellEnumRenderer works exactly as it should because it renders the enum value (which is 0,1,2,...).
As a reference - look here.

Enumeration is nothing more than explicitly named constant.

If you want the actual string - use choice editor/renderer.

Thank you.
mbeardsley
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Sep 25, 2014 7:40 pm

Re: wxGridCellEnumRenderer not working

Post by mbeardsley »

Thank you for the wonderful (but irrelevant) reference on enums, but I am quite aware of what an enum is - and it has very little to do with the issue at hand.

If wxGridCellEnumRenderer is supposed to render a digit instead of the text associated with that digit (as you seem to think), then why would it's constructor need to have a list of the text choices?

Furthermore, if it WAS supposed to render the digit, then wxGridCellEnumRenderer would not be needed at all - as this is what the default renderer would be drawing anyway.

As it stands now, wxGridCellEnumRenderer does exactly the same thing as the default renderer on a regular wxGrid - making it either worthless or bugged.

I think you are confused and/or mistaken as to the purpose of wxGridCellEnumEditor and wxGridCellEnumRenderer.

In any case, I have it working now as expected, by overriding the Draw method of wxGridCellEnumRenderer.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7458
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxGridCellEnumRenderer not working

Post by ONEEYEMAN »

Hi,
mbeardsley wrote: Thank you for the wonderful (but irrelevant) reference on enums, but I am quite aware of what an enum is - and it has very little to do with the issue at hand.
You are welcome.
mbeardsley wrote: If wxGridCellEnumRenderer is supposed to render a digit instead of the text associated with that digit (as you seem to think), then why would it's constructor need to have a list of the text choices?

Furthermore, if it WAS supposed to render the digit, then wxGridCellEnumRenderer would not be needed at all - as this is what the default renderer would be drawing anyway.

As it stands now, wxGridCellEnumRenderer does exactly the same thing as the default renderer on a regular wxGrid - making it either worthless or bugged.

I think you are confused and/or mistaken as to the purpose of wxGridCellEnumEditor and wxGridCellEnumRenderer.

In any case, I have it working now as expected, by overriding the Draw method of wxGridCellEnumRenderer.
First of all - did you look at the documentation?

It clearly states:
This class may be used to render in a cell a number as a textual equivalent.
in https://docs.wxwidgets.org/trunk/classw ... derer.html.

Second - where there is a renderer for the grid cell, there is an editor for it.

So according to the documentation quoted above - editor presents a textual choices and renderer renders them as selection.

If you want to present the actual text to the user and not the meaningless number - use Choice{Editor,Renderer} as doublemax suggested.

Thank you.
mbeardsley
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Sep 25, 2014 7:40 pm

Re: wxGridCellEnumRenderer not working

Post by mbeardsley »

As I said, you seem to be confused about the purpose/intent of wxGridCellEnumRenderer.

Yes, I HAVE read the documentation. For example, the documentation for wxGridCellEnumRenderer states :
This class may be used to render in a cell a number as a textual equivalent.

The corresponding text strings are specified as comma-separated items in the string passed to this renderer ctor or SetParameters() method. For example, if this string is "John,Fred,Bob" the cell will be rendered as "John", "Fred" or "Bob" if its contents is 0, 1 or 2 respectively.
If the cell contains a "1" the cell SHOULD be rendered as "Fred" (which is what wxGridCellEnumEditor does correctly), but wxGridCellEnumRenderer INCORRECTLY renders the cell as "1".

I have explained this as best I can in several ways now. I have a fix that corrects the issue, and I have tried to provide it in good faith. Either you are incapable of understanding the problem/issue, or you are simply trolling me at this point. Either way, I am done with this now.
Post Reply