Auto wrap and newlines in wxPython grid
Question: I want to implement a grid with the cells that have the following behaviour:

  1. cell text should be wrapped if it doesn't fit to the cell

  2. newlines (\n) in the cell text should be processed as well

i.e. the same behaviour as in table editors like MS Excel, OO Calc, etc. when
you enable the 'wrap words' option for cells.

I'm trying to do this as follows:

    
    
    import wx 
    import wx.grid 
    
    class MyGrid(wx.grid.Grid): 
    
        def __init__(self, parent = None, style = wx.WANTS_CHARS): 
    
            wx.grid.Grid.__init__(self, parent, -1, style = style) 
    
            self.CreateGrid(10, 10) 
    
            self.editor = wx.grid.GridCellAutoWrapStringEditor() 
            self.SetDefaultEditor(self.editor)
    
            self.SetDefaultRenderer(wx.grid.GridCellAutoWrapStringRenderer()) 
    
            self.SetCellValue(0, 0, "Line1\nLine2\nLine3") 
            self.SetRowSize(0, 100) 
    
    
    class MyFrame(wx.Frame): 
    
        def __init__(self, parent = None, title = "Multiline"): 
    
            wx.Frame.__init__(self, parent, -1, title) 
    
            self.Bind(wx.EVT_CHAR_HOOK, self.on_frame_char_hook) 
    
            panel = wx.Panel(self) 
    
            vbox = wx.BoxSizer(wx.VERTICAL) 
            panel.SetSizer(vbox) 
    
            grid = MyGrid(panel) 
            vbox.Add(grid, 1, wx.EXPAND | wx.ALL, 5) 
            self.grid = grid 
    
            btn_exit = wx.Button(panel, -1, "Exit") 
            vbox.Add(btn_exit, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10) 
    
        #Proceed CTRL+ENTER as newline in the cell editor
        def on_frame_char_hook(self, event): 
    
            if event.CmdDown() and event.GetKeyCode() == wx.WXK_RETURN: 
                if self.grid.editor.IsCreated(): 
                    self.grid.editor.StartingKey(event) 
                else: 
                    event.Skip 
            else: 
                event.Skip()
    
    
    if __name__ == "__main__": 
        app = wx.PySimpleApp() 
        f = MyFrame() 
        f.Center() 
        f.Show() 
        app.MainLoop()
    

But this code doesn't work as expected - newlines processed correctly in the
cell editor, but ignored in the cell renderer. If I remove the
`self.SetDefaultRenderer(wx.grid.GridCellAutoWrapStringRenderer())` then
newlines processed correcly both in the editor and renderer, but obviously
auto wrapping in the renderer doesn't work.

Does anybody know how to solve this?


Answer: Solved this problem by writing a custom renderer:

    
    
    from wx.lib import wordwrap
    import wx.grid
    
    
    class CutomGridCellAutoWrapStringRenderer(wx.grid.PyGridCellRenderer):   
        def __init__(self): 
            wx.grid.PyGridCellRenderer.__init__(self)
    
        def Draw(self, grid, attr, dc, rect, row, col, isSelected):
            text = grid.GetCellValue(row, col)
            dc.SetFont( attr.GetFont() ) 
            text = wordwrap.wordwrap(text, grid.GetColSize(col), dc, breakLongWords = False)
            hAlign, vAlign = attr.GetAlignment()       
            if isSelected: 
                bg = grid.GetSelectionBackground() 
                fg = grid.GetSelectionForeground() 
            else: 
                bg = attr.GetBackgroundColour()
                fg = attr.GetTextColour() 
            dc.SetTextBackground(bg) 
            dc.SetTextForeground(fg)
            dc.SetBrush(wx.Brush(bg, wx.SOLID))
            dc.SetPen(wx.TRANSPARENT_PEN)
            dc.DrawRectangleRect(rect)            
            grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign)
    
        def GetBestSize(self, grid, attr, dc, row, col): 
            text = grid.GetCellValue(row, col)
            dc.SetFont(attr.GetFont())
            text = wordwrap.wordwrap(text, grid.GetColSize(col), dc, breakLongWords = False)
            w, h, lineHeight = dc.GetMultiLineTextExtent(text)                   
            return wx.Size(w, h)        
    
        def Clone(self): 
            return CutomGridCellAutoWrapStringRenderer()
    

