Преглед изворни кода

- moved the key handler out of the Measurement tool to flatcamGUI.FlatCAMGui.keyPressEvent()
- Gerber Editor: started to add new function of poligonize which should make a filled polygon out of a shape

Marius Stanciu пре 6 година
родитељ
комит
1332601624

+ 2 - 0
README.md

@@ -16,6 +16,8 @@ CAD program, and create G-Code for Isolation routing.
 - Editors: activated an old function that was no longer active: each tool can have it's own set of shortcut keys, the Editor general shortcut keys that are letters are overridden
 - Editors: activated an old function that was no longer active: each tool can have it's own set of shortcut keys, the Editor general shortcut keys that are letters are overridden
 - Gerber and Geometry editors, when using the Backspace keys for certain tools, they will backtrack one point but now the utility geometry is immediately updated
 - Gerber and Geometry editors, when using the Backspace keys for certain tools, they will backtrack one point but now the utility geometry is immediately updated
 - In Geometry Editor I fixed bug in Arc modes. Arc mode shortcut key is now key 'M' and arc direction change shortcut key is 'D'
 - In Geometry Editor I fixed bug in Arc modes. Arc mode shortcut key is now key 'M' and arc direction change shortcut key is 'D'
+- moved the key handler out of the Measurement tool to flatcamGUI.FlatCAMGui.keyPressEvent()
+- Gerber Editor: started to add new function of poligonize which should make a filled polygon out of a shape
 
 
 13.04.2019
 13.04.2019
 
 

+ 60 - 1
camlib.py

@@ -26,10 +26,11 @@ from rtree import index as rtindex
 from lxml import etree as ET
 from lxml import etree as ET
 
 
 # See: http://toblerity.org/shapely/manual.html
 # See: http://toblerity.org/shapely/manual.html
+
 from shapely.geometry import Polygon, LineString, Point, LinearRing, MultiLineString
 from shapely.geometry import Polygon, LineString, Point, LinearRing, MultiLineString
 from shapely.geometry import MultiPoint, MultiPolygon
 from shapely.geometry import MultiPoint, MultiPolygon
 from shapely.geometry import box as shply_box
 from shapely.geometry import box as shply_box
-from shapely.ops import cascaded_union, unary_union
+from shapely.ops import cascaded_union, unary_union, polygonize
 import shapely.affinity as affinity
 import shapely.affinity as affinity
 from shapely.wkt import loads as sloads
 from shapely.wkt import loads as sloads
 from shapely.wkt import dumps as sdumps
 from shapely.wkt import dumps as sdumps
@@ -45,6 +46,7 @@ import ezdxf
 
 
 # TODO: Commented for FlatCAM packaging with cx_freeze
 # TODO: Commented for FlatCAM packaging with cx_freeze
 # from scipy.spatial import KDTree, Delaunay
 # from scipy.spatial import KDTree, Delaunay
+from scipy.spatial import Delaunay
 
 
 from flatcamParsers.ParseSVG import *
 from flatcamParsers.ParseSVG import *
 from flatcamParsers.ParseDXF import *
 from flatcamParsers.ParseDXF import *
@@ -7348,6 +7350,63 @@ def parse_gerber_number(strnumber, int_digits, frac_digits, zeros):
     return ret_val
     return ret_val
 
 
 
 
+def alpha_shape(points, alpha):
+    """
+    Compute the alpha shape (concave hull) of a set of points.
+
+    @param points: Iterable container of points.
+    @param alpha: alpha value to influence the gooeyness of the border. Smaller
+                  numbers don't fall inward as much as larger numbers. Too large,
+                  and you lose everything!
+    """
+    if len(points) < 4:
+        # When you have a triangle, there is no sense in computing an alpha
+        # shape.
+        return MultiPoint(list(points)).convex_hull
+
+    def add_edge(edges, edge_points, coords, i, j):
+        """Add a line between the i-th and j-th points, if not in the list already"""
+        if (i, j) in edges or (j, i) in edges:
+            # already added
+            return
+        edges.add( (i, j) )
+        edge_points.append(coords[ [i, j] ])
+
+    coords = np.array([point.coords[0] for point in points])
+
+    tri = Delaunay(coords)
+    edges = set()
+    edge_points = []
+    # loop over triangles:
+    # ia, ib, ic = indices of corner points of the triangle
+    for ia, ib, ic in tri.vertices:
+        pa = coords[ia]
+        pb = coords[ib]
+        pc = coords[ic]
+
+        # Lengths of sides of triangle
+        a = math.sqrt((pa[0]-pb[0])**2 + (pa[1]-pb[1])**2)
+        b = math.sqrt((pb[0]-pc[0])**2 + (pb[1]-pc[1])**2)
+        c = math.sqrt((pc[0]-pa[0])**2 + (pc[1]-pa[1])**2)
+
+        # Semiperimeter of triangle
+        s = (a + b + c)/2.0
+
+        # Area of triangle by Heron's formula
+        area = math.sqrt(s*(s-a)*(s-b)*(s-c))
+        circum_r = a*b*c/(4.0*area)
+
+        # Here's the radius filter.
+        #print circum_r
+        if circum_r < 1.0/alpha:
+            add_edge(edges, edge_points, coords, ia, ib)
+            add_edge(edges, edge_points, coords, ib, ic)
+            add_edge(edges, edge_points, coords, ic, ia)
+
+    m = MultiLineString(edge_points)
+    triangles = list(polygonize(m))
+    return cascaded_union(triangles), edge_points
+
 # def voronoi(P):
 # def voronoi(P):
 #     """
 #     """
 #     Returns a list of all edges of the voronoi diagram for the given input points.
 #     Returns a list of all edges of the voronoi diagram for the given input points.

+ 3 - 3
flatcamEditors/FlatCAMExcEditor.py

@@ -1683,12 +1683,12 @@ class FlatCAMExcEditor(QtCore.QObject):
 
 
         self.canvas.vis_connect('mouse_press', self.on_canvas_click)
         self.canvas.vis_connect('mouse_press', self.on_canvas_click)
         self.canvas.vis_connect('mouse_move', self.on_canvas_move)
         self.canvas.vis_connect('mouse_move', self.on_canvas_move)
-        self.canvas.vis_connect('mouse_release', self.on_canvas_click_release)
+        self.canvas.vis_connect('mouse_release', self.on_exc_click_release)
 
 
     def disconnect_canvas_event_handlers(self):
     def disconnect_canvas_event_handlers(self):
         self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
         self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
         self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
         self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
-        self.canvas.vis_disconnect('mouse_release', self.on_canvas_click_release)
+        self.canvas.vis_disconnect('mouse_release', self.on_exc_click_release)
 
 
         # we restore the key and mouse control to FlatCAMApp method
         # we restore the key and mouse control to FlatCAMApp method
         self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
         self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
@@ -2136,7 +2136,7 @@ class FlatCAMExcEditor(QtCore.QObject):
         else:
         else:
             self.storage.insert(shape)  # TODO: Check performance
             self.storage.insert(shape)  # TODO: Check performance
 
 
-    def on_canvas_click_release(self, event):
+    def on_exc_click_release(self, event):
         pos_canvas = self.canvas.vispy_canvas.translate_coords(event.pos)
         pos_canvas = self.canvas.vispy_canvas.translate_coords(event.pos)
 
 
         self.modifiers = QtWidgets.QApplication.keyboardModifiers()
         self.modifiers = QtWidgets.QApplication.keyboardModifiers()

+ 3 - 3
flatcamEditors/FlatCAMGeoEditor.py

@@ -2973,13 +2973,13 @@ class FlatCAMGeoEditor(QtCore.QObject):
 
 
         self.canvas.vis_connect('mouse_press', self.on_canvas_click)
         self.canvas.vis_connect('mouse_press', self.on_canvas_click)
         self.canvas.vis_connect('mouse_move', self.on_canvas_move)
         self.canvas.vis_connect('mouse_move', self.on_canvas_move)
-        self.canvas.vis_connect('mouse_release', self.on_canvas_click_release)
+        self.canvas.vis_connect('mouse_release', self.on_geo_click_release)
 
 
     def disconnect_canvas_event_handlers(self):
     def disconnect_canvas_event_handlers(self):
 
 
         self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
         self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
         self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
         self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
-        self.canvas.vis_disconnect('mouse_release', self.on_canvas_click_release)
+        self.canvas.vis_disconnect('mouse_release', self.on_geo_click_release)
 
 
         # we restore the key and mouse control to FlatCAMApp method
         # we restore the key and mouse control to FlatCAMApp method
         self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
         self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
@@ -3310,7 +3310,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
         # Update cursor
         # Update cursor
         self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
         self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
 
 
-    def on_canvas_click_release(self, event):
+    def on_geo_click_release(self, event):
         pos_canvas = self.canvas.vispy_canvas.translate_coords(event.pos)
         pos_canvas = self.canvas.vispy_canvas.translate_coords(event.pos)
 
 
         if self.app.grid_status():
         if self.app.grid_status():

+ 72 - 3
flatcamEditors/FlatCAMGrbEditor.py

@@ -476,6 +476,73 @@ class FCPadArray(FCShapeTool):
         self.draw_app.plot_all()
         self.draw_app.plot_all()
 
 
 
 
+class FCPoligonize(FCShapeTool):
+    """
+    Resulting type: Polygon
+    """
+
+    def __init__(self, draw_app):
+        DrawTool.__init__(self, draw_app)
+        self.name = 'poligonize'
+        self.draw_app = draw_app
+
+        self.start_msg = _("Select shape(s) and then click ...")
+        self.draw_app.in_action = True
+        self.make()
+
+    def click(self, point):
+        # self.draw_app.in_action = True
+        # if self.draw_app.selected:
+        #     self.make()
+        # else:
+        #     self.draw_app.app.inform.emit(_("[WARNING_NOTCL] No shapes are selected. Select shapes and try again ..."))
+
+        return ""
+
+    def make(self):
+        geo = []
+
+        for shape in self.draw_app.selected:
+            current_storage = self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['solid_geometry']
+            print(self.draw_app.active_tool)
+            aha = []
+            if shape.geo:
+                shape_points = list(shape.geo.exterior.coords)
+                for pt in shape_points:
+                    aha.append(Point(pt))
+                concave_hull, bla_bla = alpha_shape(points=aha, alpha=0.5)
+                geo.append(concave_hull)
+                print(geo)
+                self.geometry = DrawToolShape(geo)
+                self.draw_app.on_grb_shape_complete(current_storage)
+
+        self.draw_app.in_action = False
+        self.complete = True
+        self.draw_app.app.inform.emit(_("[success] Done. Poligonize completed."))
+
+        self.draw_app.build_ui()
+        # MS: always return to the Select Tool if modifier key is not pressed
+        # else return to the current tool
+
+        key_modifier = QtWidgets.QApplication.keyboardModifiers()
+        if self.draw_app.app.defaults["global_mselect_key"] == 'Control':
+            modifier_to_use = Qt.ControlModifier
+        else:
+            modifier_to_use = Qt.ShiftModifier
+        # if modifier key is pressed then we add to the selected list the current shape but if it's already
+        # in the selected list, we removed it. Therefore first click selects, second deselects.
+        if key_modifier == modifier_to_use:
+            self.draw_app.select_tool(self.draw_app.active_tool.name)
+        else:
+            self.draw_app.select_tool("select")
+            return
+
+    def clean_up(self):
+        self.draw_app.selected = []
+        self.draw_app.apertures_table.clearSelection()
+        self.draw_app.plot_all()
+
+
 class FCRegion(FCShapeTool):
 class FCRegion(FCShapeTool):
     """
     """
     Resulting type: Polygon
     Resulting type: Polygon
@@ -1259,6 +1326,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
                               "constructor": FCTrack},
                               "constructor": FCTrack},
             "region": {"button": self.app.ui.grb_add_region_btn,
             "region": {"button": self.app.ui.grb_add_region_btn,
                               "constructor": FCRegion},
                               "constructor": FCRegion},
+            "poligonize": {"button": self.app.ui.grb_convert_poly_btn,
+                       "constructor": FCPoligonize},
             "buffer": {"button": self.app.ui.aperture_buffer_btn,
             "buffer": {"button": self.app.ui.aperture_buffer_btn,
                                 "constructor": FCBuffer},
                                 "constructor": FCBuffer},
             "scale": {"button": self.app.ui.aperture_scale_btn,
             "scale": {"button": self.app.ui.aperture_scale_btn,
@@ -1918,12 +1987,12 @@ class FlatCAMGrbEditor(QtCore.QObject):
 
 
         self.canvas.vis_connect('mouse_press', self.on_canvas_click)
         self.canvas.vis_connect('mouse_press', self.on_canvas_click)
         self.canvas.vis_connect('mouse_move', self.on_canvas_move)
         self.canvas.vis_connect('mouse_move', self.on_canvas_move)
-        self.canvas.vis_connect('mouse_release', self.on_canvas_click_release)
+        self.canvas.vis_connect('mouse_release', self.on_grb_click_release)
 
 
     def disconnect_canvas_event_handlers(self):
     def disconnect_canvas_event_handlers(self):
         self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
         self.canvas.vis_disconnect('mouse_press', self.on_canvas_click)
         self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
         self.canvas.vis_disconnect('mouse_move', self.on_canvas_move)
-        self.canvas.vis_disconnect('mouse_release', self.on_canvas_click_release)
+        self.canvas.vis_disconnect('mouse_release', self.on_grb_click_release)
 
 
         # we restore the key and mouse control to FlatCAMApp method
         # we restore the key and mouse control to FlatCAMApp method
         self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
         self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
@@ -2338,7 +2407,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
             else:
             else:
                 self.app.log.debug("No active tool to respond to click!")
                 self.app.log.debug("No active tool to respond to click!")
 
 
-    def on_canvas_click_release(self, event):
+    def on_grb_click_release(self, event):
         pos_canvas = self.canvas.vispy_canvas.translate_coords(event.pos)
         pos_canvas = self.canvas.vispy_canvas.translate_coords(event.pos)
 
 
         self.modifiers = QtWidgets.QApplication.keyboardModifiers()
         self.modifiers = QtWidgets.QApplication.keyboardModifiers()

+ 20 - 0
flatcamGUI/FlatCAMGUI.py

@@ -690,6 +690,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.add_pad_ar_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/padarray32.png'), _('Add Pad Array'))
         self.add_pad_ar_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/padarray32.png'), _('Add Pad Array'))
         self.grb_add_track_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/track32.png'), _("Add Track"))
         self.grb_add_track_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/track32.png'), _("Add Track"))
         self.grb_add_region_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/polygon32.png'), _("Add Region"))
         self.grb_add_region_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/polygon32.png'), _("Add Region"))
+        self.grb_convert_poly_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/polygon32.png'), _("Poligonize"))
+
         self.grb_edit_toolbar.addSeparator()
         self.grb_edit_toolbar.addSeparator()
 
 
         self.aperture_buffer_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/buffer16-2.png'), _('Buffer'))
         self.aperture_buffer_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/buffer16-2.png'), _('Buffer'))
@@ -2911,6 +2913,24 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
                 if key == QtCore.Qt.Key_F3 or key == 'F3':
                 if key == QtCore.Qt.Key_F3 or key == 'F3':
                     self.app.on_shortcut_list()
                     self.app.on_shortcut_list()
                     return
                     return
+        elif self.app.call_source == 'measurement':
+            if modifiers == QtCore.Qt.ControlModifier:
+                pass
+            elif modifiers == QtCore.Qt.AltModifier:
+                pass
+            elif modifiers == QtCore.Qt.ShiftModifier:
+                pass
+            elif modifiers == QtCore.Qt.NoModifier:
+                if key == QtCore.Qt.Key_Escape or key == 'Escape':
+                    # abort the measurement action
+                    self.app.measurement_tool.on_measure(activate=False)
+                    self.app.measurement_tool.deactivate_measure_tool()
+                    self.app.inform.emit(_("Measurement Tool exit..."))
+                    return
+
+                if key == QtCore.Qt.Key_G or key == 'G':
+                    self.app.ui.grid_snap_btn.trigger()
+                    return
 
 
     def dragEnterEvent(self, event):
     def dragEnterEvent(self, event):
         if event.mimeData().hasUrls:
         if event.mimeData().hasUrls:

+ 23 - 41
flatcamTools/ToolMeasurement.py

@@ -112,6 +112,8 @@ class Measurement(FlatCAMTool):
         # self.setVisible(False)
         # self.setVisible(False)
         self.active = 0
         self.active = 0
 
 
+        self.original_call_source = 'app'
+
         # VisPy visuals
         # VisPy visuals
         self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.vispy_canvas.view.scene, layers=1)
         self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.vispy_canvas.view.scene, layers=1)
 
 
@@ -125,7 +127,7 @@ class Measurement(FlatCAMTool):
 
 
         self.app.ui.notebook.setTabText(2, _("Meas. Tool"))
         self.app.ui.notebook.setTabText(2, _("Meas. Tool"))
 
 
-        # if the splitter is hidden, display it, else hide it but only if the current widget is the same
+        # if the splitter is hidden, display it
         if self.app.ui.splitter.sizes()[0] == 0:
         if self.app.ui.splitter.sizes()[0] == 0:
             self.app.ui.splitter.setSizes([1, 1])
             self.app.ui.splitter.setSizes([1, 1])
 
 
@@ -155,29 +157,22 @@ class Measurement(FlatCAMTool):
         self.distance_y_entry.set_value('0')
         self.distance_y_entry.set_value('0')
         self.total_distance_entry.set_value('0')
         self.total_distance_entry.set_value('0')
 
 
-    def activate(self):
+    def activate_measure_tool(self):
         # we disconnect the mouse/key handlers from wherever the measurement tool was called
         # we disconnect the mouse/key handlers from wherever the measurement tool was called
-        self.canvas.vis_disconnect('key_press')
         self.canvas.vis_disconnect('mouse_move')
         self.canvas.vis_disconnect('mouse_move')
         self.canvas.vis_disconnect('mouse_press')
         self.canvas.vis_disconnect('mouse_press')
         self.canvas.vis_disconnect('mouse_release')
         self.canvas.vis_disconnect('mouse_release')
-        self.canvas.vis_disconnect('key_release')
 
 
         # we can safely connect the app mouse events to the measurement tool
         # we can safely connect the app mouse events to the measurement tool
         self.canvas.vis_connect('mouse_move', self.on_mouse_move_meas)
         self.canvas.vis_connect('mouse_move', self.on_mouse_move_meas)
-        self.canvas.vis_connect('mouse_release', self.on_mouse_click)
-        self.canvas.vis_connect('key_release', self.on_key_release_meas)
+        self.canvas.vis_connect('mouse_release', self.on_mouse_click_release)
 
 
         self.set_tool_ui()
         self.set_tool_ui()
 
 
-    def deactivate(self):
+    def deactivate_measure_tool(self):
         # disconnect the mouse/key events from functions of measurement tool
         # disconnect the mouse/key events from functions of measurement tool
         self.canvas.vis_disconnect('mouse_move', self.on_mouse_move_meas)
         self.canvas.vis_disconnect('mouse_move', self.on_mouse_move_meas)
-        self.canvas.vis_disconnect('mouse_release', self.on_mouse_click)
-        self.canvas.vis_disconnect('key_release', self.on_key_release_meas)
-
-        # reconnect the mouse/key events to the functions from where the tool was called
-        self.canvas.vis_connect('key_press', self.app.ui.keyPressEvent)
+        self.canvas.vis_disconnect('mouse_release', self.on_mouse_click_release)
 
 
         if self.app.call_source == 'app':
         if self.app.call_source == 'app':
             self.canvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
             self.canvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
@@ -186,57 +181,44 @@ class Measurement(FlatCAMTool):
         elif self.app.call_source == 'geo_editor':
         elif self.app.call_source == 'geo_editor':
             self.canvas.vis_connect('mouse_move', self.app.geo_editor.on_canvas_move)
             self.canvas.vis_connect('mouse_move', self.app.geo_editor.on_canvas_move)
             self.canvas.vis_connect('mouse_press', self.app.geo_editor.on_canvas_click)
             self.canvas.vis_connect('mouse_press', self.app.geo_editor.on_canvas_click)
-            # self.canvas.vis_connect('key_press', self.app.geo_editor.on_canvas_key)
-            self.canvas.vis_connect('mouse_release', self.app.geo_editor.on_canvas_click_release)
+            self.canvas.vis_connect('mouse_release', self.app.geo_editor.on_geo_click_release)
         elif self.app.call_source == 'exc_editor':
         elif self.app.call_source == 'exc_editor':
             self.canvas.vis_connect('mouse_move', self.app.exc_editor.on_canvas_move)
             self.canvas.vis_connect('mouse_move', self.app.exc_editor.on_canvas_move)
             self.canvas.vis_connect('mouse_press', self.app.exc_editor.on_canvas_click)
             self.canvas.vis_connect('mouse_press', self.app.exc_editor.on_canvas_click)
-            # self.canvas.vis_connect('key_press', self.app.exc_editor.on_canvas_key)
-            self.canvas.vis_connect('mouse_release', self.app.exc_editor.on_canvas_click_release)
+            self.canvas.vis_connect('mouse_release', self.app.exc_editor.on_exc_click_release)
         elif self.app.call_source == 'grb_editor':
         elif self.app.call_source == 'grb_editor':
             self.canvas.vis_connect('mouse_move', self.app.grb_editor.on_canvas_move)
             self.canvas.vis_connect('mouse_move', self.app.grb_editor.on_canvas_move)
             self.canvas.vis_connect('mouse_press', self.app.grb_editor.on_canvas_click)
             self.canvas.vis_connect('mouse_press', self.app.grb_editor.on_canvas_click)
-            # self.canvas.vis_connect('key_press', self.app.grb_editor.on_canvas_key)
-            self.canvas.vis_connect('mouse_release', self.app.grb_editor.on_canvas_click_release)
+            self.canvas.vis_connect('mouse_release', self.app.grb_editor.on_grb_click_release)
 
 
         self.app.ui.notebook.setTabText(2, _("Tools"))
         self.app.ui.notebook.setTabText(2, _("Tools"))
         self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
         self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
 
 
     def on_measure(self, signal=None, activate=None):
     def on_measure(self, signal=None, activate=None):
         log.debug("Measurement.on_measure()")
         log.debug("Measurement.on_measure()")
-        if activate is False or activate is None:
-            # DISABLE the Measuring TOOL
-            self.deactivate()
-
-            self.app.command_active = None
-
-            # delete the measuring line
-            self.delete_shape()
-
-            log.debug("Measurement Tool --> exit tool")
-        elif activate is True:
+        if activate is True:
             # ENABLE the Measuring TOOL
             # ENABLE the Measuring TOOL
             self.clicked_meas = 0
             self.clicked_meas = 0
+            self.original_call_source = copy(self.app.call_source)
+            self.app.call_source = 'measurement'
 
 
             self.app.inform.emit(_("MEASURING: Click on the Start point ..."))
             self.app.inform.emit(_("MEASURING: Click on the Start point ..."))
             self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
             self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
 
 
-            self.activate()
+            self.activate_measure_tool()
             log.debug("Measurement Tool --> tool initialized")
             log.debug("Measurement Tool --> tool initialized")
+        else:
+            # DISABLE the Measuring TOOL
+            self.deactivate_measure_tool()
+            self.app.call_source = copy(self.original_call_source)
+            self.app.command_active = None
 
 
-    def on_key_release_meas(self, event):
-        if event.key == 'escape':
-            # abort the measurement action
-            self.on_measure(activate=False)
-            self.app.inform.emit(_("Measurement Tool exit..."))
-            return
+            # delete the measuring line
+            self.delete_shape()
 
 
-        if event.key == 'G':
-            # toggle grid status
-            self.app.ui.grid_snap_btn.trigger()
-            return
+            log.debug("Measurement Tool --> exit tool")
 
 
-    def on_mouse_click(self, event):
+    def on_mouse_click_release(self, event):
         # mouse click releases will be accepted only if the left button is clicked
         # mouse click releases will be accepted only if the left button is clicked
         # this is necessary because right mouse click or middle mouse click
         # this is necessary because right mouse click or middle mouse click
         # are used for panning on the canvas
         # are used for panning on the canvas