wxGrid cell attributes question

I'm designing a grid using a custom data table. I'm currently trying to add editing capabilities to
the grid and have run into a problem. I've attached a code snippet which shows the approach I've
tried.

First some background. I have the following requirements for a grid:

Some cells need non-default text attributes: e.g., the text color should be set to red. I can do
this by overriding the GetAttr method of my wxPyGridTableBase-derived class. For some columns, I'm
using a wxGridCellChoiceEditor so that the user is presented with a set of legal values to choose
from. The nature of the grid data model is such that the legal values for any given cell in a column
may be unique. So I have to create a unique editor object for each cell. I want to create the
editors 'as needed', so I've tried doing this in the OnSelectCell method of my wxGrid class, using
the wxGrid.SetCellEditor method. This worked fine until I overrode GetAttr in the wxPyGridTableBase
class. When I did that, a default editor was used instead of the choice editor created in the
OnSelectCell method.

I tried passing a reference to the editor created in the OnSelectCell method to the GetAttr method,
and then used this reference in a call to the wxGridCellAttr.SetEditor method, but that caused a
'type error' exception.

I'm currently at a loss for things to try. Any suggestions would be greatly appreciated.

Thanks in advance,

Rad Widmer

grid_attr_problem.py (703 Bytes)

Rad Widmer wrote:

I'm designing a grid using a custom data table. I'm currently trying to add editing capabilities to
the grid and have run into a problem. I've attached a code snippet which shows the approach I've
tried.

First some background. I have the following requirements for a grid:

Some cells need non-default text attributes: e.g., the text color should be set to red. I can do
this by overriding the GetAttr method of my wxPyGridTableBase-derived class. For some columns, I'm
using a wxGridCellChoiceEditor so that the user is presented with a set of legal values to choose
from. The nature of the grid data model is such that the legal values for any given cell in a column
may be unique. So I have to create a unique editor object for each cell. I want to create the
editors 'as needed', so I've tried doing this in the OnSelectCell method of my wxGrid class, using
the wxGrid.SetCellEditor method. This worked fine until I overrode GetAttr in the wxPyGridTableBase
class. When I did that, a default editor was used instead of the choice editor created in the
OnSelectCell method.

The cell editor is one of the attributes that is contained in wxGridCellAttr and that can be returned by GetAttr, and since you are not setting it in GetAttr then you are getting the default editor. When you call grid.SetCellEditor then it will be blended with other attributes returned by the default table.GetAttr, but yours is not doing that.

You've got two options:

* Move the someCondition test and determineNamesForThisCell into the GetAttr method and create the editor as needed there, setting it into the attr object returned.

* Get the default attributes for the cell and merge your red setting into that. Something like this perhaps:

     def GetAttr(self, row, col, kind):
         if someOtherCondition:
             # set this cell's text colour to Red
             attr = wxGridCellAttr()
             defattr = self.GetAttrProvider().GetAttr(row, col, kind)
             if defattr is not None:
                 attr.MergeWith(defattr)
             attr.SetTextColour(wxRED)
             return attr
         return None

I tried passing a reference to the editor created in the OnSelectCell method to the GetAttr method,
and then used this reference in a call to the wxGridCellAttr.SetEditor method, but that caused a
'type error' exception.

GetAttr is called from within the wxGrid C++ code, you can't cause it to pass extra parameters to the function.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Thanks Robin. The second option (using an Attr Provider) works well for me. I was reluctant to use
the first option (create the editor in GetAttr) for efficiency reasons. I only want to create an
editor when it is really needed (when a user selects a cell). After rearranging the logic a bit, I
ended up with something like the following:

class MyGrid(wxGrid):
    def __init__(self, parent, table):
        wxGrid.__init__(self, parent, -1)
        self.SetTable(table, True)
        # create an attr provider and tell the table about it
        self._attrProvider = wxGridCellAttrProvider()
        table.SetAttrProvider(self._attrProvider)

    def OnSelectCell(self, evt):
        if someCondition:
            names = determineNamesForThisCell()
            editor = wxGridCellChoiceEditor(names, False)
            attr = wxGridCellAttr()
            attr.SetEditor(editor)
            self._attrProvider.SetAttr(attr, row, col)
        evt.Skip()

class MyGridTable(wxPyGridTableBase):
    def GetAttr(self, row, col, kind):
        attr = wxGridCellAttr()
        defattr = self.GetAttrProvider().GetAttr(row, col, kind)
        if defattr is not None:
            attr.MergeWith(defattr)
        if someOtherCondition:
            attr.SetTextColour(wxRED)
        return attr

Rad Widmer

···

----- Original Message -----
From: "Robin Dunn" <robin@alldunn.com>
To: <wxPython-users@lists.wxwidgets.org>
Sent: Monday, May 24, 2004 12:48 PM
Subject: Re: [wxPython-users] wxGrid cell attributes question

Rad Widmer wrote:
> I'm designing a grid using a custom data table. I'm currently trying to add editing capabilities

to

> the grid and have run into a problem. I've attached a code snippet which shows the approach I've
> tried.
>
> First some background. I have the following requirements for a grid:
>
> Some cells need non-default text attributes: e.g., the text color should be set to red. I can do
> this by overriding the GetAttr method of my wxPyGridTableBase-derived class. For some columns,

I'm

> using a wxGridCellChoiceEditor so that the user is presented with a set of legal values to

choose

> from. The nature of the grid data model is such that the legal values for any given cell in a

column

> may be unique. So I have to create a unique editor object for each cell. I want to create the
> editors 'as needed', so I've tried doing this in the OnSelectCell method of my wxGrid class,

using

> the wxGrid.SetCellEditor method. This worked fine until I overrode GetAttr in the

wxPyGridTableBase

> class. When I did that, a default editor was used instead of the choice editor created in the
> OnSelectCell method.

The cell editor is one of the attributes that is contained in
wxGridCellAttr and that can be returned by GetAttr, and since you are
not setting it in GetAttr then you are getting the default editor. When
you call grid.SetCellEditor then it will be blended with other
attributes returned by the default table.GetAttr, but yours is not doing
that.

You've got two options:

* Move the someCondition test and determineNamesForThisCell into the
GetAttr method and create the editor as needed there, setting it into
the attr object returned.

* Get the default attributes for the cell and merge your red setting
into that. Something like this perhaps:

     def GetAttr(self, row, col, kind):
         if someOtherCondition:
             # set this cell's text colour to Red
             attr = wxGridCellAttr()
             defattr = self.GetAttrProvider().GetAttr(row, col, kind)
             if defattr is not None:
                 attr.MergeWith(defattr)
             attr.SetTextColour(wxRED)
             return attr
         return None

>
> I tried passing a reference to the editor created in the OnSelectCell method to the GetAttr

method,

> and then used this reference in a call to the wxGridCellAttr.SetEditor method, but that caused a
> 'type error' exception.

GetAttr is called from within the wxGrid C++ code, you can't cause it to
pass extra parameters to the function.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Rad Widmer wrote:

Thanks Robin. The second option (using an Attr Provider) works well for me. I was reluctant to use
the first option (create the editor in GetAttr) for efficiency reasons. I only want to create an
editor when it is really needed (when a user selects a cell). After rearranging the logic a bit, I
ended up with something like the following:

class MyGrid(wxGrid):
    def __init__(self, parent, table):
        wxGrid.__init__(self, parent, -1)
        self.SetTable(table, True)
        # create an attr provider and tell the table about it
        self._attrProvider = wxGridCellAttrProvider()
        table.SetAttrProvider(self._attrProvider)

I don't think this is neccessary. The table should already have an attribute provider by default.

    def OnSelectCell(self, evt):
        if someCondition:
            names = determineNamesForThisCell()
            editor = wxGridCellChoiceEditor(names, False)
            attr = wxGridCellAttr()
            attr.SetEditor(editor)
            self._attrProvider.SetAttr(attr, row, col)

Neither is this. Whenever you set cell attributes (such as the cell editor) via wxGrid methods the attribute is stored via the table->attrProvider automatically.

OTOH, there are no problems with doing it like the above. Maybe just a bit of unneded work is all.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!