diff --git a/FlatCAMApp.py b/FlatCAMApp.py index b6d39170..4d01e222 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -39,6 +39,8 @@ from array import array from ObjectCollection import * from FlatCAMObj import * from flatcamGUI.PlotCanvas import * +from flatcamGUI.PlotCanvasLegacy import * + from flatcamGUI.FlatCAMGUI import * from FlatCAMCommon import LoudDict from FlatCAMPostProc import load_postprocessors @@ -440,6 +442,7 @@ class App(QtCore.QObject): self.defaults_form_fields = { # General App "units": self.ui.general_defaults_form.general_app_group.units_radio, + "global_graphic_engine": self.ui.general_defaults_form.general_app_group.ge_radio, "global_app_level": self.ui.general_defaults_form.general_app_group.app_level_radio, "global_portable": self.ui.general_defaults_form.general_app_group.portability_cb, "global_language": self.ui.general_defaults_form.general_app_group.language_cb, @@ -825,6 +828,7 @@ class App(QtCore.QObject): "global_serial": 0, "global_stats": {}, "global_tabs_detachable": True, + "global_graphic_engine": '3D', "global_app_level": 'b', "global_portable": False, "global_language": 'English', @@ -1584,6 +1588,13 @@ class App(QtCore.QObject): # ############################################### # ############# SETUP Plot Area ################# # ############################################### + + # determine if the Legacy Graphic Engine is to be used or the OpenGL one + if self.defaults["global_graphic_engine"] == '3D': + self.is_legacy = False + else: + self.is_legacy = True + if show_splash: self.splash.showMessage(_("FlatCAM is initializing ...\n" "Canvas initialization started."), @@ -6694,12 +6705,12 @@ class App(QtCore.QObject): for obj in self.collection.get_list(): obj.plot() self.plotcanvas.fit_view() - self.plotcanvas.vis_disconnect('mouse_press', self.on_set_zero_click) + self.plotcanvas.graph_event_disconnect('mouse_press', self.on_set_zero_click) self.worker_task.emit({'fcn': worker_task, 'params': []}) self.inform.emit(_('Click to set the origin ...')) - self.plotcanvas.vis_connect('mouse_press', self.on_set_zero_click) + self.plotcanvas.graph_event_connect('mouse_press', self.on_set_zero_click) # first disconnect it as it may have been used by something else try: @@ -7525,19 +7536,31 @@ class App(QtCore.QObject): """ self.pos = [] + if self.is_legacy is False: + event_pos = event.pos + if self.defaults["global_pan_button"] == '2': + pan_button = 2 + else: + pan_button = 3 + # Set the mouse button for panning + self.plotcanvas.view.camera.pan_button_setting = pan_button + else: + event_pos = (event.xdata, event.ydata) + # Matplotlib has the middle and right buttons mapped in reverse compared with VisPy + if self.defaults["global_pan_button"] == '2': + pan_button = 3 + else: + pan_button = 2 + # So it can receive key presses self.plotcanvas.native.setFocus() - # Set the mouse button for panning - self.plotcanvas.view.camera.pan_button_setting = self.defaults['global_pan_button'] - self.pos_canvas = self.plotcanvas.translate_coords(event.pos) + self.pos_canvas = self.plotcanvas.translate_coords(event_pos) if self.grid_status() == True: self.pos = self.geo_editor.snap(self.pos_canvas[0], self.pos_canvas[1]) - self.app_cursor.enabled = True else: self.pos = (self.pos_canvas[0], self.pos_canvas[1]) - self.app_cursor.enabled = False try: modifiers = QtWidgets.QApplication.keyboardModifiers() @@ -7565,7 +7588,8 @@ class App(QtCore.QObject): App.log.debug("App.on_mouse_click_over_plot() --> Outside plot? --> %s" % str(e)) def on_double_click_over_plot(self, event): - self.doubleclick = True + if event.button == 1: + self.doubleclick = True def on_mouse_move_over_plot(self, event, origin_click=None): """ @@ -7576,29 +7600,49 @@ class App(QtCore.QObject): :return: None """ + if self.is_legacy is False: + event_pos = event.pos + if self.defaults["global_pan_button"] == '2': + pan_button = 2 + else: + pan_button = 3 + event_is_dragging = event.is_dragging + else: + event_pos = (event.xdata, event.ydata) + # Matplotlib has the middle and right buttons mapped in reverse compared with VisPy + if self.defaults["global_pan_button"] == '2': + pan_button = 3 + else: + pan_button = 2 + event_is_dragging = self.plotcanvas.is_dragging + # So it can receive key presses self.plotcanvas.native.setFocus() - self.pos_jump = event.pos + self.pos_jump = event_pos self.ui.popMenu.mouse_is_panning = False if not origin_click: # if the RMB is clicked and mouse is moving over plot then 'panning_action' is True - if event.button == 2 and event.is_dragging == 1: + if event.button == pan_button and event_is_dragging == 1: self.ui.popMenu.mouse_is_panning = True return if self.rel_point1 is not None: try: # May fail in case mouse not within axes - pos_canvas = self.plotcanvas.translate_coords(event.pos) + pos_canvas = self.plotcanvas.translate_coords(event_pos) + if self.grid_status() == True: pos = self.geo_editor.snap(pos_canvas[0], pos_canvas[1]) - self.app_cursor.enabled = True - # Update cursor - self.app_cursor.set_data(np.asarray([(pos[0], pos[1])]), symbol='++', edge_color='black', size=20) + + if self.is_legacy is False: + # Update cursor + self.app_cursor.set_data(np.asarray([(pos[0], pos[1])]), + symbol='++', edge_color='black', size=20) + else: + self.app_cursor.set_data((pos[0], pos[1])) else: pos = (pos_canvas[0], pos_canvas[1]) - self.app_cursor.enabled = False self.ui.position_label.setText("    X: %.4f   " "Y: %.4f" % (pos[0], pos[1])) @@ -7610,7 +7654,7 @@ class App(QtCore.QObject): self.mouse = [pos[0], pos[1]] # if the mouse is moved and the LMB is clicked then the action is a selection - if event.is_dragging == 1 and event.button == 1: + if event_is_dragging == 1 and event.button == 1: self.delete_selection_shape() if dx < 0: self.draw_moving_selection_shape(self.pos, pos, color=self.defaults['global_alt_sel_line'], @@ -7664,7 +7708,16 @@ class App(QtCore.QObject): :return: """ pos = 0, 0 - pos_canvas = self.plotcanvas.translate_coords(event.pos) + + if self.is_legacy is False: + event_pos = event.pos + right_button = 2 + else: + event_pos = (event.xdata, event.ydata) + # Matplotlib has the middle and right buttons mapped in reverse compared with VisPy + right_button = 3 + + pos_canvas = self.plotcanvas.translate_coords(event_pos) if self.grid_status() == True: pos = self.geo_editor.snap(pos_canvas[0], pos_canvas[1]) else: @@ -7672,7 +7725,7 @@ class App(QtCore.QObject): # if the released mouse button was RMB then test if it was a panning motion or not, if not it was a context # canvas menu - if event.button == 2: # right click + if event.button == right_button: # right click if self.ui.popMenu.mouse_is_panning is False: self.cursor = QtGui.QCursor() self.populate_cmenu_grids() @@ -10893,22 +10946,32 @@ class App(QtCore.QObject): else: plot_container = self.ui.right_layout - self.plotcanvas = PlotCanvas(plot_container, self) + if self.is_legacy is False: + self.plotcanvas = PlotCanvas(plot_container, self) + else: + self.plotcanvas = PlotCanvasLegacy(plot_container, self) # So it can receive key presses self.plotcanvas.native.setFocus() - self.plotcanvas.vis_connect('mouse_move', self.on_mouse_move_over_plot) - self.plotcanvas.vis_connect('mouse_press', self.on_mouse_click_over_plot) - self.plotcanvas.vis_connect('mouse_release', self.on_mouse_click_release_over_plot) - self.plotcanvas.vis_connect('mouse_double_click', self.on_double_click_over_plot) + self.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move_over_plot) + self.plotcanvas.graph_event_connect('mouse_press', self.on_mouse_click_over_plot) + self.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_click_release_over_plot) + self.plotcanvas.graph_event_connect('mouse_double_click', self.on_double_click_over_plot) # Keys over plot enabled - self.plotcanvas.vis_connect('key_press', self.ui.keyPressEvent) + self.plotcanvas.graph_event_connect('key_press', self.ui.keyPressEvent) self.app_cursor = self.plotcanvas.new_cursor() - self.app_cursor.enabled = False - self.hover_shapes = ShapeCollection(parent=self.plotcanvas.view.scene, layers=1) + if self.ui.grid_snap_btn.isChecked(): + self.app_cursor.enabled = True + else: + self.app_cursor.enabled = False + + if self.is_legacy is False: + self.hover_shapes = ShapeCollection(parent=self.plotcanvas.view.scene, layers=1) + else: + self.hover_shapes = ShapeCollectionLegacy() def on_zoom_fit(self, event): """ diff --git a/FlatCAMObj.py b/FlatCAMObj.py index b6754848..6d8a55c6 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -74,6 +74,9 @@ class FlatCAMObj(QtCore.QObject): # store here the default data for Geometry Data self.default_data = {} + if self.app.is_legacy: + self.axes = None # Matplotlib axes; usefull only in Legacy Mode + self.kind = None # Override with proper name # self.shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene) @@ -331,7 +334,22 @@ class FlatCAMObj(QtCore.QObject): if self.deleted: return False - self.clear() + if self.app.is_legacy: + # 2D mode + # Axes must exist and be attached to canvas. + if self.axes is None or self.axes not in self.app.plotcanvas.figure.axes: + self.axes = self.app.plotcanvas.new_axes(self.options['name']) + + if not self.options["plot"]: + self.axes.cla() + self.app.plotcanvas.auto_adjust_axes() + return False + + # Clear axes or we will plot on top of them. + self.axes.cla() + else: + # 3D mode + self.clear() return True def single_object_plot(self): diff --git a/README.md b/README.md index dad30de5..1ec3dd1c 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ CAD program, and create G-Code for Isolation routing. 20.09.2019 - final fix for the --shellvar having spaces within the assigned value; now they are retained +- legacy graphic engine - made the mouse events work (click, release, doubleclick, dragging) +- legacy graphic engine - made the key events work (simple or with modifiers) +- legacy graphic engine - made the mouse cursor work (enabled/disabled, position report); snapping is not moving the cursor yet 19.09.2019 diff --git a/camlib.py b/camlib.py index 82ee4c07..0e9024af 100644 --- a/camlib.py +++ b/camlib.py @@ -117,7 +117,11 @@ class Geometry(object): self.old_disp_number = 0 self.el_count = 0 - self.temp_shapes = self.app.plotcanvas.new_shape_group() + if self.app.is_legacy is False: + self.temp_shapes = self.app.plotcanvas.new_shape_group() + else: + from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy + self.temp_shapes = ShapeCollectionLegacy() # if geo_steps_per_circle is None: # geo_steps_per_circle = int(Geometry.defaults["geo_steps_per_circle"]) diff --git a/flatcamEditors/FlatCAMExcEditor.py b/flatcamEditors/FlatCAMExcEditor.py index 4b6f07ea..47a0877c 100644 --- a/flatcamEditors/FlatCAMExcEditor.py +++ b/flatcamEditors/FlatCAMExcEditor.py @@ -2012,8 +2012,14 @@ class FlatCAMExcEditor(QtCore.QObject): self.exc_obj = None # VisPy Visuals - self.shapes = self.app.plotcanvas.new_shape_collection(layers=1) - self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) + if self.app.is_legacy is False: + self.shapes = self.app.plotcanvas.new_shape_collection(layers=1) + self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) + else: + from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy + self.shapes = ShapeCollectionLegacy() + self.tool_shape = ShapeCollectionLegacy() + self.app.pool_recreated.connect(self.pool_recreated) # Remove from scene @@ -2791,16 +2797,16 @@ class FlatCAMExcEditor(QtCore.QObject): # first connect to new, then disconnect the old handlers # don't ask why but if there is nothing connected I've seen issues - 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_release', self.on_exc_click_release) + self.canvas.graph_event_connect('mouse_press', self.on_canvas_click) + self.canvas.graph_event_connect('mouse_move', self.on_canvas_move) + self.canvas.graph_event_connect('mouse_release', self.on_exc_click_release) # make sure that the shortcuts key and mouse events will no longer be linked to the methods from FlatCAMApp # but those from FlatCAMGeoEditor - self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_double_click', self.app.on_double_click_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_double_click', self.app.on_double_click_over_plot) self.app.collection.view.clicked.disconnect() self.app.ui.popmenu_copy.triggered.disconnect() @@ -2819,15 +2825,15 @@ class FlatCAMExcEditor(QtCore.QObject): # we restore the key and mouse control to FlatCAMApp method # first connect to new, then disconnect the old handlers # don't ask why but if there is nothing connected I've seen issues - self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_connect('mouse_double_click', self.app.on_double_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_double_click', self.app.on_double_click_over_plot) self.app.collection.view.clicked.connect(self.app.collection.on_mouse_down) - 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_release', self.on_exc_click_release) + self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click) + self.canvas.graph_event_disconnect('mouse_move', self.on_canvas_move) + self.canvas.graph_event_disconnect('mouse_release', self.on_exc_click_release) try: self.app.ui.popmenu_copy.triggered.disconnect(self.exc_copy_drills) @@ -3287,13 +3293,11 @@ class FlatCAMExcEditor(QtCore.QObject): if self.app.grid_status() == True: self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1]) - self.app.app_cursor.enabled = True # Update cursor self.app.app_cursor.set_data(np.asarray([(self.pos[0], self.pos[1])]), symbol='++', edge_color='black', size=20) else: self.pos = (self.pos[0], self.pos[1]) - self.app.app_cursor.enabled = False if event.button is 1: self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " @@ -3605,11 +3609,8 @@ class FlatCAMExcEditor(QtCore.QObject): # ## Snap coordinates if self.app.grid_status() == True: x, y = self.app.geo_editor.snap(x, y) - self.app.app_cursor.enabled = True # Update cursor self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20) - else: - self.app.app_cursor.enabled = False self.snap_x = x self.snap_y = y diff --git a/flatcamEditors/FlatCAMGeoEditor.py b/flatcamEditors/FlatCAMGeoEditor.py index e362b8f7..c2555f58 100644 --- a/flatcamEditors/FlatCAMGeoEditor.py +++ b/flatcamEditors/FlatCAMGeoEditor.py @@ -3025,8 +3025,14 @@ class FlatCAMGeoEditor(QtCore.QObject): # VisPy visuals self.fcgeometry = None - self.shapes = self.app.plotcanvas.new_shape_collection(layers=1) - self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) + if self.app.is_legacy is False: + self.shapes = self.app.plotcanvas.new_shape_collection(layers=1) + self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) + else: + from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy + self.shapes = ShapeCollectionLegacy() + self.tool_shape = ShapeCollectionLegacy() + self.app.pool_recreated.connect(self.pool_recreated) # Remove from scene @@ -3271,7 +3277,6 @@ class FlatCAMGeoEditor(QtCore.QObject): # Disable visuals self.shapes.enabled = False self.tool_shape.enabled = False - self.app.app_cursor.enabled = False self.app.ui.geo_editor_menu.setDisabled(True) self.app.ui.geo_editor_menu.menuAction().setVisible(False) @@ -3309,16 +3314,16 @@ class FlatCAMGeoEditor(QtCore.QObject): # first connect to new, then disconnect the old handlers # don't ask why but if there is nothing connected I've seen issues - 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_release', self.on_geo_click_release) + self.canvas.graph_event_connect('mouse_press', self.on_canvas_click) + self.canvas.graph_event_connect('mouse_move', self.on_canvas_move) + self.canvas.graph_event_connect('mouse_release', self.on_geo_click_release) # make sure that the shortcuts key and mouse events will no longer be linked to the methods from FlatCAMApp # but those from FlatCAMGeoEditor - self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_double_click', self.app.on_double_click_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_double_click', self.app.on_double_click_over_plot) # self.app.collection.view.clicked.disconnect() self.app.ui.popmenu_copy.triggered.disconnect() @@ -3354,15 +3359,15 @@ class FlatCAMGeoEditor(QtCore.QObject): # we restore the key and mouse control to FlatCAMApp method # first connect to new, then disconnect the old handlers # don't ask why but if there is nothing connected I've seen issues - self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_connect('mouse_double_click', self.app.on_double_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_double_click', self.app.on_double_click_over_plot) # self.app.collection.view.clicked.connect(self.app.collection.on_mouse_down) - 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_release', self.on_geo_click_release) + self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click) + self.canvas.graph_event_disconnect('mouse_move', self.on_canvas_move) + self.canvas.graph_event_disconnect('mouse_release', self.on_geo_click_release) try: self.app.ui.popmenu_copy.triggered.disconnect(lambda: self.select_tool('copy')) @@ -3625,18 +3630,20 @@ class FlatCAMGeoEditor(QtCore.QObject): :param event: Event object dispatched by Matplotlib :return: None """ + if self.app.is_legacy is False: + event_pos = event.pos + else: + event_pos = (event.xdata, event.ydata) - self.pos = self.canvas.translate_coords(event.pos) + self.pos = self.canvas.translate_coords(event_pos) if self.app.grid_status() == True: self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1]) - self.app.app_cursor.enabled = True # Update cursor self.app.app_cursor.set_data(np.asarray([(self.pos[0], self.pos[1])]), symbol='++', edge_color='black', size=20) else: self.pos = (self.pos[0], self.pos[1]) - self.app.app_cursor.enabled = False if event.button == 1: self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " @@ -3678,7 +3685,14 @@ class FlatCAMGeoEditor(QtCore.QObject): :param event: Event object dispatched by VisPy SceneCavas :return: None """ - pos = self.canvas.translate_coords(event.pos) + if self.app.is_legacy is False: + event_pos = event.pos + event_is_dragging = event.is_dragging + else: + event_pos = (event.xdata, event.ydata) + event_is_dragging = self.app.plotcanvas.is_dragging + + pos = self.canvas.translate_coords(event_pos) event.xdata, event.ydata = pos[0], pos[1] self.x = event.xdata @@ -3688,7 +3702,7 @@ class FlatCAMGeoEditor(QtCore.QObject): # if the RMB is clicked and mouse is moving over plot then 'panning_action' is True if event.button == 2: - if event.is_dragging: + if event_is_dragging: self.app.ui.popMenu.mouse_is_panning = True # return else: @@ -3706,11 +3720,9 @@ class FlatCAMGeoEditor(QtCore.QObject): # ### Snap coordinates ### if self.app.grid_status() == True: x, y = self.snap(x, y) - self.app.app_cursor.enabled = True - # Update cursor - self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20) - else: - self.app.app_cursor.enabled = False + if self.app.is_legacy is False: + # Update cursor + self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20) self.snap_x = x self.snap_y = y @@ -3728,7 +3740,7 @@ class FlatCAMGeoEditor(QtCore.QObject): self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " "%.4f    " % (dx, dy)) - if event.button == 1 and event.is_dragging and isinstance(self.active_tool, FCEraser): + if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser): pass else: # ### Utility geometry (animated) ### @@ -3740,7 +3752,7 @@ class FlatCAMGeoEditor(QtCore.QObject): # ### Selection area on canvas section ### dx = pos[0] - self.pos[0] - if event.is_dragging and event.button == 1: + if event_is_dragging and event.button == 1: self.app.delete_selection_shape() if dx < 0: self.app.draw_moving_selection_shape((self.pos[0], self.pos[1]), (x, y), @@ -3754,7 +3766,14 @@ class FlatCAMGeoEditor(QtCore.QObject): self.app.selection_type = None def on_geo_click_release(self, event): - pos_canvas = self.canvas.translate_coords(event.pos) + if self.app.is_legacy is False: + event_pos = event.pos + event_is_dragging = event.is_dragging + else: + event_pos = (event.xdata, event.ydata) + event_is_dragging = self.app.plotcanvas.is_dragging + + pos_canvas = self.canvas.translate_coords(event_pos) if self.app.grid_status() == True: pos = self.snap(pos_canvas[0], pos_canvas[1]) diff --git a/flatcamEditors/FlatCAMGrbEditor.py b/flatcamEditors/FlatCAMGrbEditor.py index d9d9210f..f10e2984 100644 --- a/flatcamEditors/FlatCAMGrbEditor.py +++ b/flatcamEditors/FlatCAMGrbEditor.py @@ -2821,9 +2821,15 @@ class FlatCAMGrbEditor(QtCore.QObject): self.gerber_obj_options = dict() # VisPy Visuals - self.shapes = self.canvas.new_shape_collection(layers=1) - self.tool_shape = self.canvas.new_shape_collection(layers=1) - self.ma_annotation = self.canvas.new_text_group() + if self.app.is_legacy is False: + self.shapes = self.canvas.new_shape_collection(layers=1) + self.tool_shape = self.canvas.new_shape_collection(layers=1) + self.ma_annotation = self.canvas.new_text_group() + else: + from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy + self.shapes = ShapeCollectionLegacy() + self.tool_shape = ShapeCollectionLegacy() + self.ma_annotation = ShapeCollectionLegacy() self.app.pool_recreated.connect(self.pool_recreated) @@ -3511,14 +3517,14 @@ class FlatCAMGrbEditor(QtCore.QObject): # first connect to new, then disconnect the old handlers # don't ask why but if there is nothing connected I've seen issues - 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_release', self.on_grb_click_release) + self.canvas.graph_event_connect('mouse_press', self.on_canvas_click) + self.canvas.graph_event_connect('mouse_move', self.on_canvas_move) + self.canvas.graph_event_connect('mouse_release', self.on_grb_click_release) - self.canvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot) - self.canvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot) - self.canvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.canvas.vis_disconnect('mouse_double_click', self.app.on_double_click_over_plot) + self.canvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) + self.canvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot) + self.canvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.canvas.graph_event_disconnect('mouse_double_click', self.app.on_double_click_over_plot) self.app.collection.view.clicked.disconnect() self.app.ui.popmenu_copy.triggered.disconnect() @@ -3550,15 +3556,15 @@ class FlatCAMGrbEditor(QtCore.QObject): # we restore the key and mouse control to FlatCAMApp method # first connect to new, then disconnect the old handlers # don't ask why but if there is nothing connected I've seen issues - self.canvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.canvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) - self.canvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.canvas.vis_connect('mouse_double_click', self.app.on_double_click_over_plot) + self.canvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.canvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) + self.canvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.canvas.graph_event_connect('mouse_double_click', self.app.on_double_click_over_plot) self.app.collection.view.clicked.connect(self.app.collection.on_mouse_down) - 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_release', self.on_grb_click_release) + self.canvas.graph_event_disconnect('mouse_press', self.on_canvas_click) + self.canvas.graph_event_disconnect('mouse_move', self.on_canvas_move) + self.canvas.graph_event_disconnect('mouse_release', self.on_grb_click_release) try: self.app.ui.popmenu_copy.triggered.disconnect(self.on_copy_button) @@ -4136,13 +4142,11 @@ class FlatCAMGrbEditor(QtCore.QObject): if self.app.grid_status() == True: self.pos = self.app.geo_editor.snap(self.pos[0], self.pos[1]) - self.app.app_cursor.enabled = True # Update cursor self.app.app_cursor.set_data(np.asarray([(self.pos[0], self.pos[1])]), symbol='++', edge_color='black', size=20) else: self.pos = (self.pos[0], self.pos[1]) - self.app.app_cursor.enabled = False if event.button is 1: self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " @@ -4354,11 +4358,8 @@ class FlatCAMGrbEditor(QtCore.QObject): # # ## Snap coordinates if self.app.grid_status() == True: x, y = self.app.geo_editor.snap(x, y) - self.app.app_cursor.enabled = True # Update cursor self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20) - else: - self.app.app_cursor.enabled = False self.snap_x = x self.snap_y = y diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 48245c83..9cd1bff4 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -12,6 +12,7 @@ # ########################################################## from flatcamGUI.PreferencesUI import * +from matplotlib.backend_bases import KeyEvent as mpl_key_event import gettext import FlatCAMTranslation as fcTranslate @@ -2271,6 +2272,32 @@ class FlatCAMGUI(QtWidgets.QMainWindow): # events from the GUI are of type QKeyEvent elif type(event) == QtGui.QKeyEvent: key = event.key() + elif isinstance(event, mpl_key_event): + key = event.key + # if modifiers == QtCore.Qt.NoModifier: + try: + key = ord(key.upper()) + except TypeError: + key = key.upper() + if 'ctrl' in key.lower(): + modifiers = QtCore.Qt.ControlModifier + try: + key = ord(key.rpartition('+')[2].upper()) + except TypeError: + pass + elif 'alt' in key.lower(): + modifiers = QtCore.Qt.AltModifier + try: + key = ord(key.rpartition('+')[2].upper()) + except TypeError: + pass + elif 'shift' in key.lower(): + modifiers = QtCore.Qt.ShiftModifier + try: + key = ord(key.rpartition('+')[2].upper()) + except TypeError: + pass + # events from Vispy are of type KeyEvent else: key = event.key @@ -2494,7 +2521,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow): # try to disconnect the slot from Set Origin try: - self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_set_zero_click) + self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_set_zero_click) except TypeError: pass self.app.inform.emit("") diff --git a/flatcamGUI/PlotCanvas.py b/flatcamGUI/PlotCanvas.py index d1d1e61b..869ed1a5 100644 --- a/flatcamGUI/PlotCanvas.py +++ b/flatcamGUI/PlotCanvas.py @@ -152,10 +152,10 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas): except Exception as e: pass - def vis_connect(self, event_name, callback): + def graph_event_connect(self, event_name, callback): return getattr(self.events, event_name).connect(callback) - def vis_disconnect(self, event_name, callback=None): + def graph_event_disconnect(self, event_name, callback=None): if callback is None: getattr(self.events, event_name).disconnect() else: diff --git a/flatcamGUI/PlotCanvasLegacy.py b/flatcamGUI/PlotCanvasLegacy.py new file mode 100644 index 00000000..6e41c460 --- /dev/null +++ b/flatcamGUI/PlotCanvasLegacy.py @@ -0,0 +1,637 @@ +############################################################ +# FlatCAM: 2D Post-processing for Manufacturing # +# http://caram.cl/software/flatcam # +# Author: Juan Pablo Caram (c) # +# Date: 2/5/2014 # +# MIT Licence # +############################################################ + +from PyQt5 import QtGui, QtCore, QtWidgets + +# Prevent conflict with Qt5 and above. +from matplotlib import use as mpl_use + +from matplotlib.figure import Figure +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.backends.backend_agg import FigureCanvasAgg +from matplotlib.widgets import Cursor + +import FlatCAMApp +import logging + +mpl_use("Qt5Agg") +log = logging.getLogger('base') + + +class CanvasCache(QtCore.QObject): + """ + + Case story #1: + + 1) No objects in the project. + 2) Object is created (new_object() emits object_created(obj)). + on_object_created() adds (i) object to collection and emits + (ii) new_object_available() then calls (iii) object.plot() + 3) object.plot() creates axes if necessary on + app.collection.figure. Then plots on it. + 4) Plots on a cache-size canvas (in background). + 5) Plot completes. Bitmap is generated. + 6) Visible canvas is painted. + + """ + + # Signals: + # A bitmap is ready to be displayed. + new_screen = QtCore.pyqtSignal() + + def __init__(self, plotcanvas, app, dpi=50): + + super(CanvasCache, self).__init__() + + self.app = app + + self.plotcanvas = plotcanvas + self.dpi = dpi + + self.figure = Figure(dpi=dpi) + + self.axes = self.figure.add_axes([0.0, 0.0, 1.0, 1.0], alpha=1.0) + self.axes.set_frame_on(False) + self.axes.set_xticks([]) + self.axes.set_yticks([]) + + self.canvas = FigureCanvasAgg(self.figure) + + self.cache = None + + def run(self): + + log.debug("CanvasCache Thread Started!") + self.plotcanvas.update_screen_request.connect(self.on_update_req) + + def on_update_req(self, extents): + """ + Event handler for an updated display request. + + :param extents: [xmin, xmax, ymin, ymax, zoom(optional)] + """ + + # log.debug("Canvas update requested: %s" % str(extents)) + + # Note: This information below might be out of date. Establish + # a protocol regarding when to change the canvas in the main + # thread and when to check these values here in the background, + # or pass this data in the signal (safer). + # log.debug("Size: %s [px]" % str(self.plotcanvas.get_axes_pixelsize())) + # log.debug("Density: %s [units/px]" % str(self.plotcanvas.get_density())) + + # Move the requested screen portion to the main thread + # and inform about the update: + + self.new_screen.emit() + + # Continue to update the cache. + + # def on_new_object_available(self): + # + # log.debug("A new object is available. Should plot it!") + + +class PlotCanvasLegacy(QtCore.QObject): + """ + Class handling the plotting area in the application. + """ + + # Signals: + # Request for new bitmap to display. The parameter + # is a list with [xmin, xmax, ymin, ymax, zoom(optional)] + update_screen_request = QtCore.pyqtSignal(list) + double_click = QtCore.pyqtSignal(object) + + def __init__(self, container, app): + """ + The constructor configures the Matplotlib figure that + will contain all plots, creates the base axes and connects + events to the plotting area. + + :param container: The parent container in which to draw plots. + :rtype: PlotCanvas + """ + + super(PlotCanvasLegacy, self).__init__() + + self.app = app + + # Options + self.x_margin = 15 # pixels + self.y_margin = 25 # Pixels + + # Parent container + self.container = container + + # Plots go onto a single matplotlib.figure + self.figure = Figure(dpi=50) # TODO: dpi needed? + self.figure.patch.set_visible(False) + + # These axes show the ticks and grid. No plotting done here. + # New axes must have a label, otherwise mpl returns an existing one. + self.axes = self.figure.add_axes([0.05, 0.05, 0.9, 0.9], label="base", alpha=0.0) + self.axes.set_aspect(1) + self.axes.grid(True) + self.axes.axhline(color='Black') + self.axes.axvline(color='Black') + + # The canvas is the top level container (FigureCanvasQTAgg) + self.canvas = FigureCanvas(self.figure) + self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus) + self.canvas.setFocus() + self.native = self.canvas + + # self.canvas.set_hexpand(1) + # self.canvas.set_vexpand(1) + # self.canvas.set_can_focus(True) # For key press + + # Attach to parent + # self.container.attach(self.canvas, 0, 0, 600, 400) # TODO: Height and width are num. columns?? + self.container.addWidget(self.canvas) # Qt + + # Copy a bitmap of the canvas for quick animation. + # Update every time the canvas is re-drawn. + self.background = self.canvas.copy_from_bbox(self.axes.bbox) + + # ## Bitmap Cache + self.cache = CanvasCache(self, self.app) + self.cache_thread = QtCore.QThread() + self.cache.moveToThread(self.cache_thread) + # super(PlotCanvas, self).connect(self.cache_thread, QtCore.SIGNAL("started()"), self.cache.run) + self.cache_thread.started.connect(self.cache.run) + + self.cache_thread.start() + self.cache.new_screen.connect(self.on_new_screen) + + # Events + self.graph_event_connect('button_press_event', self.on_mouse_press) + self.graph_event_connect('button_release_event', self.on_mouse_release) + self.graph_event_connect('motion_notify_event', self.on_mouse_move) + # self.canvas.connect('configure-event', self.auto_adjust_axes) + self.graph_event_connect('resize_event', self.auto_adjust_axes) + # self.canvas.add_events(Gdk.EventMask.SMOOTH_SCROLL_MASK) + # self.canvas.connect("scroll-event", self.on_scroll) + self.graph_event_connect('scroll_event', self.on_scroll) + # self.graph_event_connect('key_press_event', self.on_key_down) + # self.graph_event_connect('key_release_event', self.on_key_up) + self.graph_event_connect('draw_event', self.on_draw) + + self.mouse = [0, 0] + self.key = None + + self.pan_axes = [] + self.panning = False + + # signal is the mouse is dragging + self.is_dragging = False + + # signal if there is a doubleclick + self.is_dblclk = False + + def graph_event_connect(self, event_name, callback): + """ + Attach an event handler to the canvas through the Matplotlib interface. + + :param event_name: Name of the event + :type event_name: str + :param callback: Function to call + :type callback: func + :return: Connection id + :rtype: int + """ + if event_name == 'mouse_move': + event_name = 'motion_notify_event' + if event_name == 'mouse_press': + event_name = 'button_press_event' + if event_name == 'mouse_release': + event_name = 'button_release_event' + if event_name == 'mouse_double_click': + return self.double_click.connect(callback) + + if event_name == 'key_press': + event_name = 'key_press_event' + + return self.canvas.mpl_connect(event_name, callback) + + def graph_event_disconnect(self, cid): + """ + Disconnect callback with the give id. + :param cid: Callback id. + :return: None + """ + if cid == 'mouse_move': + cid = 'motion_notify_event' + if cid == 'mouse_press': + cid = 'button_press_event' + if cid == 'mouse_release': + cid = 'button_release_event' + if cid == 'mouse_double_click': + self.double_click.disconnect(cid) + return + + if cid == 'key_press': + cid = 'key_press_event' + + self.canvas.mpl_disconnect(cid) + + def on_new_screen(self): + pass + # log.debug("Cache updated the screen!") + + def new_cursor(self): + c = MplCursor(axes=self.axes, color='black', linewidth=1) + return c + + def on_key_down(self, event): + """ + + :param event: + :return: + """ + FlatCAMApp.App.log.debug('on_key_down(): ' + str(event.key)) + self.key = event.key + + def on_key_up(self, event): + """ + + :param event: + :return: + """ + self.key = None + + def connect(self, event_name, callback): + """ + Attach an event handler to the canvas through the native Qt interface. + + :param event_name: Name of the event + :type event_name: str + :param callback: Function to call + :type callback: function + :return: Nothing + """ + self.canvas.connect(event_name, callback) + + def clear(self): + """ + Clears axes and figure. + + :return: None + """ + + # Clear + self.axes.cla() + try: + self.figure.clf() + except KeyError: + FlatCAMApp.App.log.warning("KeyError in MPL figure.clf()") + + # Re-build + self.figure.add_axes(self.axes) + self.axes.set_aspect(1) + self.axes.grid(True) + + # Re-draw + self.canvas.draw_idle() + + def adjust_axes(self, xmin, ymin, xmax, ymax): + """ + Adjusts all axes while maintaining the use of the whole canvas + and an aspect ratio to 1:1 between x and y axes. The parameters are an original + request that will be modified to fit these restrictions. + + :param xmin: Requested minimum value for the X axis. + :type xmin: float + :param ymin: Requested minimum value for the Y axis. + :type ymin: float + :param xmax: Requested maximum value for the X axis. + :type xmax: float + :param ymax: Requested maximum value for the Y axis. + :type ymax: float + :return: None + """ + + # FlatCAMApp.App.log.debug("PC.adjust_axes()") + + width = xmax - xmin + height = ymax - ymin + try: + r = width / height + except ZeroDivisionError: + FlatCAMApp.App.log.error("Height is %f" % height) + return + canvas_w, canvas_h = self.canvas.get_width_height() + canvas_r = float(canvas_w) / canvas_h + x_ratio = float(self.x_margin) / canvas_w + y_ratio = float(self.y_margin) / canvas_h + + if r > canvas_r: + ycenter = (ymin + ymax) / 2.0 + newheight = height * r / canvas_r + ymin = ycenter - newheight / 2.0 + ymax = ycenter + newheight / 2.0 + else: + xcenter = (xmax + xmin) / 2.0 + newwidth = width * canvas_r / r + xmin = xcenter - newwidth / 2.0 + xmax = xcenter + newwidth / 2.0 + + # Adjust axes + for ax in self.figure.get_axes(): + if ax._label != 'base': + ax.set_frame_on(False) # No frame + ax.set_xticks([]) # No tick + ax.set_yticks([]) # No ticks + ax.patch.set_visible(False) # No background + ax.set_aspect(1) + ax.set_xlim((xmin, xmax)) + ax.set_ylim((ymin, ymax)) + ax.set_position([x_ratio, y_ratio, 1 - 2 * x_ratio, 1 - 2 * y_ratio]) + + # Sync re-draw to proper paint on form resize + self.canvas.draw() + + # #### Temporary place-holder for cached update ##### + self.update_screen_request.emit([0, 0, 0, 0, 0]) + + def auto_adjust_axes(self, *args): + """ + Calls ``adjust_axes()`` using the extents of the base axes. + + :rtype : None + :return: None + """ + + xmin, xmax = self.axes.get_xlim() + ymin, ymax = self.axes.get_ylim() + self.adjust_axes(xmin, ymin, xmax, ymax) + + def zoom(self, factor, center=None): + """ + Zooms the plot by factor around a given + center point. Takes care of re-drawing. + + :param factor: Number by which to scale the plot. + :type factor: float + :param center: Coordinates [x, y] of the point around which to scale the plot. + :type center: list + :return: None + """ + + xmin, xmax = self.axes.get_xlim() + ymin, ymax = self.axes.get_ylim() + width = xmax - xmin + height = ymax - ymin + + if center is None or center == [None, None]: + center = [(xmin + xmax) / 2.0, (ymin + ymax) / 2.0] + + # For keeping the point at the pointer location + relx = (xmax - center[0]) / width + rely = (ymax - center[1]) / height + + new_width = width / factor + new_height = height / factor + + xmin = center[0] - new_width * (1 - relx) + xmax = center[0] + new_width * relx + ymin = center[1] - new_height * (1 - rely) + ymax = center[1] + new_height * rely + + # Adjust axes + for ax in self.figure.get_axes(): + ax.set_xlim((xmin, xmax)) + ax.set_ylim((ymin, ymax)) + + # Async re-draw + self.canvas.draw_idle() + + # #### Temporary place-holder for cached update ##### + self.update_screen_request.emit([0, 0, 0, 0, 0]) + + def pan(self, x, y): + xmin, xmax = self.axes.get_xlim() + ymin, ymax = self.axes.get_ylim() + width = xmax - xmin + height = ymax - ymin + + # Adjust axes + for ax in self.figure.get_axes(): + ax.set_xlim((xmin + x * width, xmax + x * width)) + ax.set_ylim((ymin + y * height, ymax + y * height)) + + # Re-draw + self.canvas.draw_idle() + + # #### Temporary place-holder for cached update ##### + self.update_screen_request.emit([0, 0, 0, 0, 0]) + + def new_axes(self, name): + """ + Creates and returns an Axes object attached to this object's Figure. + + :param name: Unique label for the axes. + :return: Axes attached to the figure. + :rtype: Axes + """ + + return self.figure.add_axes([0.05, 0.05, 0.9, 0.9], label=name) + + def on_scroll(self, event): + """ + Scroll event handler. + + :param event: Event object containing the event information. + :return: None + """ + + # So it can receive key presses + # self.canvas.grab_focus() + self.canvas.setFocus() + + # Event info + # z, direction = event.get_scroll_direction() + + if self.key is None: + + if event.button == 'up': + self.zoom(1.5, self.mouse) + else: + self.zoom(1 / 1.5, self.mouse) + return + + if self.key == 'shift': + + if event.button == 'up': + self.pan(0.3, 0) + else: + self.pan(-0.3, 0) + return + + if self.key == 'control': + + if event.button == 'up': + self.pan(0, 0.3) + else: + self.pan(0, -0.3) + return + + def on_mouse_press(self, event): + + self.is_dragging = True + + # Check for middle mouse button press + if self.app.defaults["global_pan_button"] == '2': + pan_button = 3 # right button for Matplotlib + else: + pan_button = 2 # middle button for Matplotlib + + if event.button == pan_button: + # Prepare axes for pan (using 'matplotlib' pan function) + self.pan_axes = [] + for a in self.figure.get_axes(): + if (event.x is not None and event.y is not None and a.in_axes(event) and + a.get_navigate() and a.can_pan()): + a.start_pan(event.x, event.y, 1) + self.pan_axes.append(a) + + # Set pan view flag + if len(self.pan_axes) > 0: + self.panning = True + + if event.dblclick: + self.double_click.emit(event) + + def on_mouse_release(self, event): + + self.is_dragging = False + + # Check for middle mouse button release to complete pan procedure + # Check for middle mouse button press + if self.app.defaults["global_pan_button"] == '2': + pan_button = 3 # right button for Matplotlib + else: + pan_button = 2 # middle button for Matplotlib + + if event.button == pan_button: + for a in self.pan_axes: + a.end_pan() + + # Clear pan flag + self.panning = False + + def on_mouse_move(self, event): + """ + Mouse movement event hadler. Stores the coordinates. Updates view on pan. + + :param event: Contains information about the event. + :return: None + """ + self.mouse = [event.xdata, event.ydata] + + # Update pan view on mouse move + if self.panning is True: + for a in self.pan_axes: + a.drag_pan(1, event.key, event.x, event.y) + + # Async re-draw (redraws only on thread idle state, uses timer on backend) + self.canvas.draw_idle() + + # #### Temporary place-holder for cached update ##### + self.update_screen_request.emit([0, 0, 0, 0, 0]) + + def translate_coords(self, position): + """ + This does not do much. It's just for code compatibility + + :param position: Mouse event position + :return: Tuple with mouse position + """ + return (position[0], position[1]) + + def on_draw(self, renderer): + + # Store background on canvas redraw + self.background = self.canvas.copy_from_bbox(self.axes.bbox) + + def get_axes_pixelsize(self): + """ + Axes size in pixels. + + :return: Pixel width and height + :rtype: tuple + """ + bbox = self.axes.get_window_extent().transformed(self.figure.dpi_scale_trans.inverted()) + width, height = bbox.width, bbox.height + width *= self.figure.dpi + height *= self.figure.dpi + return width, height + + def get_density(self): + """ + Returns unit length per pixel on horizontal + and vertical axes. + + :return: X and Y density + :rtype: tuple + """ + xpx, ypx = self.get_axes_pixelsize() + + xmin, xmax = self.axes.get_xlim() + ymin, ymax = self.axes.get_ylim() + width = xmax - xmin + height = ymax - ymin + + return width / xpx, height / ypx + + +class MplCursor(): + + def __init__(self, axes, color='red', linewidth=1): + self._enabled = True + + self.axes = axes + self.color = color + self.linewidth = linewidth + self.cursor = Cursor(self.axes, useblit=True, color=self.color, linewidth=self.linewidth) + + @property + def enabled(self): + return True if self._enabled else False + + @enabled.setter + def enabled(self, value): + self._enabled = value + self.cursor.visible = self._enabled + self.cursor.canvas.draw() + + def set_data(self, pos): + self.cursor.linev.set_xdata((pos[0], pos[0])) + self.cursor.lineh.set_ydata(([pos[1]], pos[1])) + + +class ShapeCollectionLegacy(): + + def __init__(self): + self._shapes = [] + + def add(self, shape): + try: + for sh in shape: + self._shapes.append(sh) + except TypeError: + self._shapes.append(shape) + + def clear(self, update=None): + self._shapes[:] = [] + + if update is True: + self.redraw() + + def redraw(self): + pass diff --git a/flatcamGUI/PreferencesUI.py b/flatcamGUI/PreferencesUI.py index 167530da..ed2d88eb 100644 --- a/flatcamGUI/PreferencesUI.py +++ b/flatcamGUI/PreferencesUI.py @@ -846,6 +846,17 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): self.units_radio = RadioSet([{'label': _('IN'), 'value': 'IN'}, {'label': _('MM'), 'value': 'MM'}]) + # Graphic Engine for FlatCAM + self.ge_label = QtWidgets.QLabel('%s:' % _('Graphic Engine')) + self.ge_label.setToolTip(_("Choose what graphic engine to use in FlatCAM.\n" + "Legacy(2D) -> reduced functionality, slow performance but enhanced compatibility.\n" + "OpenGL(3D) -> full functionality, high performance\n" + "Some graphic cards are too old and do not work in OpenGL(3D) mode, like:\n" + "Intel HD3000 or older. In this case the plot area will be black therefore\n" + "use the Legacy(2D) mode.")) + self.ge_radio = RadioSet([{'label': _('Legacy(2D)'), 'value': '2D'}, + {'label': _('OpenGL(3D)'), 'value': '3D'}]) + # Application Level for FlatCAM self.app_level_label = QtWidgets.QLabel('%s:' % _('APP. LEVEL')) self.app_level_label.setToolTip(_("Choose the default level of usage for FlatCAM.\n" @@ -963,6 +974,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): # Add (label - input field) pair to the QFormLayout self.form_box.addRow(self.unitslabel, self.units_radio) + self.form_box.addRow(self.ge_label, self.ge_radio) self.form_box.addRow(self.app_level_label, self.app_level_radio) self.form_box.addRow(self.portability_label, self.portability_cb) self.form_box.addRow(QtWidgets.QLabel('')) diff --git a/flatcamTools/ToolCutOut.py b/flatcamTools/ToolCutOut.py index 5bb3ab14..d6e7511c 100644 --- a/flatcamTools/ToolCutOut.py +++ b/flatcamTools/ToolCutOut.py @@ -780,13 +780,13 @@ class CutOut(FlatCAMTool): self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve Geometry object"), name)) return "Could not retrieve object: %s" % name - self.app.plotcanvas.vis_disconnect('key_press', self.app.ui.keyPressEvent) - self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_connect('key_press', self.on_key_press) - self.app.plotcanvas.vis_connect('mouse_move', self.on_mouse_move) - self.app.plotcanvas.vis_connect('mouse_release', self.on_mouse_click_release) + self.app.plotcanvas.graph_event_disconnect('key_press', self.app.ui.keyPressEvent) + self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_connect('key_press', self.on_key_press) + self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move) + self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_click_release) def on_manual_cutout(self, click_pos): name = self.man_object_combo.currentText() @@ -929,13 +929,13 @@ class CutOut(FlatCAMTool): pos = self.app.plotcanvas.translate_coords(event.pos) self.on_manual_cutout(click_pos=pos) - # self.app.plotcanvas.vis_disconnect('key_press', self.on_key_press) - # self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move) - # self.app.plotcanvas.vis_disconnect('mouse_release', self.on_mouse_click_release) - # self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent) - # self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - # self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) - # self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) + # self.app.plotcanvas.graph_event_disconnect('key_press', self.on_key_press) + # self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move) + # self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release) + # self.app.plotcanvas.graph_event_connect('key_press', self.app.ui.keyPressEvent) + # self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + # self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + # self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) # self.app.geo_editor.tool_shape.clear(update=True) # self.app.geo_editor.tool_shape.enabled = False @@ -943,13 +943,13 @@ class CutOut(FlatCAMTool): # if RMB then we exit elif event.button == 2 and self.mouse_is_dragging is False: - self.app.plotcanvas.vis_disconnect('key_press', self.on_key_press) - self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move) - self.app.plotcanvas.vis_disconnect('mouse_release', self.on_mouse_click_release) - self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent) - self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_disconnect('key_press', self.on_key_press) + self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move) + self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release) + self.app.plotcanvas.graph_event_connect('key_press', self.app.ui.keyPressEvent) + self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) # Remove any previous utility shape self.app.geo_editor.tool_shape.clear(update=True) @@ -1064,13 +1064,13 @@ class CutOut(FlatCAMTool): # Escape = Deselect All if key == QtCore.Qt.Key_Escape or key == 'Escape': - self.app.plotcanvas.vis_disconnect('key_press', self.on_key_press) - self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move) - self.app.plotcanvas.vis_disconnect('mouse_release', self.on_mouse_click_release) - self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent) - self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_disconnect('key_press', self.on_key_press) + self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move) + self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release) + self.app.plotcanvas.graph_event_connect('key_press', self.app.ui.keyPressEvent) + self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) # Remove any previous utility shape self.app.geo_editor.tool_shape.clear(update=True) diff --git a/flatcamTools/ToolMeasurement.py b/flatcamTools/ToolMeasurement.py index 320d34db..bedfe7ea 100644 --- a/flatcamTools/ToolMeasurement.py +++ b/flatcamTools/ToolMeasurement.py @@ -113,7 +113,11 @@ class Measurement(FlatCAMTool): self.original_call_source = 'app' # VisPy visuals - self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1) + if self.app.is_legacy is False: + self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1) + else: + from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy + self.sel_shapes = ShapeCollectionLegacy() self.measure_btn.clicked.connect(self.activate_measure_tool) @@ -178,26 +182,26 @@ class Measurement(FlatCAMTool): # we can connect the app mouse events to the measurement tool # NEVER DISCONNECT THOSE before connecting some other handlers; it breaks something in VisPy - self.canvas.vis_connect('mouse_move', self.on_mouse_move_meas) - self.canvas.vis_connect('mouse_release', self.on_mouse_click_release) + self.canvas.graph_event_connect('mouse_move', self.on_mouse_move_meas) + self.canvas.graph_event_connect('mouse_release', self.on_mouse_click_release) # we disconnect the mouse/key handlers from wherever the measurement tool was called if self.app.call_source == 'app': - self.canvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot) - self.canvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot) - self.canvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.canvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot) + self.canvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) + self.canvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) elif self.app.call_source == 'geo_editor': - self.canvas.vis_disconnect('mouse_move', self.app.geo_editor.on_canvas_move) - self.canvas.vis_disconnect('mouse_press', self.app.geo_editor.on_canvas_click) - self.canvas.vis_disconnect('mouse_release', self.app.geo_editor.on_geo_click_release) + self.canvas.graph_event_disconnect('mouse_move', self.app.geo_editor.on_canvas_move) + self.canvas.graph_event_disconnect('mouse_press', self.app.geo_editor.on_canvas_click) + self.canvas.graph_event_disconnect('mouse_release', self.app.geo_editor.on_geo_click_release) elif self.app.call_source == 'exc_editor': - self.canvas.vis_disconnect('mouse_move', self.app.exc_editor.on_canvas_move) - self.canvas.vis_disconnect('mouse_press', self.app.exc_editor.on_canvas_click) - self.canvas.vis_disconnect('mouse_release', self.app.exc_editor.on_exc_click_release) + self.canvas.graph_event_disconnect('mouse_move', self.app.exc_editor.on_canvas_move) + self.canvas.graph_event_disconnect('mouse_press', self.app.exc_editor.on_canvas_click) + self.canvas.graph_event_disconnect('mouse_release', self.app.exc_editor.on_exc_click_release) elif self.app.call_source == 'grb_editor': - self.canvas.vis_disconnect('mouse_move', self.app.grb_editor.on_canvas_move) - self.canvas.vis_disconnect('mouse_press', self.app.grb_editor.on_canvas_click) - self.canvas.vis_disconnect('mouse_release', self.app.grb_editor.on_grb_click_release) + self.canvas.graph_event_disconnect('mouse_move', self.app.grb_editor.on_canvas_move) + self.canvas.graph_event_disconnect('mouse_press', self.app.grb_editor.on_canvas_click) + self.canvas.graph_event_disconnect('mouse_release', self.app.grb_editor.on_grb_click_release) self.app.call_source = 'measurement' @@ -210,25 +214,25 @@ class Measurement(FlatCAMTool): self.app.call_source = copy(self.original_call_source) if self.original_call_source == 'app': - self.canvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) - self.canvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.canvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.canvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) + self.canvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.canvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) elif self.original_call_source == 'geo_editor': - 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_release', self.app.geo_editor.on_geo_click_release) + self.canvas.graph_event_connect('mouse_move', self.app.geo_editor.on_canvas_move) + self.canvas.graph_event_connect('mouse_press', self.app.geo_editor.on_canvas_click) + self.canvas.graph_event_connect('mouse_release', self.app.geo_editor.on_geo_click_release) elif self.original_call_source == 'exc_editor': - 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_release', self.app.exc_editor.on_exc_click_release) + self.canvas.graph_event_connect('mouse_move', self.app.exc_editor.on_canvas_move) + self.canvas.graph_event_connect('mouse_press', self.app.exc_editor.on_canvas_click) + self.canvas.graph_event_connect('mouse_release', self.app.exc_editor.on_exc_click_release) elif self.original_call_source == 'grb_editor': - 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_release', self.app.grb_editor.on_grb_click_release) + self.canvas.graph_event_connect('mouse_move', self.app.grb_editor.on_canvas_move) + self.canvas.graph_event_connect('mouse_press', self.app.grb_editor.on_canvas_click) + self.canvas.graph_event_connect('mouse_release', self.app.grb_editor.on_grb_click_release) # 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_release', self.on_mouse_click_release) + self.canvas.graph_event_disconnect('mouse_move', self.on_mouse_move_meas) + self.canvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release) # self.app.ui.notebook.setTabText(2, _("Tools")) # self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab) @@ -289,13 +293,11 @@ class Measurement(FlatCAMTool): pos_canvas = self.app.plotcanvas.translate_coords(event.pos) if self.app.grid_status() == True: pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1]) - self.app.app_cursor.enabled = True # Update cursor self.app.app_cursor.set_data(np.asarray([(pos[0], pos[1])]), symbol='++', edge_color='black', size=20) else: pos = (pos_canvas[0], pos_canvas[1]) - self.app.app_cursor.enabled = False if self.rel_point1 is not None: dx = pos[0] - self.rel_point1[0] diff --git a/flatcamTools/ToolMove.py b/flatcamTools/ToolMove.py index 892d6321..892069cd 100644 --- a/flatcamTools/ToolMove.py +++ b/flatcamTools/ToolMove.py @@ -44,7 +44,11 @@ class ToolMove(FlatCAMTool): self.old_coords = [] # VisPy visuals - self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1) + if self.app.is_legacy is False: + self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.view.scene, layers=1) + else: + from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy + self.sel_shapes = ShapeCollectionLegacy() self.replot_signal[list].connect(self.replot) @@ -62,10 +66,10 @@ class ToolMove(FlatCAMTool): if self.isVisible(): self.setVisible(False) - self.app.plotcanvas.vis_disconnect('mouse_move', self.on_move) - self.app.plotcanvas.vis_disconnect('mouse_press', self.on_left_click) - self.app.plotcanvas.vis_disconnect('key_release', self.on_key_press) - self.app.plotcanvas.vis_connect('key_press', self.app.ui.keyPressEvent) + self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_move) + self.app.plotcanvas.graph_event_disconnect('mouse_press', self.on_left_click) + self.app.plotcanvas.graph_event_disconnect('key_release', self.on_key_press) + self.app.plotcanvas.graph_event_connect('key_press', self.app.ui.keyPressEvent) self.clicked_move = 0 @@ -228,9 +232,9 @@ class ToolMove(FlatCAMTool): self.toggle() else: # if we have an object selected then we can safely activate the mouse events - self.app.plotcanvas.vis_connect('mouse_move', self.on_move) - self.app.plotcanvas.vis_connect('mouse_press', self.on_left_click) - self.app.plotcanvas.vis_connect('key_release', self.on_key_press) + self.app.plotcanvas.graph_event_connect('mouse_move', self.on_move) + self.app.plotcanvas.graph_event_connect('mouse_press', self.on_left_click) + self.app.plotcanvas.graph_event_connect('key_release', self.on_key_press) # first get a bounding box to fit all for obj in obj_list: xmin, ymin, xmax, ymax = obj.bounds() diff --git a/flatcamTools/ToolNonCopperClear.py b/flatcamTools/ToolNonCopperClear.py index ba00f92e..014d875b 100644 --- a/flatcamTools/ToolNonCopperClear.py +++ b/flatcamTools/ToolNonCopperClear.py @@ -1197,21 +1197,21 @@ class NonCopperClear(FlatCAMTool, Gerber): # contour=contour, # rest=rest) # - # self.app.plotcanvas.vis_disconnect('mouse_release', on_mouse_release) - # self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move) + # self.app.plotcanvas.graph_event_disconnect('mouse_release', on_mouse_release) + # self.app.plotcanvas.graph_event_disconnect('mouse_move', on_mouse_move) # - # self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - # self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) - # self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + # self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + # self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) + # self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) elif event.button == 2 and self.mouse_is_dragging == False: self.first_click = False - self.app.plotcanvas.vis_disconnect('mouse_release', on_mouse_release) - self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move) + self.app.plotcanvas.graph_event_disconnect('mouse_release', on_mouse_release) + self.app.plotcanvas.graph_event_disconnect('mouse_move', on_mouse_move) - self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) if len(self.sel_rect) == 0: return @@ -1231,7 +1231,6 @@ class NonCopperClear(FlatCAMTool, Gerber): # called on mouse move def on_mouse_move(event): curr_pos = self.app.plotcanvas.translate_coords(event.pos) - self.app.app_cursor.enabled = False # detect mouse dragging motion if event.is_dragging is True: @@ -1241,7 +1240,6 @@ class NonCopperClear(FlatCAMTool, Gerber): # update the cursor position if self.app.grid_status() == True: - self.app.app_cursor.enabled = True # Update cursor curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1]) self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]), @@ -1254,12 +1252,12 @@ class NonCopperClear(FlatCAMTool, Gerber): coords=(curr_pos[0], curr_pos[1]), face_alpha=0.0) - self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', on_mouse_release) - self.app.plotcanvas.vis_connect('mouse_move', on_mouse_move) + self.app.plotcanvas.graph_event_connect('mouse_release', on_mouse_release) + self.app.plotcanvas.graph_event_connect('mouse_move', on_mouse_move) elif select_method == 'box': self.bound_obj_name = self.box_combo.currentText() # Get source object. diff --git a/flatcamTools/ToolPaint.py b/flatcamTools/ToolPaint.py index e60c92e8..b497b7fa 100644 --- a/flatcamTools/ToolPaint.py +++ b/flatcamTools/ToolPaint.py @@ -1005,7 +1005,7 @@ class ToolPaint(FlatCAMTool, Gerber): # do paint single only for left mouse clicks if event.button == 1: self.app.inform.emit(_("Painting polygon...")) - self.app.plotcanvas.vis_disconnect('mouse_press', doit) + self.app.plotcanvas.graph_event_disconnect('mouse_press', doit) pos = self.app.plotcanvas.translate_coords(event.pos) if self.app.grid_status() == True: @@ -1017,12 +1017,12 @@ class ToolPaint(FlatCAMTool, Gerber): overlap=overlap, connect=connect, contour=contour) - self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_connect('mouse_press', doit) + self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_press', doit) elif select_method == "area": self.app.inform.emit('[WARNING_NOTCL] %s' % @@ -1082,21 +1082,21 @@ class ToolPaint(FlatCAMTool, Gerber): # connect=connect, # contour=contour) # - # self.app.plotcanvas.vis_disconnect('mouse_release', on_mouse_release) - # self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move) + # self.app.plotcanvas.graph_event_disconnect('mouse_release', on_mouse_release) + # self.app.plotcanvas.graph_event_disconnect('mouse_move', on_mouse_move) # - # self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - # self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) - # self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + # self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + # self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) + # self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) elif event.button == 2 and self.mouse_is_dragging is False: self.first_click = False - self.app.plotcanvas.vis_disconnect('mouse_release', on_mouse_release) - self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move) + self.app.plotcanvas.graph_event_disconnect('mouse_release', on_mouse_release) + self.app.plotcanvas.graph_event_disconnect('mouse_move', on_mouse_move) - self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot) if len(self.sel_rect) == 0: return @@ -1113,7 +1113,6 @@ class ToolPaint(FlatCAMTool, Gerber): # called on mouse move def on_mouse_move(event): curr_pos = self.app.plotcanvas.translate_coords(event.pos) - self.app.app_cursor.enabled = False # detect mouse dragging motion if event.is_dragging is True: @@ -1123,7 +1122,6 @@ class ToolPaint(FlatCAMTool, Gerber): # update the cursor position if self.app.grid_status() == True: - self.app.app_cursor.enabled = True # Update cursor curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1]) self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]), @@ -1136,12 +1134,12 @@ class ToolPaint(FlatCAMTool, Gerber): coords=(curr_pos[0], curr_pos[1]), face_alpha=0.0) - self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot) - self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot) + self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) - self.app.plotcanvas.vis_connect('mouse_release', on_mouse_release) - self.app.plotcanvas.vis_connect('mouse_move', on_mouse_move) + self.app.plotcanvas.graph_event_connect('mouse_release', on_mouse_release) + self.app.plotcanvas.graph_event_connect('mouse_move', on_mouse_move) elif select_method == 'ref': self.bound_obj_name = self.box_combo.currentText()