diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index d62862af72..b3fd8a6ebc 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -100,6 +100,10 @@ SET(Creator_tools draftguitools/gui_labels.py ) +SET(Modifier_tools + draftguitools/gui_subelements.py +) + SET(Draft_GUI_tools draftguitools/__init__.py draftguitools/gui_annotationstyleeditor.py @@ -124,6 +128,7 @@ SET(Draft_GUI_tools draftguitools/gui_dimension_ops.py draftguitools/gui_lineslope.py ${Creator_tools} + ${Modifier_tools} draftguitools/README.md ) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 398666b2de..2ee61f2742 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -173,6 +173,7 @@ from draftguitools.gui_labels import Draft_Label # --------------------------------------------------------------------------- from draftguitools.gui_base_original import Modifier +from draftguitools.gui_subelements import SubelementHighlight class Move(Modifier): """The Draft_Move FreeCAD command definition""" @@ -2051,96 +2052,6 @@ class Drawing(Modifier): return page -class SubelementHighlight(Modifier): - """The Draft_SubelementHighlight FreeCAD command definition""" - - def __init__(self): - self.is_running = False - self.editable_objects = [] - self.original_view_settings = {} - - def GetResources(self): - return {'Pixmap' : 'Draft_SubelementHighlight', - 'Accel' : "H, S", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_SubelementHighlight", "Subelement highlight"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_SubelementHighlight", - "Highlight the subelements " - "of the selected objects, " - "so that they can then be edited " - "with the move, rotate, and scale tools")} - - def Activated(self): - if self.is_running: - return self.finish() - self.is_running = True - Modifier.Activated(self, "SubelementHighlight") - self.get_selection() - - def proceed(self): - self.remove_view_callback() - self.get_editable_objects_from_selection() - if not self.editable_objects: - return self.finish() - self.call = self.view.addEventCallback("SoEvent", self.action) - self.highlight_editable_objects() - - def finish(self): - Modifier.finish(self) - self.remove_view_callback() - self.restore_editable_objects_graphics() - self.__init__() - - def action(self, event): - if event["Type"] == "SoKeyboardEvent" and event["Key"] == "ESCAPE": - self.finish() - - def get_selection(self): - if not FreeCADGui.Selection.getSelection() and self.ui: - FreeCAD.Console.PrintMessage(translate("draft", "Select an object to edit")+"\n") - self.call = self.view.addEventCallback("SoEvent", selectObject) - else: - self.proceed() - - def remove_view_callback(self): - if self.call: - self.view.removeEventCallback("SoEvent",self.call) - - def get_editable_objects_from_selection(self): - for object in FreeCADGui.Selection.getSelection(): - if object.isDerivedFrom("Part::Part2DObject"): - self.editable_objects.append(object) - elif hasattr(object, "Base") and object.Base.isDerivedFrom("Part::Part2DObject"): - self.editable_objects.append(object.Base) - - def highlight_editable_objects(self): - for object in self.editable_objects: - self.original_view_settings[object.Name] = { - 'Visibility': object.ViewObject.Visibility, - 'PointSize': object.ViewObject.PointSize, - 'PointColor': object.ViewObject.PointColor, - 'LineColor': object.ViewObject.LineColor - } - object.ViewObject.Visibility = True - object.ViewObject.PointSize = 10 - object.ViewObject.PointColor = (1., 0., 0.) - object.ViewObject.LineColor = (1., 0., 0.) - xray = coin.SoAnnotation() - xray.addChild(object.ViewObject.RootNode.getChild(2).getChild(0)) - xray.setName("xray") - object.ViewObject.RootNode.addChild(xray) - - def restore_editable_objects_graphics(self): - for object in self.editable_objects: - try: - for attribute, value in self.original_view_settings[object.Name].items(): - view_object = object.ViewObject - setattr(view_object, attribute, value) - view_object.RootNode.removeChild(view_object.RootNode.getByName("xray")) - except: - # This can occur if objects have had graph changing operations - pass - - class WireToBSpline(Modifier): """The Draft_Wire2BSpline FreeCAD command definition""" @@ -2635,7 +2546,6 @@ FreeCADGui.addCommand('Draft_Downgrade',Downgrade()) FreeCADGui.addCommand('Draft_Trimex',Trimex()) FreeCADGui.addCommand('Draft_Scale',Scale()) FreeCADGui.addCommand('Draft_Drawing',Drawing()) -FreeCADGui.addCommand('Draft_SubelementHighlight', SubelementHighlight()) FreeCADGui.addCommand('Draft_WireToBSpline',WireToBSpline()) FreeCADGui.addCommand('Draft_Draft2Sketch',Draft2Sketch()) FreeCADGui.addCommand('Draft_Array',Array()) diff --git a/src/Mod/Draft/draftguitools/gui_subelements.py b/src/Mod/Draft/draftguitools/gui_subelements.py new file mode 100644 index 0000000000..d723093610 --- /dev/null +++ b/src/Mod/Draft/draftguitools/gui_subelements.py @@ -0,0 +1,161 @@ +# *************************************************************************** +# * (c) 2009 Yorik van Havre * +# * (c) 2010 Ken Cline * +# * (c) 2020 Eliud Cabrera Castillo * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** +"""Provides tools for highlighting subelements in the Draft Workbench. + +The highlighting can be used to manipulate shapes with other tools +such as Move, Rotate, and Scale. +""" +## @package gui_subelements +# \ingroup DRAFT +# \brief Provides tools for highlighting subelements in the Draft Workbench. + +import pivy.coin as coin +from PySide.QtCore import QT_TRANSLATE_NOOP + +import FreeCADGui as Gui +import draftguitools.gui_base_original as gui_base_original +import draftguitools.gui_tool_utils as gui_tool_utils +from draftutils.messages import _msg +from draftutils.translate import translate, _tr + + +class SubelementHighlight(gui_base_original.Modifier): + """Gui Command for the SubelementHighlight tool.""" + + def __init__(self): + self.is_running = False + self.editable_objects = [] + self.original_view_settings = {} + + def GetResources(self): + """Set icon, menu and tooltip.""" + _menu = "Subelement highlight" + _tip = ("Highlight the subelements " + "of the selected objects, " + "so that they can then be edited " + "with the move, rotate, and scale tools.") + + return {'Pixmap': 'Draft_SubelementHighlight', + 'Accel': "H, S", + 'MenuText': QT_TRANSLATE_NOOP("Draft_SubelementHighlight", + _menu), + 'ToolTip': QT_TRANSLATE_NOOP("Draft_SubelementHighlight", + _tip)} + + def Activated(self): + """Execute when the command is called.""" + if self.is_running: + return self.finish() + self.is_running = True + super().Activated(name=_tr("Subelement highlight")) + self.get_selection() + + def proceed(self): + """Continue with the command.""" + self.remove_view_callback() + self.get_editable_objects_from_selection() + if not self.editable_objects: + return self.finish() + self.call = self.view.addEventCallback("SoEvent", self.action) + self.highlight_editable_objects() + + def finish(self): + """Terminate the operation. + + Re-initialize by running __init__ again at the end. + """ + super().finish() + self.remove_view_callback() + self.restore_editable_objects_graphics() + self.__init__() + + def action(self, event): + """Handle the 3D scene events. + + This is installed as an EventCallback in the Inventor view. + + Parameters + ---------- + event: dict + Dictionary with strings that indicates the type of event received + from the 3D view. + """ + if event["Type"] == "SoKeyboardEvent" and event["Key"] == "ESCAPE": + self.finish() + + def get_selection(self): + """Get the selection.""" + if not Gui.Selection.getSelection() and self.ui: + _msg(translate("draft", "Select an object to edit")) + self.call = self.view.addEventCallback("SoEvent", + gui_tool_utils.selectObject) + else: + self.proceed() + + def remove_view_callback(self): + """Remove the installed callback if it exists.""" + if self.call: + self.view.removeEventCallback("SoEvent", self.call) + + def get_editable_objects_from_selection(self): + """Get editable Draft objects for the selection.""" + for obj in Gui.Selection.getSelection(): + if obj.isDerivedFrom("Part::Part2DObject"): + self.editable_objects.append(obj) + elif (hasattr(obj, "Base") + and obj.Base.isDerivedFrom("Part::Part2DObject")): + self.editable_objects.append(obj.Base) + + def highlight_editable_objects(self): + """Highlight editable Draft objects from the selection.""" + for obj in self.editable_objects: + self.original_view_settings[obj.Name] = { + 'Visibility': obj.ViewObject.Visibility, + 'PointSize': obj.ViewObject.PointSize, + 'PointColor': obj.ViewObject.PointColor, + 'LineColor': obj.ViewObject.LineColor} + obj.ViewObject.Visibility = True + obj.ViewObject.PointSize = 10 + obj.ViewObject.PointColor = (1.0, 0.0, 0.0) + obj.ViewObject.LineColor = (1.0, 0.0, 0.0) + xray = coin.SoAnnotation() + xray.addChild(obj.ViewObject.RootNode.getChild(2).getChild(0)) + xray.setName("xray") + obj.ViewObject.RootNode.addChild(xray) + + def restore_editable_objects_graphics(self): + """Restore the editable objects' appearance.""" + for obj in self.editable_objects: + try: + for attribute, value in self.original_view_settings[obj.Name].items(): + vobj = obj.ViewObject + setattr(vobj, attribute, value) + vobj.RootNode.removeChild(vobj.RootNode.getByName("xray")) + except Exception: + # This can occur if objects have had graph changing operations + pass + + +Gui.addCommand('Draft_SubelementHighlight', SubelementHighlight())