File: themed_cell_renderer.py

package info (click to toggle)
python-traitsui 4.4.0-1.3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 3,680 kB
  • ctags: 6,394
  • sloc: python: 32,786; makefile: 16; sh: 5
file content (292 lines) | stat: -rw-r--r-- 10,297 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#------------------------------------------------------------------------------
#
#  Copyright (c) 2005, Enthought, Inc.
#  All rights reserved.
#
#  This software is provided without warranty under the terms of the BSD
#  license included in enthought/LICENSE.txt and may be redistributed only
#  under the conditions described in the aforementioned license.  The license
#  is also available online at http://www.enthought.com/licenses/BSD.txt
#
#  Thanks for using Enthought open source!
#
#  Author: David C. Morrill
#  Date:   10/13/2004
#
#------------------------------------------------------------------------------

""" Defines the ThemedCellRenderer class used to render theme-based cells for
    the TableEditor.
"""

#-------------------------------------------------------------------------------
#  Imports:
#-------------------------------------------------------------------------------

import wx

from wx.grid \
    import PyGridCellRenderer, GridCellStringRenderer

from traitsui.ui_traits \
    import convert_bitmap

from helper \
    import BufferDC

#-------------------------------------------------------------------------------
#  'ThemedCellRenderer' class:
#-------------------------------------------------------------------------------

class ThemedCellRenderer ( PyGridCellRenderer ):
    """ Defines the ThemedCellRenderer class used to render theme-based cells
        for the TableEditor.
    """

    def __init__( self, column ):
        """ Creates a new ThemedCellRenderer.
        """
        PyGridCellRenderer.__init__( self )

        # We are merging the pyface grid GridCellRenderer interface with the
        # wx.grid.PyGridCellRenderer interface, so we need to do this:
        self.renderer = self

        # Save the reference to the TableColumn:
        self.column = column

    #-- PyFace grid GridCellRenderer Method Overrides --------------------------

    # Invoked on left-button mouse clicks:
    def on_left_click ( self, grid, row, col ):
        return False

    # Invoked on left-button mouse double clicks:
    def on_left_dclick ( self, grid, row, col ):
        return False

    # Invoked on right-button mouse clicks:
    def on_right_click ( self, grid, row, col ):
        return False

    # Invoked on right-button mouse double clicks:
    def on_right_dclick ( self, grid, row, col ):
        return False

    # Invoked on a key press:
    def on_key ( self, grid, row, col, key_event ):
        return False

    # Clean-up:
    def dispose ( self ):
        del self.renderer
        del self.column

    #-- wx.GridCellRenderer Method Overrides -----------------------------------

    def Draw ( self, grid, attr, dc, rect, row, col, is_selected ):
        """ Draws the contents of the specified grid cell.
        """
        # Get the model object this cell is being rendered for:
        model  = grid.grid.model
        object = model.get_filtered_item( row )

        # Get the draw bounds:
        x0  = rect.x
        y0  = rect.y
        dx  = rect.width
        dy  = rect.height

        # Do all drawing into an off-screen buffer:
        bdc = BufferDC( dc, dx, dy )

        # Draw the appropriate theme background:
        column = self.column
        if is_selected:
            theme = (column.get_selected_theme( object ) or
                     column.get_cell_theme(     object ))
        else:
            theme = column.get_cell_theme( object )

        # If no column theme is specified, try to get the global theme from the
        # model:
        if theme is None:
            if row & 1:
                theme = model.alt_theme or model.cell_theme
            else:
                theme = model.cell_theme

            if is_selected:
                theme = model.selected_theme or theme

        if theme is not None:
            content = theme.content
            slice   = theme.image_slice
            slice.fill( bdc, 0, 0, dx, dy )

            # Set up the correct text color to use:
            bdc.SetTextForeground( theme.content_color )

            # Calculate the margins for the draw area:
            left   = slice.xleft   + content.left
            top    = slice.xtop    + content.top
            right  = slice.xright  + content.right
            bottom = slice.xbottom + content.bottom
            ox, oy = theme.label.left, theme.label.top
        else:
            if is_selected:
                bg_color = grid.GetSelectionBackground()
            else:
                bg_color = attr.GetBackgroundColour()

            bdc.SetBackgroundMode( wx.SOLID )
            bdc.SetBrush( wx.Brush( bg_color, wx.SOLID ) )
            bdc.SetPen( wx.TRANSPARENT_PEN )
            bdc.DrawRectangle( 0, 0, dx, dy )

            # Set up the correct text color to use:
            bdc.SetTextForeground( attr.GetTextColour() )

            # Calculate the margins for the draw area:
            left = right  = self.column.horizontal_margin
            top  = bottom = self.column.vertical_margin
            ox   = oy     = 0

        # Get the alignment information:
        halign, valign = attr.GetAlignment()

        # Draw the bar graph (if any):
        maximum = column.get_maximum( object )
        if (not is_selected) and (maximum > 0.0):
            if theme is None:
                left = right = top = bottom = 0
            try:
                ratio    = max( min( column.get_raw_value( object ) / maximum,
                                     1.0 ), -1.0 )
                avail_dx = dx - left - right
                bar_dx   = int( round( ratio * avail_dx ) )
                if halign == wx.ALIGN_CENTRE:
                    bar_dx /= 2
                    bar_x   = left + (avail_dx / 2) + min( 0, bar_dx )
                else:
                    bar_dx = abs( bar_dx )
                    if halign == wx.ALIGN_LEFT:
                        bar_x = left
                        left += self.column.horizontal_margin
                    else:
                        bar_x  = avail_dx - bar_dx
                        right += self.column.horizontal_margin

                if bar_dx > 0:
                    bdc.SetBackgroundMode( wx.SOLID )
                    bdc.SetBrush( wx.Brush( column.get_graph_color( object ),
                                            wx.SOLID ) )
                    bdc.SetPen( wx.TRANSPARENT_PEN )
                    bdc.DrawRectangle( bar_x, top, bar_dx, dy - top - bottom )
            except:
                pass

            if theme is None:
                left = right  = self.column.horizontal_margin
                top  = bottom = self.column.vertical_margin

        # Get the optional image bitmap and text:
        bitmap = convert_bitmap( column.get_image( object ) )
        text   = grid.GetCellValue( row, col )

        # If no text or bitmap to display, then we are done:
        if (bitmap is None) and (text == ''):
            bdc.copy( x0, y0 )
            return

        # Get the bitmap size:
        idx = idy = tdx = tdy = 0
        if bitmap is not None:
            idx = bitmap.GetWidth()
            idy = bitmap.GetHeight()

        # Get the text size:
        if text != '':
            bdc.SetFont( attr.GetFont() )
            tdx, tdy = bdc.GetTextExtent( text )

            # Get the spacing between text and image:
            if bitmap is not None:
                idx += self.column.horizontal_margin

        # Calculate the x-coordinate of the image/text:
        if halign == wx.ALIGN_LEFT:
            x = left
        elif halign == wx.ALIGN_CENTRE:
            x = (left + ((dx - left - right - tdx - idx) / 2))
        else:
            x = (dx - right - tdx - idx)

        # Calculate the y-coordinate of the image/text:
        max_dy = max( tdy, idy )
        if valign == wx.ALIGN_TOP:
            y = top
        elif valign == wx.ALIGN_CENTRE:
            y = (top + ((dy - top - bottom - max_dy) / 2))
        else:
            y = (dy - bottom - max_dy)

        # Set up the clipping region to prevent drawing outside the margins:
        bdc.SetClippingRegion( left, top, dx - left - right, dy - top - bottom )

        # Draw the image (if left or center aligned):
        if (bitmap is not None) and (halign != wx.ALIGN_RIGHT):
            bdc.DrawBitmap( bitmap, x, y + ((max_dy - idy) / 2),  True )
            x += idx

        # Finally, draw the text:
        if text != '':
            bdc.SetBackgroundMode( wx.TRANSPARENT )
            bdc.DrawText( text, x + ox, y + oy )
            x += tdx + self.column.horizontal_margin

        # Draw the image (if right-aligned):
        if (bitmap is not None) and (halign == wx.ALIGN_RIGHT):
            bdc.DrawBitmap( bitmap, x, y + ((max_dy - idy) / 2),  True )

        # Discard the clipping region:
        bdc.DestroyClippingRegion()

        # Copy the buffer to the display:
        bdc.copy( x0, y0 )

    def GetBestSize ( self, grid, attr, dc, row, col ):
        """ Determine best size for the cell. """
        # Get the model object this cell is being rendered for:
        object = grid.grid.model.get_filtered_item( row )

        # Get the text for this cell:
        text = grid.GetCellValue( row, col ) or 'My'

        # Now calculate and return the best size for the text and image:
        dc.SetFont( attr.GetFont() )
        tdx, tdy = dc.GetTextExtent( text )

        column = self.column
        bitmap = convert_bitmap( column.get_image( object ) )
        if bitmap is not None:
            tdx += (bitmap.GetWdth() + self.column.horizontal_margin)
            tdy  = max( tdy, bitmap.GetHeight() )

        theme = column.get_cell_theme( object )
        if theme is None:
            return wx.Size( tdx + self.column.horizontal_margin * 2, tdy + self.column.vertical_margin * 2 )

        content = theme.content
        tdx    += (content.left + content.right)
        tdy    += (content.top  + content.bottom)
        slice   = theme.image_slice

        return wx.Size( max( slice.left  + slice.right,
                             slice.xleft + slice.xright  + tdx ),
                        max( slice.top   + slice.bottom,
                             slice.xtop  + slice.xbottom + tdy ) )

    def Clone ( self ):
        return self.__class__( self.column )