Make painter implementation tool-alike.

This commit is contained in:
Arjan Molenaar
2010-03-31 07:38:14 +02:00
parent a1a62429ab
commit 2862985e1e
3 changed files with 53 additions and 41 deletions

4
NEWS
View File

@ -1,3 +1,7 @@
0.6.1
-----
- Painters are bound to a specific view, like tools
0.6.0
-----
- Handlers are no longer called recursively for observed methods/properties.

View File

@ -27,6 +27,12 @@ class Painter(object):
Painter interface.
"""
def __init__(self, view=None):
self.view = view
def set_view(self, view):
self.view = view
def paint(self, context):
"""
Do the paint action (called from the View).
@ -40,14 +46,22 @@ class PainterChain(Painter):
like ToolChain.
"""
def __init__(self):
def __init__(self, view=None):
super(PainterChain, self).__init__(view)
self._painters = []
def set_view(self, view):
self.view = view
for painters in self._painters:
painter.set_view(self.view)
def append(self, painter):
"""
Add a painter to the list of painters.
"""
self._painters.append(painter)
painter.set_view(self.view)
return self
def prepend(self, painter):
"""
@ -66,7 +80,7 @@ class PainterChain(Painter):
class DrawContext(Context):
"""
Special context for draw()'ing the item. The draw-context contains
stuff like the view, the cairo context and properties like selected and
stuff like the cairo context and properties like selected and
focused.
"""
@ -80,14 +94,14 @@ class ItemPainter(Painter):
draw_all = False
def _draw_item(self, item, view, cairo, area=None):
def _draw_item(self, item, cairo, area=None):
view = self.view
cairo.save()
try:
cairo.set_matrix(view.matrix)
cairo.transform(view.canvas.get_matrix_i2c(item))
item.draw(DrawContext(painter=self,
view=view,
cairo=cairo,
_area=area,
_item=item,
@ -100,17 +114,18 @@ class ItemPainter(Painter):
finally:
cairo.restore()
def _draw_items(self, items, view, cairo, area=None):
def _draw_items(self, items, cairo, area=None):
"""
Draw the items.
"""
for item in items:
#if not area or area - view.get_item_bounding_box(item):
self._draw_item(item, view, cairo, area=area)
self._draw_item(item, cairo, area=area)
if DEBUG_DRAW_BOUNDING_BOX:
self._draw_bounds(item, view, cairo)
self._draw_bounds(item, cairo)
def _draw_bounds(self, item, view, cairo):
def _draw_bounds(self, item, cairo):
view = self.view
try:
b = view.get_item_bounding_box(item)
except KeyError:
@ -126,12 +141,9 @@ class ItemPainter(Painter):
def paint(self, context):
cairo = context.cairo
view = context.view
area = context.area
items = context.items
cairo.set_tolerance(TOLERANCE)
cairo.set_line_join(LINE_JOIN_ROUND)
self._draw_items(items, view, cairo, area)
self._draw_items(context.items, cairo, context.area)
class CairoBoundingBoxContext(object):
@ -237,12 +249,13 @@ class BoundingBoxPainter(ItemPainter):
draw_all = True
def _draw_item(self, item, view, cairo, area=None):
def _draw_item(self, item, cairo, area=None):
cairo = CairoBoundingBoxContext(cairo)
super(BoundingBoxPainter, self)._draw_item(item, view, cairo)
super(BoundingBoxPainter, self)._draw_item(item, cairo)
bounds = cairo.get_bounds()
# Update bounding box with handles.
view = self.view
i2v = view.get_matrix_i2v(item).transform_point
for h in item.handles():
cx, cy = i2v(*h.pos)
@ -252,18 +265,15 @@ class BoundingBoxPainter(ItemPainter):
view.set_item_bounding_box(item, bounds)
def _draw_items(self, items, view, cairo, area=None):
def _draw_items(self, items, cairo, area=None):
"""
Draw the items.
"""
for item in items:
self._draw_item(item, view, cairo)
self._draw_item(item, cairo)
def paint(self, context):
cairo = context.cairo
view = context.view
items = context.items
self._draw_items(items, view, cairo)
self._draw_items(context.items, context.cairo)
class HandlePainter(Painter):
@ -271,11 +281,12 @@ class HandlePainter(Painter):
Draw handles of items that are marked as selected in the view.
"""
def _draw_handles(self, item, view, cairo, opacity=None, inner=False):
def _draw_handles(self, item, cairo, opacity=None, inner=False):
"""
Draw handles for an item.
The handles are drawn in non-antialiased mode for clearity.
"""
view = self.view
cairo.save()
i2v = view.get_matrix_i2v(item)
if not opacity:
@ -316,7 +327,7 @@ class HandlePainter(Painter):
cairo.restore()
def paint(self, context):
view = context.view
view = self.view
canvas = view.canvas
cairo = context.cairo
# Order matters here:
@ -338,7 +349,7 @@ class ToolPainter(Painter):
"""
def paint(self, context):
view = context.view
view = self.view
cairo = context.cairo
if view.tool:
cairo.save()
@ -346,7 +357,7 @@ class ToolPainter(Painter):
view.tool.draw(context)
cairo.restore()
# Move this to tool.
# Move this to segment module.
class LineSegmentPainter(Painter):
"""
This painter draws pseudo-hanldes on gaphas.item.Line objects. Each
@ -358,7 +369,7 @@ class LineSegmentPainter(Painter):
"""
def paint(self, context):
view = context.view
view = self.view
item = view.hovered_item
if item and item is view.focused_item and isinstance(item, Line):
cr = context.cairo
@ -383,16 +394,15 @@ class LineSegmentPainter(Painter):
def DefaultPainter():
def DefaultPainter(view=None):
"""
Default painter, containing item, handle and tool painters.
"""
chain = PainterChain()
chain.append(ItemPainter())
chain.append(HandlePainter())
chain.append(LineSegmentPainter())
chain.append(ToolPainter())
return chain
return PainterChain(view). \
append(ItemPainter()). \
append(HandlePainter()). \
append(LineSegmentPainter()). \
append(ToolPainter())
# vim: sw=4:et:
# vim: sw=4:et:ai

View File

@ -31,7 +31,7 @@ class View(object):
def __init__(self, canvas=None):
self._matrix = Matrix()
self._painter = DefaultPainter()
self._painter = DefaultPainter(self)
# Handling selections.
### TODO: Move this to a context?
@ -204,6 +204,7 @@ class View(object):
Set the painter to use. Painters should implement painter.Painter.
"""
self._painter = painter
painter.set_view(self)
self.emit('painter-changed')
@ -389,13 +390,12 @@ class View(object):
Update the bounding boxes of the canvas items for this view, in
canvas coordinates.
"""
painter = BoundingBoxPainter()
painter = BoundingBoxPainter(self)
if items is None:
items = self.canvas.get_all_items()
# The painter calls set_item_bounding_box() for each rendered item.
painter.paint(Context(view=self,
cairo=cr,
painter.paint(Context(cairo=cr,
items=items))
# Update the view's bounding box with the rest of the items
@ -403,8 +403,7 @@ class View(object):
def paint(self, cr):
self._painter.paint(Context(view=self,
cairo=cr,
self._painter.paint(Context(cairo=cr,
items=self.canvas.get_all_items(),
area=None))
@ -813,8 +812,7 @@ class GtkView(gtk.DrawingArea, View):
cr.clip()
area = Rectangle(x, y, width=w, height=h)
self._painter.paint(Context(view=self,
cairo=cr,
self._painter.paint(Context(cairo=cr,
items=self.get_items_in_rectangle(area),
area=area))