Changeset 1130

Show
Ignore:
Timestamp:
02/15/07 00:06:18 (2 years ago)
Author:
arjanmol
Message:

split View into View (baseclass) and GtkView?. Updated demo with SVG and PNG export.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphas/trunk/demo.py

    r1014 r1130  
    1212import math 
    1313import gtk 
    14 from gaphas import Canvas, View 
     14import cairo 
     15from gaphas import Canvas, GtkView, View 
    1516from gaphas.examples import Box, Text, DefaultExampleTool 
    1617from gaphas.item import Line, NW, SE 
    1718from gaphas.tool import PlacementTool, HandleTool 
     19from gaphas.painter import ItemPainter 
    1820 
    1921class MyBox(Box): 
     
    5052 
    5153def create_window(canvas, zoom=1.0): 
    52     view = View() 
     54    view = GtkView() 
    5355    view.tool = DefaultExampleTool() 
    5456 
     
    125127    v.add(b) 
    126128 
     129    b = gtk.Button('Write demo.png') 
     130 
     131    def on_clicked(button): 
     132        svgview = View(view.canvas) 
     133        svgview.painter = ItemPainter() 
     134 
     135        # Update bounding boxes with a temporaly CairoContext 
     136        # (used for stuff like calculating font metrics) 
     137        tmpsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 0, 0) 
     138        tmpcr = cairo.Context(tmpsurface) 
     139        svgview.update_bounding_box(tmpcr) 
     140        tmpcr.show_page() 
     141        tmpsurface.flush() 
     142        
     143        w, h = svgview.bounding_box.width, svgview.bounding_box.height 
     144        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(w), int(h)) 
     145        cr = cairo.Context(surface) 
     146        svgview.matrix.translate(-svgview.bounding_box.x0, -svgview.bounding_box.y0) 
     147        cr.save() 
     148        svgview.paint(cr) 
     149 
     150        cr.restore() 
     151        cr.show_page() 
     152        surface.write_to_png('demo.png') 
     153 
     154    b.connect('clicked', on_clicked) 
     155    v.add(b) 
     156 
     157    b = gtk.Button('Write demo.svg') 
     158 
     159    def on_clicked(button): 
     160        svgview = View(view.canvas) 
     161        svgview.painter = ItemPainter() 
     162 
     163        # Update bounding boxes with a temporaly CairoContext 
     164        # (used for stuff like calculating font metrics) 
     165        tmpsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 0, 0) 
     166        tmpcr = cairo.Context(tmpsurface) 
     167        svgview.update_bounding_box(tmpcr) 
     168        tmpcr.show_page() 
     169        tmpsurface.flush() 
     170        
     171        w, h = svgview.bounding_box.width, svgview.bounding_box.height 
     172        surface = cairo.SVGSurface('demo.svg', w, h) 
     173        cr = cairo.Context(surface) 
     174        svgview.matrix.translate(-svgview.bounding_box.x0, -svgview.bounding_box.y0) 
     175        svgview.paint(cr) 
     176        cr.show_page() 
     177        surface.flush() 
     178        surface.finish() 
     179 
     180    b.connect('clicked', on_clicked) 
     181    v.add(b) 
     182 
     183     
    127184#    b = gtk.Button('Cursor') 
    128185# 
  • gaphas/trunk/gaphas/__init__.py

    r948 r1130  
    1414from canvas import Canvas 
    1515from item import Item, Line, Element, Handle 
    16 from view import View 
     16from view import View, GtkView 
    1717 
  • gaphas/trunk/gaphas/view.py

    r1069 r1130  
    2828 
    2929class ToolContext(Context): 
    30     """Special context for tools. 
     30    """ 
     31    Special context for tools. 
    3132    """ 
    3233 
     
    3738 
    3839    def grab(self): 
    39         """Grab the view (or tool, depending on the implementation). 
     40        """ 
     41        Grab the view (or tool, depending on the implementation). 
    4042        """ 
    4143        self.view.grab_focus() 
    4244 
    4345    def ungrab(self): 
    44         """Ungrab the view. 
     46        """ 
     47        Ungrab the view. 
    4548        """ 
    4649        pass 
     
    4851 
    4952class CairoContextWrapper(object): 
    50     """Delegate all calls to the wrapped CairoContext, intercept 
     53    """ 
     54    Delegate all calls to the wrapped CairoContext, intercept 
    5155    stroke(), fill() and a few others so the bounding box of the 
    5256    item involved can be calculated. 
     
    6165 
    6266    def get_bounds(self): 
    63         """Return the bounding box. 
     67        """ 
     68        Return the bounding box. 
    6469        """ 
    6570        return self._bounds or Rectangle() 
     
    7378 
    7479    def _extents(self, extents_func, line_width=False): 
    75         """Calculate the bounding box for a given drawing operation. 
     80        """ 
     81        Calculate the bounding box for a given drawing operation. 
    7682        if @line_width is True, the current line-width is taken into account. 
    7783        """ 
     
    115121 
    116122 
     123class View(object): 
     124    """ 
     125    View class for gaphas.Canvas objects.  
     126    """ 
     127 
     128    def __init__(self, canvas=None): 
     129        self._canvas = canvas 
     130        self._bounds = Rectangle() 
     131        self._item_bounds = dict() 
     132 
     133        # Handling selections. 
     134        self._selected_items = set() 
     135        self._focused_item = None 
     136        self._hovered_item = None 
     137 
     138        self._matrix = Matrix() 
     139        self._painter = DefaultPainter() 
     140 
     141    matrix = property(lambda s: s._matrix) 
     142 
     143    def _set_canvas(self, canvas): 
     144        """ 
     145        Use view.canvas = my_canvas to set the canvas to be rendered 
     146        in the view. 
     147        """ 
     148        if self._canvas: 
     149            self._item_bounds = dict() 
     150 
     151        self._canvas = canvas 
     152         
     153        if self._canvas: 
     154            self.request_update(self._canvas.get_all_items()) 
     155 
     156    canvas = property(lambda s: s._canvas, _set_canvas) 
     157 
     158    def emit(self, args, **kwargs): 
     159        """ 
     160        Placeholder method for signal emission functionality. 
     161        """ 
     162        pass 
     163 
     164    def select_item(self, item): 
     165        """ 
     166        Select an item. This adds @item to the set of selected items. Do 
     167           del view.selected_items 
     168        to clear the selected items list 
     169        """ 
     170        self.queue_draw_item(item, handles=True) 
     171        if item not in self._selected_items: 
     172            self._selected_items.add(item) 
     173            self.emit('selection-changed', self._selected_items) 
     174 
     175    def unselect_item(self, item): 
     176        """ 
     177        Unselect an item. 
     178        """ 
     179        self.queue_draw_item(item, handles=True) 
     180        if item in self._selected_items: 
     181            self._selected_items.discard(item) 
     182            self.emit('selection-changed', self._selected_items) 
     183 
     184    def select_all(self): 
     185        for item in self.canvas.get_all_items(): 
     186            self.select_item(item) 
     187 
     188    def unselect_all(self): 
     189        """ 
     190        Clearing the selected_item also clears the focused_item. 
     191        """ 
     192        self.queue_draw_item(handles=True, *self._selected_items) 
     193        self._selected_items.clear() 
     194        self.focused_item = None 
     195        self.emit('selection-changed', self._selected_items) 
     196 
     197    selected_items = property(lambda s: set(s._selected_items), 
     198                              select_item, unselect_all, 
     199                              "Items selected by the view") 
     200 
     201    def _set_focused_item(self, item): 
     202        """ 
     203        Set the focused item, this item is also added to the selected_items 
     204        set. 
     205        """ 
     206        if not item is self._focused_item: 
     207            self.queue_draw_item(self._focused_item, item, handles=True) 
     208 
     209        if item: 
     210            self.selected_items = item #.add(item) 
     211        if item is not self._focused_item: 
     212            self._focused_item = item 
     213            self.emit('focus-changed', item) 
     214 
     215    def _del_focused_item(self): 
     216        """ 
     217        Items that loose focus remain selected. 
     218        """ 
     219        self.focused_item = None 
     220         
     221    focused_item = property(lambda s: s._focused_item, 
     222                            _set_focused_item, _del_focused_item, 
     223                            "The item with focus (receives key events a.o.)") 
     224 
     225    def _set_hovered_item(self, item): 
     226        """ 
     227        Set the hovered item. 
     228        """ 
     229        if not item is self._hovered_item: 
     230            self.queue_draw_item(self._hovered_item, item, handles=True) 
     231        if item is not self._hovered_item: 
     232            self._hovered_item = item 
     233            self.emit('hover-changed', item) 
     234 
     235    def _del_hovered_item(self): 
     236        """ 
     237        Unset the hovered item. 
     238        """ 
     239        self.hovered_item = None 
     240         
     241    hovered_item = property(lambda s: s._hovered_item, 
     242                            _set_hovered_item, _del_hovered_item, 
     243                            "The item directly under the mouse pointer") 
     244 
     245    def _set_painter(self, painter): 
     246        """ 
     247        Set the painter to use. Painters should implement painter.Painter. 
     248        """ 
     249        self._painter = painter 
     250        self.emit('painter-changed') 
     251 
     252    painter = property(lambda s: s._painter, _set_painter) 
     253 
     254    def paint(self, cr): 
     255        """ 
     256        Do the paint action, calling draw() on each item. 
     257        """ 
     258        self._painter.paint(Context(view=self, 
     259                                    cairo=cr)) 
     260 
     261    def get_item_at_point(self, x, y): 
     262        """ 
     263        Return the topmost item located at (x, y). 
     264        """ 
     265        point = (x, y) 
     266        for item in reversed(self._canvas.get_all_items()): 
     267            if point in self.get_item_bounding_box(item): 
     268                inverse = Matrix(*self._matrix) 
     269                inverse.invert() 
     270                wx, wy = inverse.transform_point(x, y) 
     271                ix, iy = self._canvas.get_matrix_w2i(item).transform_point(wx, wy) 
     272                if item.point(ix, iy) < 0.5: 
     273                    return item 
     274        return None 
     275 
     276    def select_in_rectangle(self, rect): 
     277        """ 
     278        Select all items who have their bounding box within the 
     279        rectangle @rect. 
     280        """ 
     281        for item in self._canvas.get_all_items(): 
     282            if self.get_item_bounding_box(item) in rect: 
     283                self.select_item(item) 
     284 
     285    def zoom(self, factor): 
     286        """ 
     287        Zoom in/out by factor @factor. 
     288        """ 
     289        self._matrix.scale(factor, factor) 
     290 
     291        # Make sure everything's updated 
     292        self.request_update(self._canvas.get_all_items()) 
     293 
     294    def set_item_bounding_box(self, item, bounds): 
     295        """ 
     296        Update the bounding box of the item (in canvas coordinates). 
     297        """ 
     298        self._item_bounds[item] = bounds 
     299        if bounds: 
     300            bounds.x1 += 1 
     301            bounds.y1 += 1 
     302            # Also update the view's overall bounding box. 
     303            self._bounds += bounds 
     304 
     305    def get_item_bounding_box(self, item): 
     306        """ 
     307        Get the bounding box for the item, in canvas coordinates. 
     308        """ 
     309        return self._item_bounds[item] 
     310 
     311    def get_canvas_size(self): 
     312        """ 
     313        The canvas size (width, height) in canvas coordinates, determined 
     314        from the origin (0, 0). 
     315        """ 
     316        inverse = Matrix(*self._matrix) 
     317        inverse.invert() 
     318        ww, wh = self.transform_point_c2w(self._bounds.x1, self._bounds.y1) 
     319        return self._matrix.transform_distance(ww, wh) 
     320 
     321    bounding_box = property(lambda s: s._bounds) 
     322 
     323    def update_bounding_box(self, cr, items=None): 
     324        """ 
     325        Update the bounding boxes of the canvas items for this view. 
     326        """ 
     327        self._item_bounds = dict() 
     328        self._bounds = Rectangle() 
     329 
     330        painter = BoundingBoxPainter() 
     331        painter.paint(Context(view=self, 
     332                              cairo=cr, 
     333                              items=items)) 
     334 
     335        # Update the view's bounding box with the rest of the items 
     336        bounds = self._bounds 
     337        for b in self._item_bounds.itervalues(): 
     338            bounds += b 
     339 
     340    def transform_distance_c2w(self, x, y): 
     341        """ 
     342        Transform a point from canvas to world coordinates. 
     343        """ 
     344        inverse = Matrix(*self._matrix) 
     345        inverse.invert() 
     346        return inverse.transform_distance(x, y) 
     347 
     348    def transform_distance_w2c(self, x, y): 
     349        """ 
     350        Transform a distance from world to canvas coordinates. 
     351        """ 
     352        return self._matrix.transform_distance(x, y) 
     353 
     354    def transform_point_c2w(self, x, y): 
     355        """ 
     356        Transform a distance from canvas to world coordinates. 
     357        """ 
     358        inverse = Matrix(*self._matrix) 
     359        inverse.invert() 
     360        return inverse.transform_point(x, y) 
     361 
     362    def transform_point_w2c(self, x, y): 
     363        """ 
     364        Transform a point from world to canvas coordinates. 
     365        """ 
     366        return self._matrix.transform_point(x, y) 
     367 
     368    def transform_point_c2i(self, item, x, y): 
     369        """ 
     370        Transforma point from canvas to item coordinates. 
     371        """ 
     372        assert self.canvas 
     373        wx, wy = self.transform_point_c2w(x, y) 
     374        return self._canvas.get_matrix_w2i(item).transform_point(wx, wy) 
     375 
     376    def transform_point_i2c(self, item, x, y): 
     377        """ 
     378        Transform a point from item coordinates to canvas coordinates. 
     379        """ 
     380        assert self.canvas 
     381        wx, wy = self._canvas.get_matrix_i2w(item).transform_point(x, y) 
     382        return self.transform_point_w2c(wx, wy) 
     383 
     384 
     385    def wrap_cairo_context(self, cr): 
     386        """ 
     387        Create a wrapper class for the cairo context. This class is used 
     388        to calculate the items bounding box while the item is drawn (the 
     389        bounding box contains all drawn elements). 
     390        """ 
     391        return CairoContextWrapper(cr) 
     392 
     393 
    117394# Map GDK events to tool methods 
    118395EVENT_HANDLERS = { 
     
    127404 
    128405 
    129 class View(gtk.DrawingArea): 
    130     """GTK+ widget for rendering a canvas.Canvas to a screen. 
     406 
     407class GtkView(gtk.DrawingArea, View): 
     408    # NOTE: Ingerit from GTK+ class first, otherwise BusErrors may occur! 
     409    """ 
     410    GTK+ widget for rendering a canvas.Canvas to a screen. 
    131411    The view uses Tools from tool.py to handle events and Painters 
    132412    from painter.py to draw. Both are configurable. 
     
    149429                      ()) 
    150430    } 
     431 
    151432    def __init__(self, canvas=None): 
    152         super(View, self).__init__() 
     433        super(GtkView, self).__init__() 
     434        View.__init__(self) 
    153435        self.set_flags(gtk.CAN_FOCUS) 
    154436        self.add_events(gtk.gdk.BUTTON_PRESS_MASK 
     
    157439                        | gtk.gdk.KEY_PRESS_MASK 
    158440                        | gtk.gdk.KEY_RELEASE_MASK) 
    159         self._canvas = canvas 
    160         self._bounds = Rectangle() 
    161         self._item_bounds = dict() 
    162  
    163         # Handling selections. 
    164         self._selected_items = set() 
    165         self._focused_item = None 
    166         self._hovered_item = None 
    167  
    168         self._matrix = Matrix() 
    169441 
    170442        self.hadjustment = gtk.Adjustment() 
     
    172444 
    173445        self._tool = DefaultTool() 
    174         self._painter = DefaultPainter() 
    175  
    176     matrix = property(lambda s: s._matrix) 
     446 
     447    def emit(self, *args, **kwargs): 
     448        """ 
     449        Delegate signal emissions to the DrawingArea (=GTK+) 
     450        """ 
     451        gtk.DrawingArea.emit(self, *args, **kwargs) 
    177452 
    178453    def _set_canvas(self, canvas): 
    179         """Use view.canvas = my_canvas to set the canvas to be rendered 
     454        """ 
     455        Use view.canvas = my_canvas to set the canvas to be rendered 
    180456        in the view. 
     457        This extends the behaviour of View.canvas. 
    181458        """ 
    182459        if self._canvas: 
    183460            self._canvas.unregister_view(self) 
    184             self._item_bounds = dict() 
    185  
    186         self._canvas = canvas 
     461 
     462        super(GtkView, self)._set_canvas(canvas) 
    187463         
    188464        if self._canvas: 
    189465            self._canvas.register_view(self) 
    190             #for item in self._canvas.get_all_items(): 
    191             #    self._canvas.request_update(item) 
    192             self.request_update(self._canvas.get_all_items()) 
    193466 
    194467    canvas = property(lambda s: s._canvas, _set_canvas) 
    195468 
    196     def select_item(self, item): 
    197         """Select an item. This adds @item to the set of selected items. Do 
    198            del view.selected_items 
    199         to clear the selected items list 
    200          
    201         """ 
    202         self.queue_draw_item(item, handles=True) 
    203         if item not in self._selected_items: 
    204             self._selected_items.add(item) 
    205             self.emit('selection-changed', self._selected_items) 
    206  
    207     def unselect_item(self, item): 
    208         """Unselect an item. 
    209         """ 
    210         self.queue_draw_item(item, handles=True) 
    211         if item in self._selected_items: 
    212             self._selected_items.discard(item) 
    213             self.emit('selection-changed', self._selected_items) 
    214  
    215     def select_all(self): 
    216         for item in self.canvas.get_all_items(): 
    217             self.select_item(item) 
    218  
    219     def unselect_all(self): 
    220         """Clearing the selected_item also clears the focused_item. 
    221         """ 
    222         self.queue_draw_item(handles=True, *self._selected_items) 
    223         self._selected_items.clear() 
    224         self.focused_item = None 
    225         self.emit('selection-changed', self._selected_items) 
    226  
    227     selected_items = property(lambda s: set(s._selected_items), 
    228                               select_item, unselect_all, 
    229                               "Items selected by the view") 
    230  
    231     def _set_focused_item(self, item): 
    232         """Set the focused item, this item is also added to the selected_items 
    233         set. 
    234         """ 
    235         if not item is self._focused_item: 
    236             self.queue_draw_item(self._focused_item, item, handles=True) 
    237  
    238         if item: 
    239             self.selected_items = item #.add(item) 
    240         if item is not self._focused_item: 
    241             self._focused_item = item 
    242             self.emit('focus-changed', item) 
    243  
    244     def _del_focused_item(self): 
    245         """Items that loose focus remain selected. 
    246         """ 
    247         self.focused_item = None 
    248          
    249     focused_item = property(lambda s: s._focused_item, 
    250                             _set_focused_item, _del_focused_item, 
    251                             "The item with focus (receives key events a.o.)") 
    252  
    253     def _set_hovered_item(self, item): 
    254         """Set the hovered item. 
    255         """ 
    256         if not item is self._hovered_item: 
    257             self.queue_draw_item(self._hovered_item, item, handles=True) 
    258         if item is not self._hovered_item: 
    259             self._hovered_item = item 
    260             self.emit('hover-changed', item) 
    261  
    262     def _del_hovered_item(self): 
    263         """Unset the hovered item. 
    264         """ 
    265         self.hovered_item = None 
    266          
    267     hovered_item = property(lambda s: s._hovered_item, 
    268                             _set_hovered_item, _del_hovered_item, 
    269                             "The item directly under the mouse pointer") 
    270  
    271469    def _set_tool(self, tool): 
    272         """Set the tool to use. Tools should implement tool.Tool. 
     470        """ 
     471        Set the tool to use. Tools should implement tool.Tool. 
    273472        """ 
    274473        self._tool = tool 
     
    277476    tool = property(lambda s: s._tool, _set_tool) 
    278477 
    279     def _set_painter(self, painter): 
    280         """Set the painter to use. Painters should implement painter.Painter. 
    281         """ 
    282         self._painter = painter 
    283         self.emit('painter-changed') 
    284  
    285     painter = property(lambda s: s._painter, _set_painter) 
    286  
    287478    def _set_hadjustment(self, adj): 
    288         """Set horizontal adjustment object, for scrollbars. 
     479        """ 
     480        Set horizontal adjustment object, for scrollbars. 
    289481        """ 
    290482        #if self._hadjustment: 
     
    296488 
    297489    def _set_vadjustment(self, adj): 
    298         """Set vertical adjustment object, for scrollbars. 
     490        """ 
     491        Set vertical adjustment object, for scrollbars. 
    299492        """ 
    300493        #if self._vadjustment: 
     
    305498    vadjustment = property(lambda s: s._vadjustment, _set_vadjustment) 
    306499 
    307     def get_item_at_point(self, x, y): 
    308         """Return the topmost item located at (x, y). 
    309         """ 
    310         point = (x, y) 
    311         for item in reversed(self._canvas.get_all_items()): 
    312             if point in self.get_item_bounding_box(item): 
    313                 inverse = Matrix(*self._matrix) 
    314                 inverse.invert() 
    315                 wx, wy = inverse.transform_point(x, y) 
    316                 ix, iy = self._canvas.get_matrix_w2i(item).transform_point(wx, wy) 
    317                 if item.point(ix, iy) < 0.5: 
    318                     return item 
    319         return None 
    320  
    321     def select_in_rectangle(self, rect): 
    322         """Select all items who have their bounding box within the 
    323         rectangle @rect. 
    324         """ 
    325         for item in self._canvas.get_all_items(): 
    326             if self.get_item_bounding_box(item) in rect: 
    327                 self.select_item(item) 
    328  
    329500    def zoom(self, factor): 
    330         """Zoom in/out by factor @factor. 
    331         """ 
    332         self._matrix.scale(factor, factor) 
    333  
    334         # Make sure everything's updated 
    335         self.request_update(self._canvas.get_all_items()) 
     501        """ 
     502        Zoom in/out by factor @factor. 
     503        """ 
     504        super(GtkView, self).zoom(factor) 
    336505        a = self.allocation 
    337         super(View, self).queue_draw_area(0, 0, a.width, a.height) 
     506        super(GtkView, self).queue_draw_area(0, 0, a.width, a.height) 
    338507 
    339508    def _update_adjustment(self, adjustment, value, canvas_size, viewport_size): 
    340509        """ 
    341         >>> v = View() 
     510        >>> v = GtkView() 
    342511        >>> a = gtk.Adjustment() 
    343512        >>> v._hadjustment = a 
     
    361530            adjustment.value_changed() 
    362531 
    363     def transform_distance_c2w(self, x, y): 
    364         """Transform a point from canvas to world coordinates. 
    365         """ 
    366         inverse = Matrix(*self._matrix) 
    367         inverse.invert() 
    368         return inverse.transform_distance(x, y) 
    369  
    370     def transform_distance_w2c(self, x, y): 
    371         """Transform a distance from world to canvas coordinates. 
    372         """ 
    373         return self._matrix.transform_distance(x, y) 
    374  
    375     def transform_point_c2w(self, x, y): 
    376         """Transform a distance from canvas to world coordinates. 
    377         """ 
    378         inverse = Matrix(*self._matrix) 
    379         inverse.invert() 
    380         return inverse.transform_point(x, y) 
    381  
    382     def transform_point_w2c(self, x, y): 
    383         """Transform a point from world to canvas coordinates. 
    384         """ 
    385         return self._matrix.transform_point(x, y) 
    386  
    387     def transform_point_c2i(self, item, x, y): 
    388         """Transforma point from canvas to item coordinates. 
    389         """ 
    390         assert self.canvas 
    391         wx, wy = self.transform_point_c2w(x, y) 
    392         return self._canvas.get_matrix_w2i(item).transform_point(wx, wy) 
    393  
    394     def transform_point_i2c(self, item, x, y): 
    395         """Transform a point from item coordinates to canvas coordinates. 
    396         """ 
    397         assert self.canvas 
    398         wx, wy = self._canvas.get_matrix_i2w(item).transform_point(x, y) 
    399         return self.transform_point_w2c(wx, wy) 
    400  
    401     def get_canvas_size(self): 
    402         """The canvas size (width, height) in canvas coordinates. 
    403         """ 
    404         inverse = Matrix(*self._matrix) 
    405         inverse.invert() 
    406         ww, wh = self.transform_point_c2w(self._bounds.x1, self._bounds.y1) 
    407         return self._matrix.transform_distance(ww, wh) 
    408  
    409532    def update_adjustments(self, allocation=None): 
    410         """Update the allocation objects (for scrollbars). 
     533        """ 
     534        Update the allocation objects (for scrollbars). 
    411535        """ 
    412536        if not allocation: 
     
    423547 
    424548    def queue_draw_item(self, *items, **kwargs): 
    425         """Like DrawingArea.queue_draw_area, but use the bounds of the 
     549        """ 
     550        Like DrawingArea.queue_draw_area, but use the bounds of the 
    426551        item as update areas. Of course with a pythonic flavor: update 
    427552        any number of items at once. 
     
    442567 
    443568    def queue_draw_area(self, x, y, w, h): 
    444         """Wrap draw_area to convert all values to ints. 
    445         """ 
    446         super(View, self).queue_draw_area(int(x), int(y), int(w+1), int(h+1)) 
    447  
    448     def set_item_bounding_box(self, item, bounds): 
    449         """Update the bounding box of the item (in canvas coordinates). 
    450         """ 
    451         self._item_bounds[item] = bounds 
    452         if bounds: 
    453             bounds.x1 += 1 
    454             bounds.y1 += 1 
    455             # Also update the view's overall bounding box. 
    456             self._bounds += bounds 
    457  
    458     def get_item_bounding_box(self, item): 
    459         """Get the bounding box for the item, in canvas coordinates. 
    460         """ 
    461         return self._item_bounds[item] 
    462  
    463     def wrap_cairo_context(self, cairo): 
    464         """Create a wrapper class for the cairo context. This class is used 
    465         to calculate the items bounding box while the item is drawn (the 
    466         bounding box contains all drawn elements). 
    467         """ 
    468         return CairoContextWrapper(cairo) 
     569        """ 
     570        Wrap draw_area to convert all values to ints. 
     571        """ 
     572        super(GtkView, self).queue_draw_area(int(x), int(y), int(w+1), int(h+1)) 
    469573 
    470574    @async(single=False, priority=PRIORITY_HIGH_IDLE) 
    471575    def request_update(self, items): 
    472         """Update view status according to the items updated by the canvas. 
     576        """ 
     577        Update view status according to the items updated by the canvas. 
    473578        """ 
    474579        if not self.window: return True 
     
    493598 
    494599        # Pseudo-draw 
    495         context = self.window.cairo_create() 
    496         context.rectangle(0,0,0,0) 
    497         context.clip() 
    498  
    499         self._item_bounds = dict() 
    500         self._bounds = Rectangle() 
    501  
    502         painter = BoundingBoxPainter() 
    503         painter.paint(Context(view=self, 
    504                               cairo=context)) 
     600        cr = self.window.cairo_create() 
     601        cr.rectangle(0,0,0,0) 
     602        cr.clip() 
     603 
     604        self.update_bounding_box(cr, items) 
    505605 
    506606        for i in items: 
     
    511611    @nonrecursive 
    512612    def do_size_allocate(self, allocation): 
    513         """Allocate the widget size (x, y, width, height). 
     613        """ 
     614        Allocate the widget size (x, y, width, height). 
    514615        """ 
    515616        gtk.DrawingArea.do_size_allocate(self, allocation) 
    516         # doesn't work: super(View, self).do_size_allocate(allocation) 
     617        # doesn't work: super(GtkView, self).do_size_allocate(allocation) 
    517618        self.update_adjustments(allocation) 
    518619        
    519620    def do_expose_event(self, event): 
    520         """Render some text to the screen. 
     621        """ 
     622        Render some text to the screen. 
    521623        """ 
    522624        if not self._canvas: 
     
    527629                                   area.x, area.y, area.width, area.height) 
    528630 
    529         context = self.window.cairo_create() 
     631        cr = self.window.cairo_create() 
    530632 
    531633        # Draw no more than nessesary. 
    532         context.rectangle(area.x, area.y, area.width, area.height) 
    533         context.clip() 
    534  
    535         self._painter.paint(Context(view=self, 
    536                                     cairo=context)) 
     634        cr.rectangle(area.x, area.y, area.width, area.height) 
     635        cr.clip() 
     636 
     637        self.paint(cr) 
    537638 
    538639        if DEBUG_DRAW_BOUNDING_BOX: 
    539             context.save() 
    540             context.identity_matrix() 
    541             context.set_source_rgb(0, .8, 0) 
    542             context.set_line_width(1.0) 
     640            cr.save() 
     641            cr.identity_matrix() 
     642            cr.set_source_rgb(0, .8, 0) 
     643            cr.set_line_width(1.0) 
    543644            b = self._bounds 
    544             context.rectangle(b[0], b[1], b[2] - b[0], b[3] - b[1]) 
    545             context.stroke() 
    546             context.restore() 
     645            cr.rectangle(b[0], b[1], b[2] - b[0], b[3] - b[1]) 
     646            cr.stroke() 
     647            cr.restore() 
    547648 
    548649        return False 
    549650 
    550651    def do_event(self, event): 
    551         """Handle GDK events. Events are delegated to a Tool. 
     652        """ 
     653        Handle GDK events. Events are delegated to a Tool. 
    552654        """ 
    553655        handler = EVENT_HANDLERS.get(event.type) 
     
    557659 
    558660    def on_adjustment_changed(self, adj): 
    559         """Change the transformation matrix of the view to reflect the 
     661        """ 
     662        Change the transformation matrix of the view to reflect the 
    560663        value of the x/y adjustment (scrollbar). 
    561664        """ 
     
    569672 
    570673        a = self.allocation 
    571         super(View, self).queue_draw_area(0, 0, a.width, a.height) 
     674        super(GtkView, self).queue_draw_area(0, 0, a.width, a.height) 
    572675 
    573676