Provide connection to lines
This commit is contained in:
parent
8173c47dab
commit
9ea1407955
@ -270,7 +270,9 @@ item.py: Element
|
||||
An element has ``min_height`` and ``min_width`` properties.
|
||||
|
||||
>>> from gaphas import Element
|
||||
>>> e = Element()
|
||||
>>> from gaphas.connections import Connections
|
||||
>>> from gaphas.solver import Solver
|
||||
>>> e = Element(Connections(Solver()))
|
||||
>>> e.min_height, e.min_width
|
||||
(Variable(10, 100), Variable(10, 100))
|
||||
>>> e.min_height, e.min_width = 30, 40
|
||||
@ -293,7 +295,7 @@ A line has the following properties: ``line_width``, ``fuzziness``,
|
||||
|
||||
>>> from gaphas import Line
|
||||
>>> from gaphas.segment import Segment
|
||||
>>> l = Line()
|
||||
>>> l = Line(Connections(Solver()))
|
||||
|
||||
Let's first add a segment to the line, to test orthogonal lines as well.
|
||||
|
||||
@ -350,7 +352,7 @@ Also creation and removal of connected lines is recorded and can be undone:
|
||||
>>> canvas.add(b0)
|
||||
>>> b1 = Item()
|
||||
>>> canvas.add(b1)
|
||||
>>> l = Line()
|
||||
>>> l = Line(Connections(Solver()))
|
||||
>>> canvas.add(l)
|
||||
>>> real_connect(l, l.handles()[0], b0)
|
||||
>>> real_connect(l, l.handles()[1], b1)
|
||||
|
@ -32,9 +32,12 @@ class Connections:
|
||||
solver = property(lambda s: s._solver)
|
||||
|
||||
def add_constraint(self, item, constraint):
|
||||
self._solver.add_constraint(constraint)
|
||||
self._connections.insert(item, None, None, None, constraint, None)
|
||||
return constraint
|
||||
|
||||
def remove_constraint(self, item, constraint):
|
||||
self._solver.remove_constraint(constraint)
|
||||
self._connections.delete(item, None, None, None, constraint, None)
|
||||
|
||||
@observed
|
||||
|
@ -192,8 +192,9 @@ class Element(Item):
|
||||
min_width = variable(strength=REQUIRED, varname="_min_width")
|
||||
min_height = variable(strength=REQUIRED, varname="_min_height")
|
||||
|
||||
def __init__(self, width=10, height=10):
|
||||
def __init__(self, connections, width=10, height=10):
|
||||
super().__init__()
|
||||
self._connections = connections
|
||||
self._handles = [h(strength=VERY_STRONG) for h in [Handle] * 4]
|
||||
|
||||
handles = self._handles
|
||||
@ -213,21 +214,19 @@ class Element(Item):
|
||||
# initialize min_x variables
|
||||
self.min_width, self.min_height = 10, 10
|
||||
|
||||
self.constraint(horizontal=(h_nw.pos, h_ne.pos))
|
||||
self.constraint(horizontal=(h_sw.pos, h_se.pos))
|
||||
self.constraint(vertical=(h_nw.pos, h_sw.pos))
|
||||
self.constraint(vertical=(h_ne.pos, h_se.pos))
|
||||
add = connections.add_constraint
|
||||
add(self, constraint(horizontal=(h_nw.pos, h_ne.pos)))
|
||||
add(self, constraint(horizontal=(h_sw.pos, h_se.pos)))
|
||||
add(self, constraint(vertical=(h_nw.pos, h_sw.pos)))
|
||||
add(self, constraint(vertical=(h_ne.pos, h_se.pos)))
|
||||
|
||||
# create minimal size constraints
|
||||
self.constraint(left_of=(h_nw.pos, h_se.pos), delta=self.min_width)
|
||||
self.constraint(above=(h_nw.pos, h_se.pos), delta=self.min_height)
|
||||
add(self, constraint(left_of=(h_nw.pos, h_se.pos), delta=self.min_width))
|
||||
add(self, constraint(above=(h_nw.pos, h_se.pos), delta=self.min_height))
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
# TODO: constraints that calculate width and height based on handle pos
|
||||
# self.constraints.append(EqualsConstraint(p1[1], p2[1], delta))
|
||||
|
||||
def setup_canvas(self):
|
||||
super().setup_canvas()
|
||||
|
||||
@ -315,8 +314,9 @@ class Line(Item):
|
||||
draw an arrow point).
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, connections):
|
||||
super().__init__()
|
||||
self._connections = connections
|
||||
self._handles = [Handle(connectable=True), Handle((10, 10), connectable=True)]
|
||||
self._ports = []
|
||||
self._update_ports()
|
||||
@ -351,7 +351,7 @@ class Line(Item):
|
||||
return
|
||||
|
||||
for c in self._orthogonal_constraints:
|
||||
self._canvas.solver.remove_constraint(c)
|
||||
self._connections.remove_constraint(self, c)
|
||||
del self._orthogonal_constraints[:]
|
||||
|
||||
if not orthogonal:
|
||||
@ -361,16 +361,16 @@ class Line(Item):
|
||||
# if len(h) < 3:
|
||||
# self.split_segment(0)
|
||||
eq = EqualsConstraint # lambda a, b: a - b
|
||||
add = self._canvas.solver.add_constraint
|
||||
add = self._connections.add_constraint
|
||||
cons = []
|
||||
rest = self._horizontal and 1 or 0
|
||||
for pos, (h0, h1) in enumerate(zip(h, h[1:])):
|
||||
p0 = h0.pos
|
||||
p1 = h1.pos
|
||||
if pos % 2 == rest: # odd
|
||||
cons.append(add(eq(a=p0.x, b=p1.x)))
|
||||
cons.append(add(self, eq(a=p0.x, b=p1.x)))
|
||||
else:
|
||||
cons.append(add(eq(a=p0.y, b=p1.y)))
|
||||
cons.append(add(self, eq(a=p0.y, b=p1.y)))
|
||||
p1.x.notify()
|
||||
p1.y.notify()
|
||||
self._set_orthogonal_constraints(cons)
|
||||
@ -427,21 +427,6 @@ class Line(Item):
|
||||
|
||||
horizontal = reversible_property(lambda s: s._horizontal, _set_horizontal)
|
||||
|
||||
def setup_canvas(self):
|
||||
"""Setup constraints.
|
||||
|
||||
In this case orthogonal.
|
||||
"""
|
||||
super().setup_canvas()
|
||||
self._update_orthogonal_constraints(self.orthogonal)
|
||||
|
||||
def teardown_canvas(self):
|
||||
"""Remove constraints created in setup_canvas()."""
|
||||
super().teardown_canvas()
|
||||
assert self._canvas
|
||||
for c in self._orthogonal_constraints:
|
||||
self._canvas.solver.remove_constraint(c)
|
||||
|
||||
@observed
|
||||
def _reversible_insert_handle(self, index, handle):
|
||||
self._handles.insert(index, handle)
|
||||
|
@ -23,22 +23,23 @@ class SimpleCanvas:
|
||||
|
||||
def __init__(self):
|
||||
self.canvas = Canvas()
|
||||
self.connections = self.canvas.connections
|
||||
|
||||
self.box1 = Box()
|
||||
self.box1 = Box(self.connections)
|
||||
self.canvas.add(self.box1)
|
||||
self.box1.matrix.translate(100, 50)
|
||||
self.box1.width = 40
|
||||
self.box1.height = 40
|
||||
self.canvas.request_update(self.box1)
|
||||
|
||||
self.box2 = Box()
|
||||
self.box2 = Box(self.connections)
|
||||
self.canvas.add(self.box2)
|
||||
self.box2.matrix.translate(100, 150)
|
||||
self.box2.width = 50
|
||||
self.box2.height = 50
|
||||
self.canvas.request_update(self.box2)
|
||||
|
||||
self.line = Line()
|
||||
self.line = Line(self.connections)
|
||||
self.head = self.line.handles()[0]
|
||||
self.tail = self.line.handles()[-1]
|
||||
self.tail.pos = 100, 100
|
||||
|
@ -10,8 +10,8 @@ from gaphas.matrix import Matrix
|
||||
def test_update_matrices():
|
||||
"""Test updating of matrices."""
|
||||
c = Canvas()
|
||||
i = Box()
|
||||
ii = Box()
|
||||
i = Box(c.connections)
|
||||
ii = Box(c.connections)
|
||||
c.add(i)
|
||||
c.add(ii, i)
|
||||
|
||||
@ -24,8 +24,8 @@ def test_update_matrices():
|
||||
|
||||
def test_reparent():
|
||||
c = Canvas()
|
||||
b1 = Box()
|
||||
b2 = Box()
|
||||
b1 = Box(c.connections)
|
||||
b2 = Box(c.connections)
|
||||
c.add(b1)
|
||||
c.add(b2, b1)
|
||||
c.reparent(b2, None)
|
||||
@ -36,10 +36,10 @@ def count(i):
|
||||
|
||||
|
||||
def test_connect_item():
|
||||
b1 = Box()
|
||||
b2 = Box()
|
||||
line = Line()
|
||||
c = Canvas()
|
||||
b1 = Box(c.connections)
|
||||
b2 = Box(c.connections)
|
||||
line = Line(c.connections)
|
||||
c.add(b1)
|
||||
c.add(b2)
|
||||
c.add(line)
|
||||
@ -54,10 +54,10 @@ def test_connect_item():
|
||||
|
||||
|
||||
def test_disconnect_item_with_callback():
|
||||
b1 = Box()
|
||||
b2 = Box()
|
||||
line = Line()
|
||||
c = Canvas()
|
||||
b1 = Box(c.connections)
|
||||
b2 = Box(c.connections)
|
||||
line = Line(c.connections)
|
||||
c.add(b1)
|
||||
c.add(b2)
|
||||
c.add(line)
|
||||
@ -76,10 +76,10 @@ def test_disconnect_item_with_callback():
|
||||
|
||||
|
||||
def test_disconnect_item_with_constraint():
|
||||
b1 = Box()
|
||||
b2 = Box()
|
||||
line = Line()
|
||||
c = Canvas()
|
||||
b1 = Box(c.connections)
|
||||
b2 = Box(c.connections)
|
||||
line = Line(c.connections)
|
||||
c.add(b1)
|
||||
c.add(b2)
|
||||
c.add(line)
|
||||
@ -98,10 +98,10 @@ def test_disconnect_item_with_constraint():
|
||||
|
||||
|
||||
def test_disconnect_item_by_deleting_element():
|
||||
b1 = Box()
|
||||
b2 = Box()
|
||||
line = Line()
|
||||
c = Canvas()
|
||||
b1 = Box(c.connections)
|
||||
b2 = Box(c.connections)
|
||||
line = Line(c.connections)
|
||||
c.add(b1)
|
||||
c.add(b2)
|
||||
c.add(line)
|
||||
@ -121,10 +121,10 @@ def test_disconnect_item_by_deleting_element():
|
||||
|
||||
|
||||
def test_disconnect_item_with_constraint_by_deleting_element():
|
||||
b1 = Box()
|
||||
b2 = Box()
|
||||
line = Line()
|
||||
c = Canvas()
|
||||
b1 = Box(c.connections)
|
||||
b2 = Box(c.connections)
|
||||
line = Line(c.connections)
|
||||
c.add(b1)
|
||||
c.add(b2)
|
||||
c.add(line)
|
||||
@ -150,15 +150,15 @@ def test_remove_connected_item():
|
||||
|
||||
from gaphas.aspect import ConnectionSink, Connector
|
||||
|
||||
l1 = Line()
|
||||
l1 = Line(canvas.connections)
|
||||
canvas.add(l1)
|
||||
|
||||
b1 = Box()
|
||||
b1 = Box(canvas.connections)
|
||||
canvas.add(b1)
|
||||
|
||||
number_cons1 = len(canvas.solver.constraints)
|
||||
|
||||
b2 = Box()
|
||||
b2 = Box(canvas.connections)
|
||||
canvas.add(b2)
|
||||
|
||||
number_cons2 = len(canvas.solver.constraints)
|
||||
|
@ -12,8 +12,8 @@ def connections():
|
||||
|
||||
|
||||
def test_reconnect_item(connections):
|
||||
i = item.Line()
|
||||
ii = item.Line()
|
||||
i = item.Line(connections)
|
||||
ii = item.Line(connections)
|
||||
|
||||
cons1 = EqualsConstraint(i.handles()[0].pos.x, i.handles()[0].pos.x)
|
||||
cons2 = EqualsConstraint(i.handles()[0].pos.y, i.handles()[0].pos.y)
|
||||
@ -30,7 +30,7 @@ def test_reconnect_item(connections):
|
||||
|
||||
|
||||
def test_add_item_constraint(connections):
|
||||
i = item.Line()
|
||||
i = item.Line(connections)
|
||||
c1 = EqualsConstraint(i.handles()[0].pos.x, i.handles()[0].pos.x)
|
||||
|
||||
connections.add_constraint(i, c1)
|
||||
@ -42,7 +42,7 @@ def test_add_item_constraint(connections):
|
||||
|
||||
|
||||
def test_remove_item_constraint(connections):
|
||||
i = item.Line()
|
||||
i = item.Line(connections)
|
||||
c1 = EqualsConstraint(i.handles()[0].pos.x, i.handles()[0].pos.x)
|
||||
|
||||
connections.add_constraint(i, c1)
|
||||
@ -52,7 +52,7 @@ def test_remove_item_constraint(connections):
|
||||
|
||||
|
||||
def test_remove_item_constraint_when_item_is_disconnected(connections):
|
||||
i = item.Line()
|
||||
i = item.Line(connections)
|
||||
c1 = EqualsConstraint(i.handles()[0].pos.x, i.handles()[0].pos.x)
|
||||
|
||||
connections.add_constraint(i, c1)
|
||||
|
@ -10,7 +10,7 @@ from gaphas.item import Element as Box
|
||||
class CanvasBox:
|
||||
def __init__(self):
|
||||
self.canvas = Canvas()
|
||||
self.box = Box()
|
||||
self.box = Box(self.canvas.connections)
|
||||
self.handles = self.box.handles()
|
||||
|
||||
|
||||
|
@ -2,8 +2,10 @@ import pytest
|
||||
from gi.repository import Gtk
|
||||
|
||||
from gaphas.canvas import Canvas
|
||||
from gaphas.connections import Connections
|
||||
from gaphas.guide import Guide, GuidedItemInMotion
|
||||
from gaphas.item import Element, Line
|
||||
from gaphas.solver import Solver
|
||||
from gaphas.view import GtkView
|
||||
|
||||
|
||||
@ -14,33 +16,38 @@ class Window:
|
||||
self.window = Gtk.Window()
|
||||
self.window.add(self.view)
|
||||
self.window.show_all()
|
||||
self.line = Line()
|
||||
self.line = Line(self.canvas.connections)
|
||||
self.canvas.add(self.line)
|
||||
self.e1 = Element()
|
||||
self.e2 = Element()
|
||||
self.e3 = Element()
|
||||
self.e1 = Element(self.canvas.connections)
|
||||
self.e2 = Element(self.canvas.connections)
|
||||
self.e3 = Element(self.canvas.connections)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@pytest.fixture
|
||||
def win():
|
||||
test_window = Window()
|
||||
yield test_window
|
||||
test_window.window.destroy()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def connections(win):
|
||||
return win.canvas.connections
|
||||
|
||||
|
||||
def test_find_closest(win):
|
||||
"""Test find closest method."""
|
||||
set1 = [0, 10, 20]
|
||||
set2 = [2, 15, 30]
|
||||
|
||||
guider = GuidedItemInMotion(Element(), win.view)
|
||||
guider = GuidedItemInMotion(Element(win.canvas.connections), win.view)
|
||||
d, closest = guider.find_closest(set1, set2)
|
||||
assert 2.0 == d
|
||||
assert [2.0] == closest
|
||||
|
||||
|
||||
def test_element_guide():
|
||||
e1 = Element()
|
||||
e1 = Element(Connections(Solver()))
|
||||
assert 10 == e1.width
|
||||
assert 10 == e1.height
|
||||
guides = Guide(e1).horizontal()
|
||||
|
@ -5,16 +5,17 @@ from gaphas.item import Line
|
||||
from gaphas.segment import Segment
|
||||
|
||||
|
||||
def test_initial_ports(revert_undo):
|
||||
def test_initial_ports():
|
||||
"""Test initial ports amount."""
|
||||
line = Line()
|
||||
canvas = Canvas()
|
||||
line = Line(canvas.connections)
|
||||
assert 1 == len(line.ports())
|
||||
|
||||
|
||||
def test_orthogonal_horizontal_undo(revert_undo, undo_fixture):
|
||||
"""Test orthogonal line constraints bug (#107)."""
|
||||
canvas = Canvas()
|
||||
line = Line()
|
||||
line = Line(canvas.connections)
|
||||
canvas.add(line)
|
||||
assert not line.horizontal
|
||||
assert len(canvas.solver._constraints) == 0
|
||||
@ -45,7 +46,7 @@ def test_orthogonal_horizontal_undo(revert_undo, undo_fixture):
|
||||
def test_orthogonal_line_undo(revert_undo, undo_fixture):
|
||||
"""Test orthogonal line undo."""
|
||||
canvas = Canvas()
|
||||
line = Line()
|
||||
line = Line(canvas.connections)
|
||||
canvas.add(line)
|
||||
|
||||
segment = Segment(line, canvas)
|
||||
|
@ -10,7 +10,7 @@ from gaphas.view import GtkView
|
||||
class SegmentFixture:
|
||||
def __init__(self):
|
||||
self.canvas = Canvas()
|
||||
self.line = Line()
|
||||
self.line = Line(self.canvas.connections)
|
||||
self.canvas.add(self.line)
|
||||
self.view = GtkView(self.canvas)
|
||||
self.item = Item()
|
||||
@ -33,7 +33,7 @@ def test_segment_fails_for_item(seg):
|
||||
|
||||
def test_segment(seg):
|
||||
"""Test add a new segment to a line."""
|
||||
line = Line()
|
||||
line = Line(seg.canvas.connections)
|
||||
seg.canvas.add(line)
|
||||
segment = Segment(line, seg.canvas)
|
||||
assert 2 == len(line.handles())
|
||||
@ -145,7 +145,7 @@ def test_ports_after_split(simple_canvas):
|
||||
def test_constraints_after_split(simple_canvas):
|
||||
"""Test if constraints are recreated after line split."""
|
||||
# Connect line2 to self.line
|
||||
line2 = Line()
|
||||
line2 = Line(simple_canvas.connections)
|
||||
simple_canvas.canvas.add(line2)
|
||||
head = line2.handles()[0]
|
||||
simple_canvas.tool.connect(line2, head, (25, 25))
|
||||
@ -206,19 +206,19 @@ def test_orthogonal_line_split(simple_canvas):
|
||||
|
||||
def test_params_error_exc(simple_canvas):
|
||||
"""Test parameter error exceptions."""
|
||||
line = Line()
|
||||
line = Line(simple_canvas.connections)
|
||||
segment = Segment(line, simple_canvas.canvas)
|
||||
|
||||
# There is only 1 segment
|
||||
with pytest.raises(ValueError):
|
||||
segment.split_segment(-1)
|
||||
|
||||
line = Line()
|
||||
line = Line(simple_canvas.connections)
|
||||
segment = Segment(line, simple_canvas.canvas)
|
||||
with pytest.raises(ValueError):
|
||||
segment.split_segment(1)
|
||||
|
||||
line = Line()
|
||||
line = Line(simple_canvas.connections)
|
||||
# Can't split into one or less segment :)
|
||||
segment = Segment(line, simple_canvas.canvas)
|
||||
with pytest.raises(ValueError):
|
||||
@ -264,7 +264,7 @@ def test_merge_first_single(simple_canvas):
|
||||
|
||||
def test_constraints_after_merge(simple_canvas):
|
||||
"""Test if constraints are recreated after line merge."""
|
||||
line2 = Line()
|
||||
line2 = Line(simple_canvas.connections)
|
||||
simple_canvas.canvas.add(line2)
|
||||
head = line2.handles()[0]
|
||||
|
||||
@ -363,7 +363,7 @@ def test_orthogonal_line_merge(simple_canvas):
|
||||
@pytest.mark.parametrize("num_segments", [-1, 2, (0, 1), 0, 1, (0, 3)])
|
||||
def test_params_errors(simple_canvas, num_segments):
|
||||
"""Test parameter error exceptions."""
|
||||
line = Line()
|
||||
line = Line(simple_canvas.connections)
|
||||
simple_canvas.canvas.add(line)
|
||||
segment = Segment(line, simple_canvas.canvas)
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -5,13 +5,13 @@ from gaphas.item import Line
|
||||
|
||||
|
||||
def test_undo_on_delete_element(revert_undo, undo_fixture):
|
||||
b1 = Box()
|
||||
b2 = Box()
|
||||
line = Line()
|
||||
|
||||
canvas = Canvas()
|
||||
b1 = Box(canvas.connections)
|
||||
b2 = Box(canvas.connections)
|
||||
line = Line(canvas.connections)
|
||||
|
||||
canvas.add(b1)
|
||||
assert 6 == len(canvas.solver.constraints)
|
||||
assert 12 == len(canvas.solver.constraints)
|
||||
|
||||
canvas.add(b2)
|
||||
assert 12 == len(canvas.solver.constraints)
|
||||
|
@ -17,8 +17,9 @@ class ViewFixture:
|
||||
self.window.add(self.view)
|
||||
self.window.show_all()
|
||||
|
||||
self.box = Box()
|
||||
self.box = Box(self.canvas.connections)
|
||||
self.canvas.add(self.box)
|
||||
self.connections = self.canvas.connections
|
||||
|
||||
# Process pending (expose) events, which cause the canvas to be drawn.
|
||||
while Gtk.events_pending():
|
||||
@ -51,7 +52,7 @@ def test_get_unselected_item_at_point(view_fixture):
|
||||
|
||||
|
||||
def test_get_handle_at_point(view_fixture):
|
||||
box = Box()
|
||||
box = Box(view_fixture.connections)
|
||||
box.min_width = 20
|
||||
box.min_height = 30
|
||||
box.matrix.translate(20, 20)
|
||||
@ -64,7 +65,7 @@ def test_get_handle_at_point(view_fixture):
|
||||
|
||||
|
||||
def test_get_handle_at_point_at_pi_div_2(view_fixture):
|
||||
box = Box()
|
||||
box = Box(view_fixture.connections)
|
||||
box.min_width = 20
|
||||
box.min_height = 30
|
||||
box.matrix.translate(20, 20)
|
||||
|
Loading…
x
Reference in New Issue
Block a user