Changeset 817

Show
Ignore:
Timestamp:
03/27/06 05:28:33 (3 years ago)
Author:
arjanmol
Message:

Calculate bounding boxes for items on the fly.

Files:

Legend:

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

    r815 r817  
    77class Box(Item): 
    88    def __init__(self): 
    9         print 'Box.__init__' 
    109        super(Box, self).__init__() 
    1110        self._width = 10 
    1211        self._height = 10 
     12        self._handles = [Handle(0, 0)] 
     13 
     14    def handles(self): 
     15        return iter(self._handles) 
     16 
     17    def update(self, context): 
     18        self._handles[0].x = self._width 
     19        self._handles[0].y = self._height 
    1320 
    1421    def draw(self, context): 
    15         print 'Box.draw' 
     22        print 'Box.draw', self 
    1623        c = context.cairo 
    1724        c.rectangle(0,0, self._width, self._height) 
    18         c.set_source_rgb(0,0,80
     25        c.set_source_rgb(0,0,0.8
    1926        c.stroke() 
    2027        context.draw_children() 
  • trunk/gaphas/item.py

    r815 r817  
    1111    x = solvable() 
    1212    y = solvable() 
    13     def __init__(self, x, y): 
     13 
     14    def __init__(self, x=0, y=0): 
    1415        self.x = x 
    1516        self.y = y 
  • trunk/gaphas/view.py

    r815 r817  
    22This module contains everything to display a Canvas on a screen. 
    33""" 
     4 
     5if __name__ == '__main__': 
     6    import pygtk 
     7    pygtk.require('2.0')  
    48 
    59import gtk 
     
    1721        """ 
    1822        self.view._draw_items(self.children, self.cairo) 
     23 
     24 
     25class CairoContextWrapper(object): 
     26    """Delegate all calls to the wrapped CairoContext, intercept 
     27    stroke(), fill() and a few others so the bounding box of the 
     28    item involved can be calculated. 
     29    """ 
     30 
     31    def __init__(self, cairo_context): 
     32        self._cairo_context = cairo_context 
     33        self._bounds = None 
     34 
     35    def __getattr__(self, key): 
     36        return getattr(self._cairo_context, key) 
     37 
     38    def _update_bounds(self, bounds): 
     39        #print 'bounds', bounds 
     40        if not self._bounds: 
     41            self._bounds = bounds 
     42        else: 
     43            b = self._bounds 
     44            self._bounds = (min(b[0], bounds[0]), min(b[1], bounds[1]), 
     45                            max(b[2], bounds[2]), max(b[3], bounds[3])) 
     46 
     47    def fill(self): 
     48        ctx = self._cairo_context 
     49        ctx.save() 
     50        ctx.identity_matrix() 
     51        self._update_bounds(ctx.fill_extents()) 
     52        ctx.restore() 
     53        return ctx.fill() 
     54 
     55    def fill_preserve(self): 
     56        ctx = self._cairo_context 
     57        ctx.save() 
     58        ctx.identity_matrix() 
     59        self._update_bounds(ctx.fill_extents()) 
     60        ctx.restore() 
     61        return ctx.fill_preserve() 
     62 
     63    def stroke(self): 
     64        ctx = self._cairo_context 
     65        ctx.save() 
     66        ctx.identity_matrix() 
     67        self._update_bounds(ctx.stroke_extents()) 
     68        ctx.restore() 
     69        return ctx.stroke() 
     70 
     71    def stroke_preserve(self): 
     72        ctx = self._cairo_context 
     73        ctx.save() 
     74        ctx.identity_matrix() 
     75        self._update_bounds(ctx.stroke_extents()) 
     76        ctx.restore() 
     77        return ctx.stroke_preserve() 
     78 
     79    def text_show(self, utf8): 
     80        e = self._cairo_context.text_extents(utf8) 
     81        # Do something with it 
     82        return ctx.show_text(utf8) 
     83 
    1984 
    2085class View(gtk.DrawingArea): 
     
    3095                        | gtk.gdk.KEY_PRESS_MASK 
    3196                        | gtk.gdk.KEY_RELEASE_MASK) 
    32         self.width = 0 
    33         self.height = 0 
    3497        self._canvas = canvas 
    3598        self._cairo_context = None 
    3699        self._tool = None 
     100        self._calculate_bounding_box = False 
     101 
     102        # Handy debug flag for drawing bounding boxes around the items. 
     103        self._debug_draw_bounding_box = True 
    37104 
    38105    def _set_canvas(self, canvas): 
     
    54121                cairo_context.set_matrix(item._matrix_w2i) 
    55122                #cairo_context.transform(Matrix(*item.matrix)) 
     123                if self._calculate_bounding_box: 
     124                    wrapper = CairoContextWrapper(cairo_context) 
     125                else: 
     126                    # No wrapper: 
     127                    wrapper = cairo_context 
     128 
    56129                item.draw(DrawContext(view=self, 
    57                                       cairo=cairo_context
     130                                      cairo=wrapper
    58131                                      children=self._canvas.get_children(item))) 
     132 
     133                if self._calculate_bounding_box: 
     134                    item._view_bounds = wrapper._bounds 
     135                    #print item, wrapper._bounds 
     136 
     137                if self._debug_draw_bounding_box: 
     138                    ctx = cairo_context 
     139                    ctx.save() 
     140                    ctx.identity_matrix() 
     141                    ctx.set_source_rgb(.8, 0, 0) 
     142                    ctx.set_line_width(1.0) 
     143                    b = item._view_bounds 
     144                    ctx.rectangle(b[0], b[1], b[2] - b[0], b[3] - b[1]) 
     145                    ctx.stroke() 
     146                    ctx.restore() 
     147 
    59148                self._draw_handles(item, cairo_context) 
    60149            finally: 
     
    62151 
    63152    def _draw_handles(self, item, cairo_context): 
    64         size = 7 
    65         cairo_context.save() 
    66         cairo_context.rectangle(0, 0, size, size
    67         cairo_context.set_source_rgba(0, 1, 0, .6
    68         cairo_context.fill_preserve(
    69         cairo_context.move_to(2, 2
    70         cairo_context.line_to(5, 5
    71         cairo_context.move_to(5, 2
    72         cairo_context.line_to(2, 5
    73         cairo_context.set_source_rgba(0, 0, 0, 0.6
    74         cairo_context.set_line_width(1.0
    75         cairo_context.stroke(
    76  
    77         cairo_context.restore() 
     153        for handle in item.handles(): 
     154            cairo_context.save() 
     155            cairo_context.translate(handle.x - 4, handle.y - 4
     156            cairo_context.rectangle(0, 0, 9, 9
     157            cairo_context.set_source_rgba(0, 1, 0, .6
     158            cairo_context.fill_preserve(
     159            cairo_context.move_to(2, 2
     160            cairo_context.line_to(7, 7
     161            cairo_context.move_to(7, 2
     162            cairo_context.line_to(2, 7
     163            cairo_context.set_source_rgba(0, .2, 0, 0.9
     164            cairo_context.set_line_width(1.1
     165            cairo_context.stroke() 
     166            cairo_context.restore() 
    78167 
    79168    def do_expose_event(self, event): 
    80169        """Render some text to the screen. 
    81170        """ 
     171 
    82172        # Set this to some idle function 
    83173        if self._canvas.require_update(): 
    84174            self._canvas.update_now() 
     175            self._calculate_bounding_box = True 
    85176 
    86177        viewport = self.get_allocation() 
     
    97188            # TODO: add move/zoom matrix 
    98189            self._draw_items(self._canvas.get_root_items(), context) 
     190 
     191        self._calculate_bounding_box = False 
     192 
    99193        return False 
    100194 
     
    108202 
    109203    def do_motion_notify_event(self, event): 
    110         print 'do motion notify', event 
     204        #print 'do motion notify', event 
    111205        return False 
    112206 
     
    137231    print 'view', v 
    138232    b=Box() 
     233    print 'box', b 
    139234    b.matrix=(1.0, 0.0, 0.0, 1, 20,20) 
    140235    b._width=b._height = 40 
    141236    c.add(b) 
    142237    bb=Box() 
     238    print 'box', bb 
    143239    bb.matrix=(1.0, 0.0, 0.0, 1, 10,10) 
    144240    c.add(bb, parent=b) 
    145241    bb=Box() 
     242    print 'box', bb 
    146243    bb.matrix.rotate(math.pi/4.) 
    147244    c.add(bb, parent=b)