summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2016-07-07 16:30:33 +0200
committerSebastian Koslowski <koslowski@kit.edu>2016-07-13 16:35:49 +0200
commit5cef62d03e3a750bce7f180930ceb777f7dba6b2 (patch)
treef6f5996cdbe60a497a28ae27226aebb220f31ee7
parent74e7af6cd0eb5e2f3892b42f08b0089ed2f2fec0 (diff)
grc: gtk3: refactor and update draw code WIP
-rw-r--r--grc/gui/Block.py32
-rw-r--r--grc/gui/Connection.py26
-rw-r--r--grc/gui/Element.py76
-rw-r--r--grc/gui/FlowGraph.py76
-rw-r--r--grc/gui/Port.py26
5 files changed, 115 insertions, 121 deletions
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 225881fec8..a38e4cc59a 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -41,7 +41,7 @@ class Block(Element, _Block):
def __init__(self, flow_graph, n):
"""
- Block contructor.
+ Block constructor.
Add graphics related params to the block.
"""
_Block.__init__(self, flow_graph, n)
@@ -113,8 +113,10 @@ class Block(Element, _Block):
def create_shapes(self):
"""Update the block, parameters, and ports when a change occurs."""
Element.create_shapes(self)
- if self.is_horizontal(): self.add_area((0, 0), (self.W, self.H))
- elif self.is_vertical(): self.add_area((0, 0), (self.H, self.W))
+ if self.is_horizontal():
+ self.add_area(0, 0, self.W, self.H)
+ elif self.is_vertical():
+ self.add_area(0, 0, self.H, self.W)
def create_labels(self):
"""Create the labels for the signal block."""
@@ -205,31 +207,30 @@ class Block(Element, _Block):
"""
Draw the signal block with label and inputs/outputs.
"""
- # draw ports
- for port in self.get_ports_gui():
- port.draw(widget, cr)
# draw main block
+ bg_color = self._bg_color
border_color = (
Colors.HIGHLIGHT_COLOR if self.is_highlighted() else
Colors.MISSING_BLOCK_BORDER_COLOR if self.is_dummy_block else
Colors.BORDER_COLOR
)
- Element.draw(self, widget, cr, border_color, self._bg_color)
- x, y = self.get_coordinate()
- # create the image surface
+
+ for port in self.get_ports_gui():
+ cr.save()
+ port.draw(widget, cr, border_color, bg_color)
+ cr.restore()
+ Element.draw(self, widget, cr, border_color, bg_color)
+
+ # create the param label
width = self.label_width
cr.set_source_rgb(*self._bg_color)
- cr.save()
if self.is_horizontal():
- cr.translate(x + BLOCK_LABEL_PADDING, y + (self.H - self.label_height) / 2)
+ cr.translate(BLOCK_LABEL_PADDING, (self.H - self.label_height) / 2)
elif self.is_vertical():
- cr.translate(x + (self.H - self.label_height) / 2, y + BLOCK_LABEL_PADDING)
+ cr.translate((self.H - self.label_height) / 2, BLOCK_LABEL_PADDING)
cr.rotate(-90 * math.pi / 180.)
cr.translate(-width, 0)
- # cr.rectangle(0, 0, width, height)
- # cr.fill()
-
# draw the layouts
h_off = 0
for i, layout in enumerate(self._param_layouts):
@@ -243,7 +244,6 @@ class Block(Element, _Block):
PangoCairo.show_layout(cr, layout)
cr.translate(-w_off, -h_off)
h_off += h + LABEL_SEPARATION
- cr.restore()
def what_is_selected(self, coor, coor_m=None):
"""
diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py
index b1a22e3949..ce40a3b036 100644
--- a/grc/gui/Connection.py
+++ b/grc/gui/Connection.py
@@ -42,7 +42,6 @@ class Connection(Element, _Connection):
def __init__(self, **kwargs):
Element.__init__(self)
_Connection.__init__(self, **kwargs)
- # can't use Colors.CONNECTION_ENABLED_COLOR here, might not be defined (grcc)
self._bg_color = self._arrow_color = self._color = None
self._sink_rot = self._source_rot = None
@@ -112,16 +111,14 @@ class Connection(Element, _Connection):
self.clear()
#source connector
source = self.source_port
- X, Y = source.get_connector_coordinate()
- x1, y1 = self.x1 + X, self.y1 + Y
- self.add_line((x1, y1), (X, Y))
+ x0, y0 = p0 = source.get_connector_coordinate()
+ x1, y1 = p1 = self.x1 + x0, self.y1 + y0
#sink connector
sink = self.sink_port
- X, Y = sink.get_connector_coordinate()
- x2, y2 = self.x2 + X, self.y2 + Y
- self.add_line((x2, y2), (X, Y))
+ x3, y3 = p3 = sink.get_connector_coordinate()
+ x2, y2 = p2 = self.x2 + x3, self.y2 + y3
#adjust arrow
- self._arrow = [(x+X, y+Y) for x, y in self.arrow]
+ self._arrow = [(x + x3, y + y3) for x, y in self.arrow]
#add the horizontal and vertical lines in this connection
if abs(source.get_connector_direction() - sink.get_connector_direction()) == 180:
#2 possible point sets to create a 3-line connector
@@ -133,11 +130,9 @@ class Connection(Element, _Connection):
if Utils.get_angle_from_coordinates(points[0][0], (x2, y2)) == sink.get_connector_direction(): points.reverse()
#points[0][0] -> source connector should not be in the direction of source
if Utils.get_angle_from_coordinates(points[0][0], (x1, y1)) == source.get_connector_direction(): points.reverse()
- #create 3-line connector
- p1, p2 = list(map(int, points[0][0])), list(map(int, points[0][1]))
- self.add_line((x1, y1), p1)
- self.add_line(p1, p2)
- self.add_line((x2, y2), p2)
+ # create 3-line connector
+ i1, i2 = list(map(int, points[0][0])), list(map(int, points[0][1]))
+ self.add_line(p0, p1, i1, i2, p2, p3)
else:
#2 possible points to create a right-angled connector
points = [(x1, y2), (x2, y1)]
@@ -148,8 +143,8 @@ class Connection(Element, _Connection):
#points[0] -> source connector should not be in the direction of source
if Utils.get_angle_from_coordinates(points[0], (x1, y1)) == source.get_connector_direction(): points.reverse()
#create right-angled connector
- self.add_line((x1, y1), points[0])
- self.add_line((x2, y2), points[0])
+ i1 = points[0]
+ self.add_line(p0, p1, i1, p2, p3)
def draw(self, widget, cr):
"""
@@ -176,6 +171,7 @@ class Connection(Element, _Connection):
Colors.CONNECTION_DISABLED_COLOR if not self.get_enabled() else
color
)
+ cr.set_dash([5, 5], 0.0)
Element.draw(self, widget, cr, mod_color(self._color), mod_color(self._bg_color))
# draw arrow on sink port
cr.set_source_rgb(*self._arrow_color)
diff --git a/grc/gui/Element.py b/grc/gui/Element.py
index 48fdf62543..c4d5b5e47d 100644
--- a/grc/gui/Element.py
+++ b/grc/gui/Element.py
@@ -42,7 +42,7 @@ class Element(object):
self.set_rotation(POSSIBLE_ROTATIONS[0])
self.set_coordinate((0, 0))
self.clear()
- self.set_highlighted(False)
+ self.highlighted = False
self.line_attributes = []
""" # No idea where this is in pygobject
0, Gdk.LINE_SOLID, Gdk.CAP_BUTT, Gdk.JOIN_MITER
@@ -102,21 +102,22 @@ class Element(object):
bg_color: the color for the inside of the rectangle
"""
X, Y = self.get_coordinate()
- # TODO: gc.set_line_attributes(*self.line_attributes)
- for (rX, rY), (W, H) in self._areas_list:
- aX = X + rX
- aY = Y + rY
+ cr.translate(X, Y)
+ for area in self._areas_list:
+ # aX = X + rX
+ # aY = Y + rY
cr.set_source_rgb(*bg_color)
- cr.rectangle(aX, aY, W, H)
+ cr.rectangle(*area)
cr.fill()
cr.set_source_rgb(*border_color)
- cr.rectangle(aX, aY, W, H)
+ cr.rectangle(*area)
cr.stroke()
- for (x1, y1), (x2, y2) in self._lines_list:
- cr.set_source_rgb(*border_color)
- cr.move_to(X + x1, Y + y1)
- cr.line_to(X + x2, Y + y2)
+ cr.set_source_rgb(*border_color)
+ for line in self._lines_list:
+ cr.move_to(*line[0])
+ for point in line[1:]:
+ cr.line_to(*point)
cr.stroke()
def rotate(self, rotation):
@@ -142,15 +143,6 @@ class Element(object):
"""
self.coor = coor
- # def get_parent(self):
- # """
- # Get the parent of this element.
- #
- # Returns:
- # the parent
- # """
- # return self.parent
-
def set_highlighted(self, highlighted):
"""
Set the highlight status.
@@ -188,7 +180,7 @@ class Element(object):
X, Y = self.get_coordinate()
self.set_coordinate((X+deltaX, Y+deltaY))
- def add_area(self, rel_coor, area):
+ def add_area(self, x, y, w, h):
"""
Add an area to the area list.
An area is actually a coordinate relative to the main coordinate
@@ -196,25 +188,17 @@ class Element(object):
A positive width is to the right of the coordinate.
A positive height is above the coordinate.
The area is associated with a rotation.
-
- Args:
- rel_coor: (x,y) offset from this element's coordinate
- area: (width,height) tuple
"""
- self._areas_list.append((rel_coor, area))
+ self._areas_list.append([x, y, w, h])
- def add_line(self, rel_coor1, rel_coor2):
+ def add_line(self, *points):
"""
Add a line to the line list.
- A line is defined by 2 relative coordinates.
+ A line is defined by 2 or more relative coordinates.
Lines must be horizontal or vertical.
The line is associated with a rotation.
-
- Args:
- rel_coor1: relative (x1,y1) tuple
- rel_coor2: relative (x2,y2) tuple
"""
- self._lines_list.append((rel_coor1, rel_coor2))
+ self._lines_list.append(points)
def what_is_selected(self, coor, coor_m=None):
"""
@@ -239,27 +223,33 @@ class Element(object):
if coor_m:
x_m, y_m = [a-b for a,b in zip(coor_m, self.get_coordinate())]
#handle rectangular areas
- for (x1,y1), (w,h) in self._areas_list:
+ for x1, y1, w, h in self._areas_list:
if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
in_between(x1+w, x, x_m) and in_between(y1, y, y_m) or \
in_between(x1, x, x_m) and in_between(y1+h, y, y_m) or \
in_between(x1+w, x, x_m) and in_between(y1+h, y, y_m):
return self
#handle horizontal or vertical lines
- for (x1, y1), (x2, y2) in self._lines_list:
- if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
- in_between(x2, x, x_m) and in_between(y2, y, y_m):
- return self
+ for line in self._lines_list:
+ last_point = line[0]
+ for x2, y2 in line[1:]:
+ (x1, y1), last_point = last_point, (x2, y2)
+ if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
+ in_between(x2, x, x_m) and in_between(y2, y, y_m):
+ return self
return None
else:
#handle rectangular areas
- for (x1,y1), (w,h) in self._areas_list:
+ for x1, y1, w, h in self._areas_list:
if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): return self
#handle horizontal or vertical lines
- for (x1, y1), (x2, y2) in self._lines_list:
- if x1 == x2: x1, x2 = x1-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY
- if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY
- if in_between(x, x1, x2) and in_between(y, y1, y2): return self
+ for line in self._lines_list:
+ last_point = line[0]
+ for x2, y2 in line[1:]:
+ (x1, y1), last_point = last_point, (x2, y2)
+ if x1 == x2: x1, x2 = x1-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY
+ if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY
+ if in_between(x, x1, x2) and in_between(y, y1, y2): return self
return None
def get_rotation(self):
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index 77615f13b0..dc80a4c87e 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -22,14 +22,11 @@ from __future__ import absolute_import
import functools
import random
from distutils.spawn import find_executable
-from itertools import chain, count
-from operator import methodcaller
+from itertools import count
import six
from six.moves import filter
-from gi.repository import GObject
-
from . import Actions, Colors, Utils, Bars, Dialogs
from .Element import Element
from .external_editor import ExternalEditor
@@ -67,7 +64,9 @@ class FlowGraph(Element, _Flowgraph):
#context menu
self._context_menu = Bars.ContextMenu()
self.get_context_menu = lambda: self._context_menu
+ self._elements_to_draw = []
+ self._elements_to_draw = []
self._external_updaters = {}
def _get_unique_id(self, base_id=''):
@@ -199,6 +198,7 @@ class FlowGraph(Element, _Flowgraph):
Args:
clipboard: the nested data of blocks, connections
"""
+ # todo: rewrite this...
selected = set()
(x_min, y_min), blocks_n, connections_n = clipboard
old_id2block = dict()
@@ -400,44 +400,58 @@ class FlowGraph(Element, _Flowgraph):
changed = True
return changed
+ def update_elements_to_draw(self):
+ hide_disabled_blocks = Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active()
+ hide_variables = Actions.TOGGLE_HIDE_VARIABLES.get_active()
+
+ def draw_order(elem):
+ return elem.highlighted, elem.is_block, elem.get_enabled()
+
+ elements = sorted(self.get_elements(), key=draw_order)
+ del self._elements_to_draw[:]
+
+ for element in elements:
+ if hide_disabled_blocks and not element.get_enabled():
+ continue # skip hidden disabled blocks and connections
+ if hide_variables and (element.is_variable or element.is_import):
+ continue # skip hidden disabled blocks and connections
+ self._elements_to_draw.append(element)
+
+ def _drawables(self):
+ show_comments = Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active()
+ for element in self._elements_to_draw:
+ if element.is_block and show_comments and element.get_enabled():
+ yield element.draw_comment
+ for element in self._elements_to_draw:
+ yield element.draw
+
def draw(self, widget, cr):
- """
- Draw the background and grid if enabled.
- """
- # draw comments first
- if Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active():
- for block in self.blocks:
- if block.get_enabled():
- block.draw_comment(widget, cr)
+ """Draw blocks connections comment and select rectangle"""
+ # todo: only update if required, duplicate logic in
+ self.update_elements_to_draw()
+
+ for draw_element in self._drawables():
+ cr.save()
+ draw_element(widget, cr)
+ cr.restore()
+
# draw multi select rectangle
- if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()):
+ if self.mouse_pressed and (not self.selected_elements or self.get_ctrl_mask()):
x1, y1 = self.press_coor
x2, y2 = self.get_coordinate()
x, y = int(min(x1, x2)), int(min(y1, y2))
w, h = int(abs(x1 - x2)), int(abs(y1 - y2))
- cr.set_source_rgb(*Colors.HIGHLIGHT_COLOR)
+ cr.set_source_rgba(
+ Colors.HIGHLIGHT_COLOR[0],
+ Colors.HIGHLIGHT_COLOR[1],
+ Colors.HIGHLIGHT_COLOR[2],
+ 0.5,
+ )
cr.rectangle(x, y, w, h)
cr.fill()
- cr.set_source_rgb(*Colors.BORDER_COLOR)
cr.rectangle(x, y, w, h)
cr.stroke()
- # draw blocks on top of connections
- hide_disabled_blocks = Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active()
- hide_variables = Actions.TOGGLE_HIDE_VARIABLES.get_active()
- blocks = sorted(self.blocks, key=methodcaller('get_enabled'))
-
- for element in chain(self.connections, blocks):
- if hide_disabled_blocks and not element.get_enabled():
- continue # skip hidden disabled blocks and connections
- if hide_variables and (element.is_variable or element.is_import):
- continue # skip hidden disabled blocks and connections
- element.draw(widget, cr)
-
- # draw selected blocks on top of selected connections
- for selected_element in self.get_selected_connections() + self.get_selected_blocks():
- selected_element.draw(widget, cr)
-
def update_selected(self):
"""
Remove deleted elements from the selected elements list.
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
index 62086c76e4..8945aa8c28 100644
--- a/grc/gui/Port.py
+++ b/grc/gui/Port.py
@@ -106,22 +106,22 @@ class Port(_Port, Element):
if (self.is_sink and rotation == 0) or (self.is_source and rotation == 180):
x = -W
y = port_separation*index+offset
- self.add_area((x, y), (W, self.H))
+ self.add_area(x, y, W, self.H)
self._connector_coordinate = (x-1, y+self.H/2)
elif (self.is_source and rotation == 0) or (self.is_sink and rotation == 180):
x = self.parent.W
y = port_separation*index+offset
- self.add_area((x, y), (W, self.H))
+ self.add_area(x, y, W, self.H)
self._connector_coordinate = (x+1+W, y+self.H/2)
elif (self.is_source and rotation == 90) or (self.is_sink and rotation == 270):
y = -W
x = port_separation*index+offset
- self.add_area((x, y), (self.H, W))
+ self.add_area(x, y, self.H, W)
self._connector_coordinate = (x+self.H/2, y-1)
elif (self.is_sink and rotation == 90) or (self.is_source and rotation == 270):
y = self.parent.W
x = port_separation*index+offset
- self.add_area((x, y), (self.H, W))
+ self.add_area(x, y, self.H, W)
self._connector_coordinate = (x+self.H/2, y+1+W)
#the connector length
self.connector_length = Constants.CONNECTOR_EXTENSION_MINIMAL + Constants.CONNECTOR_EXTENSION_INCREMENT * index
@@ -132,32 +132,26 @@ class Port(_Port, Element):
name=Utils.encode(self.get_name()), font=Constants.PORT_FONT
))
- def draw(self, widget, cr):
+ def draw(self, widget, cr, border_color, bg_color):
"""
Draw the socket with a label.
"""
- border_color = (
- Colors.HIGHLIGHT_COLOR if self.is_highlighted() else
- Colors.MISSING_BLOCK_BORDER_COLOR if self.parent.is_dummy_block else
- Colors.BORDER_COLOR
- )
Element.draw(self, widget, cr, border_color, self._bg_color)
if not self._areas_list or self._label_hidden():
return # this port is either hidden (no areas) or folded (no label)
- X, Y = self.get_coordinate()
- (x, y), _ = self._areas_list[0]
+
+ x, y, _, __ = self._areas_list[0]
+
cr.set_source_rgb(*self._bg_color)
- cr.save()
if self.is_horizontal():
- cr.translate(x + X + (self.W - self.w) / 2, y + Y + (self.H - self.h) / 2)
+ cr.translate(x + (self.W - self.w) / 2, y + (self.H - self.h) / 2)
elif self.is_vertical():
- cr.translate(x + X + (self.H - self.h) / 2, y + Y + (self.W - self.w) / 2)
+ cr.translate(x + (self.H - self.h) / 2, y + (self.W - self.w) / 2)
cr.rotate(-90 * math.pi / 180.)
cr.translate(-self.w, 0)
PangoCairo.update_layout(cr, self.layout)
PangoCairo.show_layout(cr, self.layout)
- cr.restore()
def get_connector_coordinate(self):
"""