/
connection_element.py
159 lines (126 loc) · 4.7 KB
/
connection_element.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
"""
clutter/connection_element.py -- clutter backend for connection elements
Copyright (c) Bill Gribble <grib@billgribble.com>
"""
import math
from gi.repository import Clutter
import cairo
from ..colordb import ColorDB
from ..base_element import BaseElement
from .base_element import ClutterBaseElementBackend
from ..connection_element import (
ConnectionElement,
ConnectionElementImpl,
)
class ClutterConnectionElementImpl(ConnectionElement, ConnectionElementImpl, ClutterBaseElementBackend):
backend_name = "clutter"
def __init__(self, window, obj_1, port_1, obj_2, port_2, dashed=False):
super().__init__(window, obj_1, port_1, obj_2, port_2, dashed)
self.texture = Clutter.Canvas.new()
self.group.set_content(self.texture)
self.texture.connect("draw", self.draw_cb)
self.group.set_reactive(True)
if self.obj_1.layer is not None:
self.move_to_layer(self.obj_1.layer)
elif self.obj_2.layer is not None:
self.move_to_layer(self.obj_2.layer)
self.width = 15
self.height = 15
self.texture.set_size(self.width, self.height)
px, py = self.obj_1.get_position()
self.position_x = px
self.position_y = py
self.texture.invalidate()
async def update(self):
await self.draw()
async def delete(self, **kwargs):
if self.texture:
self.group.set_content(None)
self.texture = None
await super().delete(**kwargs)
def select(self):
super().select()
self.redraw()
def unselect(self):
super().unselect()
self.redraw()
def redraw(self):
super().redraw()
if self.texture:
self.texture.invalidate()
async def draw(self, update_state=True, **kwargs):
if self.obj_1 is None or self.obj_2 is None:
return
prev_rotation = kwargs.get("rotation", self.rotation)
p1 = self.obj_1.port_center(BaseElement.PORT_OUT, self.port_1)
p2 = self.obj_2.port_center(BaseElement.PORT_IN, self.port_2)
if self.dsp_connect is True:
width = 2.5 * self.LINE_WIDTH
else:
width = 1.5 * self.LINE_WIDTH
height = ((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2) ** 0.5
theta = math.atan2(p1[0] - p2[0], p2[1] - p1[1])
rotation = theta * 180.0 / math.pi
position_x = p1[0] - math.cos(theta) * width / 2.0
position_y = p1[1] - math.sin(theta) * width / 2.0
await self.move(position_x, position_y, update_state=update_state, **kwargs)
if update_state and abs(prev_rotation-rotation) > BaseElement.TINY_DELTA:
await self.dispatch(
self.action(
self.SET_ROTATION,
value=rotation,
),
previous=dict(rotation=prev_rotation)
)
else:
self.rotation = rotation
self.group.set_position(self.position_x, self.position_y)
self.group.set_rotation(Clutter.RotateAxis.Z_AXIS, self.rotation, 0, 0, 0)
await self.set_size(
math.ceil(width), math.ceil(height),
update_state=update_state,
**kwargs
)
if self.texture:
self.texture.invalidate()
def draw_cb(self, texture, ctx, width, height):
# clear the drawing area
ctx.save()
ctx.set_operator(cairo.OPERATOR_CLEAR)
ctx.paint()
ctx.restore()
ctx.set_operator(cairo.OPERATOR_OVER)
ctx.set_antialias(cairo.ANTIALIAS_NONE)
if self.dsp_connect:
lw = 2.0 * self.LINE_WIDTH
else:
lw = self.LINE_WIDTH
ctx.set_line_width(lw)
if self.dashed:
ctx.set_dash([4, 4])
else:
ctx.set_dash([])
ctx.translate(width/2.0, lw/2.0)
ctx.move_to(0, 0)
ctx.line_to(0, height)
ctx.close_path()
c = ColorDB().normalize(self.get_color('stroke-color'))
ctx.set_source_rgba(c.red, c.green, c.blue, c.alpha)
ctx.stroke()
return True
def draw_ports(self):
pass
async def set_size(self, width, height, **kwargs):
await super().set_size(width, height, **kwargs)
if self.texture:
self.texture.set_size(width, height)
self.texture.invalidate()
async def move(self, x, y, **kwargs):
await super().move(x, y, **kwargs)
self.group.set_position(x, y)
def corners(self):
if self.obj_1 and self.obj_2:
p1 = self.obj_1.port_center(BaseElement.PORT_OUT, self.port_1)
p2 = self.obj_2.port_center(BaseElement.PORT_IN, self.port_2)
return [p1, p2]
return None