Source code for enable.savage.compliance.crosshair
# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in 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!
""" Cross-hair tool for measuring SVG rendering results.
"""
from enable.api import BaseTool, ColorTrait, LineStyle
from traits.api import Bool, Float, HasTraits, List, Tuple, observe
[docs]class Crosshair(BaseTool):
""" Display a crosshair at the given SVG coordinates.
This will do the appropriate transformations in order to map Enable
coordinates to SVG coordinates.
"""
svg_coords = Tuple(Float, Float)
line_color = ColorTrait("black")
line_width = Float(1.0)
line_style = LineStyle("solid")
# Whether the mouse is currently inside the component or not.
mouse_in = Bool(False)
visible = True
draw_mode = "overlay"
[docs] def draw(self, gc, view_bounds=None):
""" Draws this tool on a graphics context.
It is assumed that the graphics context has a coordinate transform that
matches the origin of its component. (For containers, this is just the
origin; for components, it is the origin of their containers.)
"""
if not self.mouse_in:
return
# Convert from SVG coordinates to Enable coordinates.
h = self.component.height
x, y0 = self.svg_coords
y = h - y0
gc.save_state()
try:
gc.set_stroke_color(self.line_color_)
gc.set_line_width(self.line_width)
gc.set_line_dash(self.line_style_)
gc.move_to(self.component.x, y + 0.5)
gc.line_to(self.component.x2, y + 0.5)
gc.move_to(x - 0.5, self.component.y)
gc.line_to(x - 0.5, self.component.y2)
gc.stroke_path()
finally:
gc.restore_state()
[docs] def overlay(self, component, gc, view_bounds=None, mode="normal"):
""" Draws this component overlaid on a graphics context.
"""
self.draw(gc, view_bounds)
[docs] def do_layout(self, *args, **kw):
pass
[docs] def normal_mouse_enter(self, event):
self.mouse_in = True
[docs] def normal_mouse_leave(self, event):
self.mouse_in = False
[docs] def normal_mouse_move(self, event):
""" Handles the mouse being moved.
"""
if self.component is None:
return
# Map the Enable coordinates of the event to SVG coordinates.
h = self.component.height
y = h - event.y
self.svg_coords = event.x, y
event.handled = True
[docs] @observe("svg_coords,mouse_in")
def ensure_redraw(self, event=None):
if self.component is not None:
self.component.invalidate_and_redraw()
[docs]class MultiController(HasTraits):
""" Keep multiple Crosshairs in sync.
"""
svg_coords = Tuple(Float, Float)
mouse_in = Bool(False)
crosshairs = List()
def __init__(self, *crosshairs, **traits):
super().__init__(**traits)
for ch in crosshairs:
self.add(ch)
[docs] def add(self, crosshair):
""" Synch a new Crosshair.
"""
if crosshair not in self.crosshairs:
self.sync_trait("svg_coords", crosshair)
self.sync_trait("mouse_in", crosshair)
self.crosshairs.append(crosshair)
[docs] def remove(self, crosshair):
""" Unsynch a recorded Crosshair.
"""
if crosshair in self.crosshairs:
self.sync_trait("svg_coords", crosshair, remove=True)
self.sync_trait("mouse_in", crosshair, remove=True)
self.crosshairs.append(crosshair)