From 5cf9dadd680308158806678157f6da30b45d469d Mon Sep 17 00:00:00 2001 From: vocx-fc Date: Fri, 3 Apr 2020 19:37:56 -0600 Subject: [PATCH] Draft: move Rotate GuiCommand to gui_rotate module --- src/Mod/Draft/CMakeLists.txt | 1 + src/Mod/Draft/DraftTools.py | 276 +------------- src/Mod/Draft/draftguitools/gui_rotate.py | 428 ++++++++++++++++++++++ 3 files changed, 430 insertions(+), 275 deletions(-) create mode 100644 src/Mod/Draft/draftguitools/gui_rotate.py diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index 30d68c4c92..20784b1efc 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -104,6 +104,7 @@ SET(Modifier_tools draftguitools/gui_subelements.py draftguitools/gui_move.py draftguitools/gui_styles.py + draftguitools/gui_rotate.py ) SET(Draft_GUI_tools diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index aee9de22b8..720b054ded 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -176,280 +176,7 @@ from draftguitools.gui_base_original import Modifier from draftguitools.gui_subelements import SubelementHighlight from draftguitools.gui_move import Move from draftguitools.gui_styles import ApplyStyle - - -class Rotate(Modifier): - """The Draft_Rotate FreeCAD command definition""" - - def GetResources(self): - return {'Pixmap' : 'Draft_Rotate', - 'Accel' : "R, O", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Rotate", "Rotate"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Rotate", "Rotates the selected objects. CTRL to snap, SHIFT to constrain, ALT creates a copy")} - - def Activated(self): - Modifier.Activated(self,"Rotate") - if not self.ui: - return - self.ghosts = [] - self.arctrack = None - self.get_object_selection() - - def get_object_selection(self): - if FreeCADGui.Selection.getSelection(): - return self.proceed() - self.ui.selectUi() - FreeCAD.Console.PrintMessage(translate("draft", "Select an object to rotate")+"\n") - self.call = self.view.addEventCallback("SoEvent", selectObject) - - def proceed(self): - if self.call: - self.view.removeEventCallback("SoEvent", self.call) - self.selected_objects = FreeCADGui.Selection.getSelection() - self.selected_objects = Draft.getGroupContents(self.selected_objects, addgroups=True, spaces=True, noarchchild=True) - self.selected_subelements = FreeCADGui.Selection.getSelectionEx() - self.step = 0 - self.center = None - self.ui.rotateSetCenterUi() - self.ui.modUi() - self.ui.setTitle(translate("draft","Rotate")) - self.arctrack = trackers.arcTracker() - self.call = self.view.addEventCallback("SoEvent",self.action) - FreeCAD.Console.PrintMessage(translate("draft", "Pick rotation center")+"\n") - - def action(self, arg): - """scene event handler""" - if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": - self.finish() - elif arg["Type"] == "SoLocation2Event": - self.handle_mouse_move_event(arg) - elif arg["Type"] == "SoMouseButtonEvent" \ - and arg["State"] == "DOWN" \ - and arg["Button"] == "BUTTON1": - self.handle_mouse_click_event(arg) - - def handle_mouse_move_event(self, arg): - for ghost in self.ghosts: - ghost.off() - self.point,ctrlPoint,info = getPoint(self,arg) - # this is to make sure radius is what you see on screen - if self.center and DraftVecUtils.dist(self.point,self.center): - viewdelta = DraftVecUtils.project(self.point.sub(self.center), plane.axis) - if not DraftVecUtils.isNull(viewdelta): - self.point = self.point.add(viewdelta.negative()) - if self.extendedCopy: - if not hasMod(arg,MODALT): - self.step = 3 - self.finish() - if (self.step == 0): - pass - elif (self.step == 1): - currentrad = DraftVecUtils.dist(self.point,self.center) - if (currentrad != 0): - angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis) - else: angle = 0 - self.ui.setRadiusValue(math.degrees(angle),unit="Angle") - self.firstangle = angle - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() - elif (self.step == 2): - currentrad = DraftVecUtils.dist(self.point,self.center) - if (currentrad != 0): - angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis) - else: angle = 0 - if (angle < self.firstangle): - sweep = (2*math.pi-self.firstangle)+angle - else: - sweep = angle - self.firstangle - self.arctrack.setApertureAngle(sweep) - for ghost in self.ghosts: - ghost.rotate(plane.axis,sweep) - ghost.on() - self.ui.setRadiusValue(math.degrees(sweep), 'Angle') - self.ui.radiusValue.setFocus() - self.ui.radiusValue.selectAll() - redraw3DView() - - def handle_mouse_click_event(self, arg): - if not self.point: - return - if self.step == 0: - self.set_center() - elif self.step == 1: - self.set_start_point() - else: - self.set_rotation_angle(arg) - - def set_center(self): - if not self.ghosts: - self.set_ghosts() - self.center = self.point - self.node = [self.point] - self.ui.radiusUi() - self.ui.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Angle).UserString) - self.ui.hasFill.hide() - self.ui.labelRadius.setText(translate("draft","Base angle")) - self.ui.radiusValue.setToolTip(translate("draft","The base angle you wish to start the rotation from")) - self.arctrack.setCenter(self.center) - for ghost in self.ghosts: - ghost.center(self.center) - self.step = 1 - FreeCAD.Console.PrintMessage(translate("draft", "Pick base angle")+"\n") - if self.planetrack: - self.planetrack.set(self.point) - - def set_start_point(self): - self.ui.labelRadius.setText(translate("draft","Rotation")) - self.ui.radiusValue.setToolTip(translate("draft", "The amount of rotation you wish to perform. The final angle will be the base angle plus this amount.")) - self.rad = DraftVecUtils.dist(self.point,self.center) - self.arctrack.on() - self.arctrack.setStartPoint(self.point) - for ghost in self.ghosts: - ghost.on() - self.step = 2 - FreeCAD.Console.PrintMessage(translate("draft", "Pick rotation angle")+"\n") - - def set_rotation_angle(self, arg): - currentrad = DraftVecUtils.dist(self.point,self.center) - angle = self.point.sub(self.center).getAngle(plane.u) - if DraftVecUtils.project(self.point.sub(self.center), plane.v).getAngle(plane.v) > 1: - angle = -angle - if (angle < self.firstangle): - self.angle = (2*math.pi-self.firstangle)+angle - else: - self.angle = angle - self.firstangle - self.rotate(self.ui.isCopy.isChecked() or hasMod(arg,MODALT)) - if hasMod(arg,MODALT): - self.extendedCopy = True - else: - self.finish(cont=True) - - def set_ghosts(self): - if self.ui.isSubelementMode.isChecked(): - return self.set_subelement_ghosts() - self.ghosts = [trackers.ghostTracker(self.selected_objects)] - - def set_subelement_ghosts(self): - import Part - for object in self.selected_subelements: - for subelement in object.SubObjects: - if isinstance(subelement, Part.Vertex) \ - or isinstance(subelement, Part.Edge): - self.ghosts.append(trackers.ghostTracker(subelement)) - - def finish(self, closed=False, cont=False): - """finishes the arc""" - if self.arctrack: - self.arctrack.finalize() - for ghost in self.ghosts: - ghost.finalize() - if cont and self.ui: - if self.ui.continueMode: - ToDo.delayAfter(self.Activated, []) - Modifier.finish(self) - if self.doc: - self.doc.recompute() - - def rotate(self, is_copy=False): - if self.ui.isSubelementMode.isChecked(): - self.rotate_subelements(is_copy) - else: - self.rotate_object(is_copy) - - def rotate_subelements(self, is_copy): - try: - if is_copy: - self.commit(translate("draft", "Copy"), self.build_copy_subelements_command()) - else: - self.commit(translate("draft", "Rotate"), self.build_rotate_subelements_command()) - except: - FreeCAD.Console.PrintError(translate("draft", "Some subelements could not be moved.")) - - def build_copy_subelements_command(self): - import Part - command = [] - arguments = [] - for object in self.selected_subelements: - for index, subelement in enumerate(object.SubObjects): - if not isinstance(subelement, Part.Edge): - continue - arguments.append('[FreeCAD.ActiveDocument.{}, {}, {}, {}, {}]'.format( - object.ObjectName, - int(object.SubElementNames[index][len("Edge"):])-1, - math.degrees(self.angle), - DraftVecUtils.toString(self.center), - DraftVecUtils.toString(plane.axis))) - command.append('Draft.copyRotatedEdges([{}])'.format(','.join(arguments))) - command.append('FreeCAD.ActiveDocument.recompute()') - return command - - def build_rotate_subelements_command(self): - import Part - command = [] - for object in self.selected_subelements: - for index, subelement in enumerate(object.SubObjects): - if isinstance(subelement, Part.Vertex): - command.append('Draft.rotateVertex(FreeCAD.ActiveDocument.{}, {}, {}, {}, {})'.format( - object.ObjectName, - int(object.SubElementNames[index][len("Vertex"):])-1, - math.degrees(self.angle), - DraftVecUtils.toString(self.center), - DraftVecUtils.toString(plane.axis))) - elif isinstance(subelement, Part.Edge): - command.append('Draft.rotateEdge(FreeCAD.ActiveDocument.{}, {}, {}, {}, {})'.format( - object.ObjectName, - int(object.SubElementNames[index][len("Edge"):])-1, - math.degrees(self.angle), - DraftVecUtils.toString(self.center), - DraftVecUtils.toString(plane.axis))) - command.append('FreeCAD.ActiveDocument.recompute()') - return command - - def rotate_object(self, is_copy): - objects = '[' + ','.join(['FreeCAD.ActiveDocument.' + object.Name for object in self.selected_objects]) + ']' - FreeCADGui.addModule("Draft") - self.commit(translate("draft","Copy" if is_copy else "Rotate"), - ['Draft.rotate({},{},{},axis={},copy={})'.format( - objects, - math.degrees(self.angle), - DraftVecUtils.toString(self.center), - DraftVecUtils.toString(plane.axis), - is_copy - ), - 'FreeCAD.ActiveDocument.recompute()']) - - def numericInput(self,numx,numy,numz): - """this function gets called by the toolbar when valid x, y, and z have been entered there""" - self.center = Vector(numx,numy,numz) - self.node = [self.center] - self.arctrack.setCenter(self.center) - for ghost in self.ghosts: - ghost.center(self.center) - self.ui.radiusUi() - self.ui.hasFill.hide() - self.ui.labelRadius.setText(translate("draft","Base angle")) - self.ui.radiusValue.setToolTip(translate("draft","The base angle you wish to start the rotation from")) - self.ui.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Angle).UserString) - self.step = 1 - FreeCAD.Console.PrintMessage(translate("draft", "Pick base angle")+"\n") - - def numericRadius(self,rad): - """this function gets called by the toolbar when valid radius have been entered there""" - if (self.step == 1): - self.ui.labelRadius.setText(translate("draft","Rotation")) - self.ui.radiusValue.setToolTip(translate("draft","The amount of rotation you wish to perform. The final angle will be the base angle plus this amount.")) - self.ui.radiusValue.setText(FreeCAD.Units.Quantity(0,FreeCAD.Units.Angle).UserString) - self.firstangle = math.radians(rad) - self.arctrack.setStartAngle(self.firstangle) - self.arctrack.on() - for ghost in self.ghosts: - ghost.on() - self.step = 2 - FreeCAD.Console.PrintMessage(translate("draft", "Pick rotation angle")+"\n") - else: - self.angle = math.radians(rad) - self.rotate(self.ui.isCopy.isChecked()) - self.finish(cont=True) +from draftguitools.gui_rotate import Rotate class Offset(Modifier): @@ -2316,7 +2043,6 @@ from draftguitools.gui_snaps import ShowSnapBar # drawing commands # modification commands -FreeCADGui.addCommand('Draft_Rotate',Rotate()) FreeCADGui.addCommand('Draft_Offset',Offset()) FreeCADGui.addCommand('Draft_Join',Join()) FreeCADGui.addCommand('Draft_Split',Split()) diff --git a/src/Mod/Draft/draftguitools/gui_rotate.py b/src/Mod/Draft/draftguitools/gui_rotate.py new file mode 100644 index 0000000000..5e16c66e58 --- /dev/null +++ b/src/Mod/Draft/draftguitools/gui_rotate.py @@ -0,0 +1,428 @@ +# *************************************************************************** +# * (c) 2009, 2010 Yorik van Havre * +# * (c) 2009, 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 rotating objects in the 3D space.""" +## @package gui_rotate +# \ingroup DRAFT +# \brief Provides tools for rotating objects in the 3D space. + +import math +from PySide.QtCore import QT_TRANSLATE_NOOP + +import FreeCAD as App +import FreeCADGui as Gui +import Draft_rc +from FreeCAD import Units as U +import DraftVecUtils +import draftutils.utils as utils +import draftutils.todo as todo +import draftguitools.gui_base_original as gui_base_original +import draftguitools.gui_tool_utils as gui_tool_utils +import draftguitools.gui_trackers as trackers +from draftutils.messages import _msg, _err +from draftutils.translate import translate, _tr + +# The module is used to prevent complaints from code checkers (flake8) +True if Draft_rc.__name__ else False + + +class Rotate(gui_base_original.Modifier): + """Gui Command for the Rotate tool.""" + + def GetResources(self): + """Set icon, menu and tooltip.""" + _tip = ("Rotates the selected objects. " + "Choose the center of rotation, then the initial angle, " + "and then the final angle.\n" + 'If the "copy" option is active, it will create ' + "rotated copies.\n" + "CTRL to snap, SHIFT to constrain. " + "Hold ALT and click to create a copy with each click.") + + return {'Pixmap': 'Draft_Rotate', + 'Accel': "R, O", + 'MenuText': QT_TRANSLATE_NOOP("Draft_Rotate", "Rotate"), + 'ToolTip': QT_TRANSLATE_NOOP("Draft_Rotate", _tip)} + + def Activated(self): + """Execute when the command is called.""" + super().Activated(name=_tr("Rotate")) + if not self.ui: + return + self.ghosts = [] + self.arctrack = None + self.get_object_selection() + + def get_object_selection(self): + """Get the object selection.""" + if Gui.Selection.getSelection(): + return self.proceed() + self.ui.selectUi() + _msg(translate("draft", "Select an object to rotate")) + self.call = \ + self.view.addEventCallback("SoEvent", gui_tool_utils.selectObject) + + def proceed(self): + """Continue with the command after a selection has been made.""" + if self.call: + self.view.removeEventCallback("SoEvent", self.call) + self.selected_objects = Gui.Selection.getSelection() + self.selected_objects = utils.getGroupContents(self.selected_objects, + addgroups=True, + spaces=True, + noarchchild=True) + self.selected_subelements = Gui.Selection.getSelectionEx() + self.step = 0 + self.center = None + self.ui.rotateSetCenterUi() + self.ui.modUi() + self.ui.setTitle(translate("draft", "Rotate")) + self.arctrack = trackers.arcTracker() + self.call = self.view.addEventCallback("SoEvent", self.action) + _msg(translate("draft", "Pick rotation center")) + + def action(self, arg): + """Handle the 3D scene events. + + This is installed as an EventCallback in the Inventor view. + + Parameters + ---------- + arg: dict + Dictionary with strings that indicates the type of event received + from the 3D view. + """ + if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE": + self.finish() + elif arg["Type"] == "SoLocation2Event": + self.handle_mouse_move_event(arg) + elif (arg["Type"] == "SoMouseButtonEvent" + and arg["State"] == "DOWN" + and arg["Button"] == "BUTTON1"): + self.handle_mouse_click_event(arg) + + def handle_mouse_move_event(self, arg): + """Hande the mouse when moving.""" + plane = App.DraftWorkingPlane + + for ghost in self.ghosts: + ghost.off() + self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) + # this is to make sure radius is what you see on screen + if self.center and DraftVecUtils.dist(self.point, self.center): + viewdelta = DraftVecUtils.project(self.point.sub(self.center), + plane.axis) + if not DraftVecUtils.isNull(viewdelta): + self.point = self.point.add(viewdelta.negative()) + if self.extendedCopy: + if not gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): + self.step = 3 + self.finish() + if self.step == 0: + pass + elif self.step == 1: + currentrad = DraftVecUtils.dist(self.point, self.center) + if currentrad != 0: + angle = DraftVecUtils.angle(plane.u, + self.point.sub(self.center), + plane.axis) + else: + angle = 0 + self.ui.setRadiusValue(math.degrees(angle), unit="Angle") + self.firstangle = angle + self.ui.radiusValue.setFocus() + self.ui.radiusValue.selectAll() + elif self.step == 2: + currentrad = DraftVecUtils.dist(self.point, self.center) + if currentrad != 0: + angle = DraftVecUtils.angle(plane.u, + self.point.sub(self.center), + plane.axis) + else: + angle = 0 + if angle < self.firstangle: + sweep = (2 * math.pi - self.firstangle) + angle + else: + sweep = angle - self.firstangle + self.arctrack.setApertureAngle(sweep) + for ghost in self.ghosts: + ghost.rotate(plane.axis, sweep) + ghost.on() + self.ui.setRadiusValue(math.degrees(sweep), 'Angle') + self.ui.radiusValue.setFocus() + self.ui.radiusValue.selectAll() + gui_tool_utils.redraw3DView() + + def handle_mouse_click_event(self, arg): + """Hande the mouse when the first button is clicked.""" + if not self.point: + return + if self.step == 0: + self.set_center() + elif self.step == 1: + self.set_start_point() + else: + self.set_rotation_angle(arg) + + def set_center(self): + """Set the center of the rotation.""" + if not self.ghosts: + self.set_ghosts() + self.center = self.point + self.node = [self.point] + self.ui.radiusUi() + self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) + self.ui.hasFill.hide() + self.ui.labelRadius.setText(translate("draft", "Base angle")) + _tip = "The base angle you wish to start the rotation from" + self.ui.radiusValue.setToolTip(translate("draft", _tip)) + self.arctrack.setCenter(self.center) + for ghost in self.ghosts: + ghost.center(self.center) + self.step = 1 + _msg(translate("draft", "Pick base angle")) + if self.planetrack: + self.planetrack.set(self.point) + + def set_start_point(self): + """Set the starting point of the rotation.""" + self.ui.labelRadius.setText(translate("draft", "Rotation")) + _tip = ("The amount of rotation you wish to perform.\n" + "The final angle will be the base angle plus this amount.") + self.ui.radiusValue.setToolTip(translate("draft", _tip)) + self.rad = DraftVecUtils.dist(self.point, self.center) + self.arctrack.on() + self.arctrack.setStartPoint(self.point) + for ghost in self.ghosts: + ghost.on() + self.step = 2 + _msg(translate("draft", "Pick rotation angle")) + + def set_rotation_angle(self, arg): + """Set the rotation angle.""" + plane = App.DraftWorkingPlane + + # currentrad = DraftVecUtils.dist(self.point, self.center) + angle = self.point.sub(self.center).getAngle(plane.u) + _v = DraftVecUtils.project(self.point.sub(self.center), plane.v) + if _v.getAngle(plane.v) > 1: + angle = -angle + if angle < self.firstangle: + self.angle = (2 * math.pi - self.firstangle) + angle + else: + self.angle = angle - self.firstangle + self.rotate(self.ui.isCopy.isChecked() + or gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT)) + if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): + self.extendedCopy = True + else: + self.finish(cont=True) + + def set_ghosts(self): + """Set the ghost to display.""" + if self.ui.isSubelementMode.isChecked(): + return self.set_subelement_ghosts() + self.ghosts = [trackers.ghostTracker(self.selected_objects)] + + def set_subelement_ghosts(self): + """Set ghost for the subelements (vertices, edges).""" + import Part + + for obj in self.selected_subelements: + for subelement in obj.SubObjects: + if (isinstance(subelement, Part.Vertex) + or isinstance(subelement, Part.Edge)): + self.ghosts.append(trackers.ghostTracker(subelement)) + + def finish(self, closed=False, cont=False): + """Finish the rotate operation.""" + if self.arctrack: + self.arctrack.finalize() + for ghost in self.ghosts: + ghost.finalize() + if cont and self.ui: + if self.ui.continueMode: + todo.ToDo.delayAfter(self.Activated, []) + super().finish() + if self.doc: + self.doc.recompute() + + def rotate(self, is_copy=False): + """Perform the rotation of the subelements or the entire object.""" + if self.ui.isSubelementMode.isChecked(): + self.rotate_subelements(is_copy) + else: + self.rotate_object(is_copy) + + def rotate_subelements(self, is_copy): + """Rotate the subelements.""" + try: + if is_copy: + self.commit(translate("draft", "Copy"), + self.build_copy_subelements_command()) + else: + self.commit(translate("draft", "Rotate"), + self.build_rotate_subelements_command()) + except Exception: + _err(translate("draft", "Some subelements could not be moved.")) + + def build_copy_subelements_command(self): + """Build the string to commit to copy the subelements.""" + import Part + plane = App.DraftWorkingPlane + + command = [] + arguments = [] + E = len("Edge") + for obj in self.selected_subelements: + for index, subelement in enumerate(obj.SubObjects): + if not isinstance(subelement, Part.Edge): + continue + _edge_index = int(obj.SubElementNames[index][E:]) - 1 + _cmd = '[' + _cmd += 'FreeCAD.ActiveDocument.' + _cmd += obj.ObjectName + ', ' + _cmd += str(_edge_index) + ', ' + _cmd += str(math.degrees(self.angle)) + ', ' + _cmd += DraftVecUtils.toString(self.center) + ', ' + _cmd += DraftVecUtils.toString(plane.axis) + _cmd += ']' + arguments.append(_cmd) + + all_args = ', '.join(arguments) + command.append('Draft.copyRotatedEdges([' + all_args + '])') + command.append('FreeCAD.ActiveDocument.recompute()') + return command + + def build_rotate_subelements_command(self): + """Build the string to commit to rotate the subelements.""" + import Part + plane = App.DraftWorkingPlane + + command = [] + V = len("Vertex") + E = len("Edge") + for obj in self.selected_subelements: + for index, subelement in enumerate(obj.SubObjects): + if isinstance(subelement, Part.Vertex): + _vertex_index = int(obj.SubElementNames[index][V:]) - 1 + _cmd = 'Draft.rotateVertex' + _cmd += '(' + _cmd += 'FreeCAD.ActiveDocument.' + _cmd += obj.ObjectName + ', ' + _cmd += str(_vertex_index) + ', ' + _cmd += str(math.degrees(self.angle)) + ', ' + _cmd += DraftVecUtils.toString(self.center) + ', ' + _cmd += DraftVecUtils.toString(plane.axis) + _cmd += ')' + command.append(_cmd) + elif isinstance(subelement, Part.Edge): + _edge_index = int(obj.SubElementNames[index][E:]) - 1 + _cmd = 'Draft.rotateEdge' + _cmd += '(' + _cmd += 'FreeCAD.ActiveDocument.' + _cmd += obj.ObjectName + ', ' + _cmd += str(_edge_index) + ', ' + _cmd += str(math.degrees(self.angle)) + ', ' + _cmd += DraftVecUtils.toString(self.center) + ', ' + _cmd += DraftVecUtils.toString(plane.axis) + _cmd += ')' + command.append(_cmd) + command.append('FreeCAD.ActiveDocument.recompute()') + return command + + def rotate_object(self, is_copy): + """Move the object.""" + plane = App.DraftWorkingPlane + + _doc = 'FreeCAD.ActiveDocument.' + _selected = self.selected_objects + + objects = '[' + objects += ','.join([_doc + obj.Name for obj in _selected]) + objects += ']' + + _cmd = 'Draft.rotate' + _cmd += '(' + _cmd += objects + ', ' + _cmd += str(math.degrees(self.angle)) + ', ' + _cmd += DraftVecUtils.toString(self.center) + ', ' + _cmd += 'axis=' + DraftVecUtils.toString(plane.axis) + ', ' + _cmd += 'copy=' + str(is_copy) + _cmd += ')' + _cmd_list = [_cmd, + 'FreeCAD.ActiveDocument.recompute()'] + + _mode = "Copy" if is_copy else "Rotate" + Gui.addModule("Draft") + self.commit(translate("draft", _mode), + _cmd_list) + + def numericInput(self, numx, numy, numz): + """Validate the entry fields in the user interface. + + This function is called by the toolbar or taskpanel interface + when valid x, y, and z have been entered in the input fields. + """ + self.center = App.Vector(numx, numy, numz) + self.node = [self.center] + self.arctrack.setCenter(self.center) + for ghost in self.ghosts: + ghost.center(self.center) + self.ui.radiusUi() + self.ui.hasFill.hide() + self.ui.labelRadius.setText(translate("draft", "Base angle")) + _tip = "The base angle you wish to start the rotation from" + self.ui.radiusValue.setToolTip(translate("draft", _tip)) + self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) + self.step = 1 + _msg(translate("draft", "Pick base angle")) + + def numericRadius(self, rad): + """Validate the radius entry field in the user interface. + + This function is called by the toolbar or taskpanel interface + when a valid radius has been entered in the input field. + """ + if self.step == 1: + self.ui.labelRadius.setText(translate("draft", "Rotation")) + _tip = ("The amount of rotation you wish to perform.\n" + "The final angle will be the base angle " + "plus this amount.") + self.ui.radiusValue.setToolTip(translate("draft", _tip)) + self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) + self.firstangle = math.radians(rad) + self.arctrack.setStartAngle(self.firstangle) + self.arctrack.on() + for ghost in self.ghosts: + ghost.on() + self.step = 2 + _msg(translate("draft", "Pick rotation angle")) + else: + self.angle = math.radians(rad) + self.rotate(self.ui.isCopy.isChecked()) + self.finish(cont=True) + + +Gui.addCommand('Draft_Rotate', Rotate())