commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 27/101: grc: gtk3: refactor and update draw


From: git
Subject: [Commit-gnuradio] [gnuradio] 27/101: grc: gtk3: refactor and update draw code WIP
Date: Thu, 16 Mar 2017 14:58:01 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch python3
in repository gnuradio.

commit 5cef62d03e3a750bce7f180930ceb777f7dba6b2
Author: Sebastian Koslowski <address@hidden>
Date:   Thu Jul 7 16:30:33 2016 +0200

    grc: gtk3: refactor and update draw code WIP
---
 grc/gui/Block.py      | 32 +++++++++++-----------
 grc/gui/Connection.py | 26 ++++++++----------
 grc/gui/Element.py    | 76 ++++++++++++++++++++++-----------------------------
 grc/gui/FlowGraph.py  | 76 ++++++++++++++++++++++++++++++---------------------
 grc/gui/Port.py       | 26 +++++++-----------
 5 files changed, 115 insertions(+), 121 deletions(-)

diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 225881f..a38e4cc 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 b1a22e3..ce40a3b 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 48fdf62..c4d5b5e 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 77615f1..dc80a4c 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 62086c7..8945aa8 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):
         """



reply via email to

[Prev in Thread] Current Thread [Next in Thread]