diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py
index 07962ad989..53d154c1b9 100644
--- a/src/Mod/Arch/InitGui.py
+++ b/src/Mod/Arch/InitGui.py
@@ -51,6 +51,7 @@ class ArchWorkbench(FreeCADGui.Workbench):
import DraftGui
from draftguitools import gui_circulararray
from draftguitools import gui_polararray
+ from draftguitools import gui_orthoarray
from draftguitools import gui_arrays
import Arch_rc
import Arch
diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt
index 31e6e30e64..ae6a91f934 100644
--- a/src/Mod/Draft/CMakeLists.txt
+++ b/src/Mod/Draft/CMakeLists.txt
@@ -60,12 +60,14 @@ SET(Draft_utilities
SET(Draft_objects
draftobjects/__init__.py
draftobjects/circulararray.py
+ draftobjects/orthoarray.py
draftobjects/polararray.py
)
SET(Draft_view_providers
draftviewproviders/__init__.py
draftviewproviders/view_circulararray.py
+ draftviewproviders/view_orthoarray.py
draftviewproviders/view_polararray.py
)
@@ -73,6 +75,7 @@ SET(Draft_GUI_tools
draftguitools/__init__.py
draftguitools/gui_base.py
draftguitools/gui_circulararray.py
+ draftguitools/gui_orthoarray.py
draftguitools/gui_polararray.py
draftguitools/gui_arrays.py
)
@@ -80,6 +83,7 @@ SET(Draft_GUI_tools
SET(Draft_task_panels
drafttaskpanels/__init__.py
drafttaskpanels/task_circulararray.py
+ drafttaskpanels/task_orthoarray.py
drafttaskpanels/task_polararray.py
)
diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py
index cace902269..d864f31af4 100644
--- a/src/Mod/Draft/InitGui.py
+++ b/src/Mod/Draft/InitGui.py
@@ -82,6 +82,7 @@ class DraftWorkbench(FreeCADGui.Workbench):
import DraftFillet
from draftguitools import gui_circulararray
from draftguitools import gui_polararray
+ from draftguitools import gui_orthoarray
from draftguitools import gui_arrays
FreeCADGui.addLanguagePath(":/translations")
FreeCADGui.addIconPath(":/icons")
diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc
index 0156b55822..0eef2df32e 100644
--- a/src/Mod/Draft/Resources/Draft.qrc
+++ b/src/Mod/Draft/Resources/Draft.qrc
@@ -152,6 +152,7 @@
ui/preferences-oca.ui
ui/preferences-svg.ui
ui/TaskPanel_CircularArray.ui
+ ui/TaskPanel_OrthoArray.ui
ui/TaskPanel_PolarArray.ui
ui/TaskSelectPlane.ui
ui/TaskShapeString.ui
diff --git a/src/Mod/Draft/Resources/ui/TaskPanel_OrthoArray.ui b/src/Mod/Draft/Resources/ui/TaskPanel_OrthoArray.ui
new file mode 100644
index 0000000000..52541fe2f9
--- /dev/null
+++ b/src/Mod/Draft/Resources/ui/TaskPanel_OrthoArray.ui
@@ -0,0 +1,441 @@
+
+
+ DraftOrthoArrayTaskPanel
+
+
+
+ 0
+ 0
+ 440
+ 883
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 250
+ 0
+
+
+
+ Orthogonal array
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
-
+
+
+ Distance between the elements in the Z direction. Normally, only the Z value is necessary; the other two values can give an additional shift in their respective directions.
+
+
+ Interval Z
+
+
+
-
+
+
-
+
+
+ Z
+
+
+
+ -
+
+
+ Y
+
+
+
+ -
+
+
+ X
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ 100.000000000000000
+
+
+
+
+
+ -
+
+
+ Reset the distances
+
+
+ Reset Z
+
+
+
+
+
+
+ -
+
+
-
+
+
+ If checked, the resulting objects in the array will be fused if they touch each other
+
+
+ Fuse
+
+
+
+ -
+
+
+ If checked, the resulting objects in the array will be Links instead of simple copies
+
+
+ Use Links
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Number of elements in the array in the specified direction, including a copy of the original object. The number must be at least 1 in each direction.
+
+
+ Number of elements
+
+
+
-
+
+
-
+
+
+ X
+
+
+
+ -
+
+
+ Z
+
+
+
+ -
+
+
+ Y
+
+
+
+ -
+
+
+ 1
+
+
+ 2
+
+
+
+ -
+
+
+ 1
+
+
+ 2
+
+
+
+ -
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+
+ -
+
+
+ (Placeholder for the icon)
+
+
+
+ -
+
+
+ Distance between the elements in the X direction. Normally, only the X value is necessary; the other two values can give an additional shift in their respective directions.
+
+
+ Interval X
+
+
+
-
+
+
-
+
+
+ Z
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ 100.000000000000000
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+ X
+
+
+
+ -
+
+
+ Y
+
+
+
+
+
+ -
+
+
+ Reset the distances
+
+
+ Reset X
+
+
+
+
+
+
+ -
+
+
+ Distance between the elements in the Y direction. Normally, only the Y value is necessary; the other two values can give an additional shift in their respective directions.
+
+
+ Interval Y
+
+
+
-
+
+
-
+
+
+ X
+
+
+
+ -
+
+
+ Y
+
+
+
+ -
+
+
+ Z
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ 100.000000000000000
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Reset the distances
+
+
+ Reset Y
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Gui::InputField
+ QLineEdit
+
+
+
+
+ input_X_x
+ input_X_y
+ input_X_z
+ button_reset_X
+ checkbox_fuse
+ checkbox_link
+
+
+
+
diff --git a/src/Mod/Draft/draftguitools/gui_arrays.py b/src/Mod/Draft/draftguitools/gui_arrays.py
index c0048c2e78..49a7f096f5 100644
--- a/src/Mod/Draft/draftguitools/gui_arrays.py
+++ b/src/Mod/Draft/draftguitools/gui_arrays.py
@@ -35,7 +35,7 @@ class ArrayGroupCommand:
def GetCommands(self):
"""Tuple of array commands."""
- return tuple(["Draft_Array", "Draft_LinkArray",
+ return tuple(["Draft_OrthoArray",
"Draft_PolarArray", "Draft_CircularArray",
"Draft_PathArray", "Draft_PathLinkArray",
"Draft_PointArray"])
diff --git a/src/Mod/Draft/draftguitools/gui_orthoarray.py b/src/Mod/Draft/draftguitools/gui_orthoarray.py
new file mode 100644
index 0000000000..b7c0551f3b
--- /dev/null
+++ b/src/Mod/Draft/draftguitools/gui_orthoarray.py
@@ -0,0 +1,142 @@
+"""Provide the Draft OrthoArray tool."""
+## @package gui_orthoarray
+# \ingroup DRAFT
+# \brief Provide the Draft OrthoArray tool.
+
+# ***************************************************************************
+# * (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 *
+# * *
+# ***************************************************************************
+
+import FreeCAD as App
+import FreeCADGui as Gui
+import Draft
+import DraftGui
+import Draft_rc
+from . import gui_base
+from drafttaskpanels import task_orthoarray
+
+
+if App.GuiUp:
+ from PySide.QtCore import QT_TRANSLATE_NOOP
+ # import DraftTools
+ from draftutils.translate import translate
+ # from DraftGui import displayExternal
+ from pivy import coin
+else:
+ def QT_TRANSLATE_NOOP(context, text):
+ return text
+
+ def translate(context, text):
+ return text
+
+
+def _tr(text):
+ """Translate the text with the context set."""
+ return translate("Draft", text)
+
+
+# So the resource file doesn't trigger errors from code checkers (flake8)
+True if Draft_rc.__name__ else False
+
+
+class GuiCommandOrthoArray(gui_base.GuiCommandBase):
+ """Gui command for the OrthoArray tool."""
+
+ def __init__(self):
+ super().__init__()
+ self.command_name = "OrthoArray"
+ # self.location = None
+ self.mouse_event = None
+ self.view = None
+ # self.callback_move = None
+ self.callback_click = None
+ self.ui = None
+ self.point = App.Vector()
+
+ def GetResources(self):
+ """Set icon, menu and tooltip."""
+ _msg = ("Creates copies of a selected object, "
+ "and places the copies in an orthogonal pattern.\n"
+ "The properties of the array can be further modified after "
+ "the new object is created, including turning it into "
+ "a different type of array.")
+ d = {'Pixmap': 'Draft_Array',
+ 'MenuText': QT_TRANSLATE_NOOP("Draft", "Array"),
+ 'ToolTip': QT_TRANSLATE_NOOP("Draft", _msg)}
+ return d
+
+ def Activated(self):
+ """Execute this when the command is called.
+
+ We add callbacks that connect the 3D view with
+ the widgets of the task panel.
+ """
+ # self.location = coin.SoLocation2Event.getClassTypeId()
+ self.mouse_event = coin.SoMouseButtonEvent.getClassTypeId()
+ self.view = Draft.get3DView()
+ # self.callback_move = \
+ # self.view.addEventCallbackPivy(self.location, self.move)
+ self.callback_click = \
+ self.view.addEventCallbackPivy(self.mouse_event, self.click)
+
+ self.ui = task_orthoarray.TaskPanelOrthoArray()
+ # The calling class (this one) is saved in the object
+ # of the interface, to be able to call a function from within it.
+ self.ui.source_command = self
+ # Gui.Control.showDialog(self.ui)
+ DraftGui.todo.delay(Gui.Control.showDialog, self.ui)
+
+ def click(self, event_cb=None):
+ """Run callback for when the mouse pointer clicks on the 3D view.
+
+ It should act as if the Enter key was pressed, or the OK button
+ was pressed in the task panel.
+ """
+ if event_cb:
+ event = event_cb.getEvent()
+ if (event.getState() != coin.SoMouseButtonEvent.DOWN
+ or event.getButton() != coin.SoMouseButtonEvent.BUTTON1):
+ return
+ if self.ui and self.point:
+ # The accept function of the interface
+ # should call the completed function
+ # of the calling class (this one).
+ self.ui.accept()
+
+ def completed(self):
+ """Run when the command is terminated.
+
+ We should remove the callbacks that were added to the 3D view
+ and then close the task panel.
+ """
+ # self.view.removeEventCallbackPivy(self.location,
+ # self.callback_move)
+ self.view.removeEventCallbackPivy(self.mouse_event,
+ self.callback_click)
+ if Gui.Control.activeDialog():
+ Gui.Snapper.off()
+ Gui.Control.closeDialog()
+ super().finish()
+
+
+if App.GuiUp:
+ Gui.addCommand('Draft_OrthoArray', GuiCommandOrthoArray())
diff --git a/src/Mod/Draft/draftobjects/orthoarray.py b/src/Mod/Draft/draftobjects/orthoarray.py
new file mode 100644
index 0000000000..f8d415f614
--- /dev/null
+++ b/src/Mod/Draft/draftobjects/orthoarray.py
@@ -0,0 +1,60 @@
+"""Provide the object code for Draft Array."""
+## @package orthoarray
+# \ingroup DRAFT
+# \brief Provide the object code for Draft Array.
+
+# ***************************************************************************
+# * (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 *
+# * *
+# ***************************************************************************
+
+import FreeCAD as App
+import Draft
+
+
+def make_ortho_array(obj,
+ v_x=App.Vector(10, 0, 0),
+ v_y=App.Vector(0, 10, 0),
+ v_z=App.Vector(0, 0, 10),
+ n_x=2,
+ n_y=2,
+ n_z=1,
+ use_link=False):
+ """Create an orthogonal array from the given object."""
+ obj = Draft.makeArray(obj,
+ arg1=v_x, arg2=v_y, arg3=v_z,
+ arg4=n_x, arg5=n_y, arg6=n_z,
+ useLink=use_link)
+ return obj
+
+
+def make_ortho_array2(obj,
+ v_x=App.Vector(10, 0, 0),
+ v_y=App.Vector(0, 10, 0),
+ n_x=2,
+ n_y=2,
+ use_link=False):
+ """Create a 2D orthogonal array from the given object."""
+ obj = Draft.makeArray(obj,
+ arg1=v_x, arg2=v_y,
+ arg3=n_x, arg4=n_y,
+ useLink=use_link)
+ return obj
diff --git a/src/Mod/Draft/drafttaskpanels/task_orthoarray.py b/src/Mod/Draft/drafttaskpanels/task_orthoarray.py
new file mode 100644
index 0000000000..170be5e810
--- /dev/null
+++ b/src/Mod/Draft/drafttaskpanels/task_orthoarray.py
@@ -0,0 +1,347 @@
+"""Provide the task panel for the Draft OrthoArray tool."""
+## @package task_orthoarray
+# \ingroup DRAFT
+# \brief Provide the task panel for the Draft OrthoArray tool.
+
+# ***************************************************************************
+# * (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 *
+# * *
+# ***************************************************************************
+
+import FreeCAD as App
+import FreeCADGui as Gui
+# import Draft
+import Draft_rc
+import DraftVecUtils
+
+import PySide.QtGui as QtGui
+from PySide.QtCore import QT_TRANSLATE_NOOP
+# import DraftTools
+from draftutils.translate import translate
+# from DraftGui import displayExternal
+
+_Quantity = App.Units.Quantity
+
+
+def _Msg(text, end="\n"):
+ """Print message with newline."""
+ App.Console.PrintMessage(text + end)
+
+
+def _Wrn(text, end="\n"):
+ """Print warning with newline."""
+ App.Console.PrintWarning(text + end)
+
+
+def _tr(text):
+ """Translate with the context set."""
+ return translate("Draft", text)
+
+
+# So the resource file doesn't trigger errors from code checkers (flake8)
+True if Draft_rc else False
+
+
+class TaskPanelOrthoArray:
+ """TaskPanel for the OrthoArray command.
+
+ The names of the widgets are defined in the `.ui` file.
+ In this class all those widgets are automatically created
+ under the name `self.form.`
+
+ The `.ui` file may use special FreeCAD widgets such as
+ `Gui::InputField` (based on `QLineEdit`) and
+ `Gui::QuantitySpinBox` (based on `QAbstractSpinBox`).
+ See the Doxygen documentation of the corresponding files in `src/Gui/`,
+ for example, `InputField.h` and `QuantitySpinBox.h`.
+ """
+
+ def __init__(self):
+ ui_file = ":/ui/TaskPanel_OrthoArray.ui"
+ self.form = Gui.PySideUic.loadUi(ui_file)
+ self.name = self.form.windowTitle()
+
+ icon_name = "Draft_Array"
+ svg = ":/icons/" + icon_name
+ pix = QtGui.QPixmap(svg)
+ icon = QtGui.QIcon.fromTheme(icon_name, QtGui.QIcon(svg))
+ self.form.setWindowIcon(icon)
+ self.form.label_icon.setPixmap(pix.scaled(32, 32))
+
+ start_x = _Quantity(100.0, App.Units.Length)
+ start_y = start_x
+ start_z = start_x
+ start_zero = _Quantity(0.0, App.Units.Length)
+ length_unit = start_x.getUserPreferred()[2]
+
+ self.form.input_X_x.setProperty('rawValue', start_x.Value)
+ self.form.input_X_x.setProperty('unit', length_unit)
+ self.form.input_X_y.setProperty('rawValue', start_zero.Value)
+ self.form.input_X_y.setProperty('unit', length_unit)
+ self.form.input_X_z.setProperty('rawValue', start_zero.Value)
+ self.form.input_X_z.setProperty('unit', length_unit)
+
+ self.form.input_Y_x.setProperty('rawValue', start_zero.Value)
+ self.form.input_Y_x.setProperty('unit', length_unit)
+ self.form.input_Y_y.setProperty('rawValue', start_y.Value)
+ self.form.input_Y_y.setProperty('unit', length_unit)
+ self.form.input_Y_z.setProperty('rawValue', start_zero.Value)
+ self.form.input_Y_z.setProperty('unit', length_unit)
+
+ self.form.input_Z_x.setProperty('rawValue', start_zero.Value)
+ self.form.input_Z_x.setProperty('unit', length_unit)
+ self.form.input_Z_y.setProperty('rawValue', start_zero.Value)
+ self.form.input_Z_y.setProperty('unit', length_unit)
+ self.form.input_Z_z.setProperty('rawValue', start_z.Value)
+ self.form.input_Z_z.setProperty('unit', length_unit)
+
+ self.v_X = App.Vector(100, 0, 0)
+ self.v_Y = App.Vector(0, 100, 0)
+ self.v_Z = App.Vector(0, 0, 100)
+
+ # Old style for Qt4, avoid!
+ # QtCore.QObject.connect(self.form.button_reset,
+ # QtCore.SIGNAL("clicked()"),
+ # self.reset_point)
+ # New style for Qt5
+ self.form.button_reset_X.clicked.connect(lambda: self.reset_v("X"))
+ self.form.button_reset_Y.clicked.connect(lambda: self.reset_v("Y"))
+ self.form.button_reset_Z.clicked.connect(lambda: self.reset_v("Z"))
+
+ self.n_X = 2
+ self.n_Y = 2
+ self.n_Z = 1
+
+ self.form.spinbox_n_X.setValue(self.n_X)
+ self.form.spinbox_n_Y.setValue(self.n_Y)
+ self.form.spinbox_n_Z.setValue(self.n_Z)
+
+ self.valid_input = False
+
+ # When the checkbox changes, change the fuse value
+ self.fuse = False
+ self.form.checkbox_fuse.stateChanged.connect(self.set_fuse)
+
+ self.use_link = False
+ self.form.checkbox_link.stateChanged.connect(self.set_link)
+
+ def accept(self):
+ """Execute when clicking the OK button."""
+ selection = Gui.Selection.getSelection()
+ n_X = self.form.spinbox_n_X.value()
+ n_Y = self.form.spinbox_n_Y.value()
+ n_Z = self.form.spinbox_n_Z.value()
+ self.valid_input = self.validate_input(selection,
+ n_X,
+ n_Y,
+ n_Z)
+ if self.valid_input:
+ self.create_object(selection)
+ self.print_messages(selection)
+ self.finish()
+
+ def validate_input(self, selection, n_X, n_Y, n_Z):
+ """Check that the input is valid."""
+ if not selection:
+ _Wrn(_tr("At least one element must be selected"))
+ return False
+ if n_X < 1 or n_Y < 1 or n_Z < 1:
+ _Wrn(_tr("Number of elements must be at least 1"))
+ return False
+ # Todo: each of the elements of the selection could be tested,
+ # not only the first one.
+ obj = selection[0]
+ if obj.isDerivedFrom("App::FeaturePython"):
+ _Wrn(_tr("Selection is not suitable for array"))
+ _Wrn(_tr("Object:") + " {0} ({1})".format(obj.Label, obj.TypeId))
+ return False
+ return True
+
+ def create_object(self, selection):
+ """Create the actual object."""
+ self.v_X, self.v_Y, self.v_Z = self.set_intervals()
+ self.n_X, self.n_Y, self.n_Z = self.set_numbers()
+
+ if len(selection) == 1:
+ sel_obj = selection[0]
+ else:
+ # This can be changed so a compound of multiple
+ # selected objects is produced
+ sel_obj = selection[0]
+
+ self.fuse = self.form.checkbox_fuse.isChecked()
+ self.use_link = self.form.checkbox_link.isChecked()
+
+ # This creates the object immediately
+ # obj = Draft.makeArray(sel_obj,
+ # self.v_X, self.v_Y, self.v_Z,
+ # self.n_X, self.n_Y, self.n_Z)
+ # if obj:
+ # obj.Fuse = self.fuse
+
+ # Instead, we build the commands to execute through the parent
+ # of this class, the GuiCommand.
+ # This is needed to schedule geometry manipulation
+ # that would crash Coin3D if done in the event callback.
+ _cmd = "obj = Draft.makeArray("
+ _cmd += "FreeCAD.ActiveDocument." + sel_obj.Name + ", "
+ _cmd += "arg1=" + DraftVecUtils.toString(self.v_X) + ", "
+ _cmd += "arg2=" + DraftVecUtils.toString(self.v_Y) + ", "
+ _cmd += "arg3=" + DraftVecUtils.toString(self.v_Z) + ", "
+ _cmd += "arg4=" + str(self.n_X) + ", "
+ _cmd += "arg5=" + str(self.n_Y) + ", "
+ _cmd += "arg6=" + str(self.n_Z) + ", "
+ _cmd += "useLink=" + str(self.use_link)
+ _cmd += ")"
+
+ _cmd_list = ["FreeCADGui.addModule('Draft')",
+ _cmd,
+ "obj.Fuse = " + str(self.fuse),
+ "Draft.autogroup(obj)",
+ "FreeCAD.ActiveDocument.recompute()"]
+ self.source_command.commit("Ortho array", _cmd_list)
+
+ def set_numbers(self):
+ """Assign the number of elements."""
+ self.n_X = self.form.spinbox_n_X.value()
+ self.n_Y = self.form.spinbox_n_Y.value()
+ self.n_Z = self.form.spinbox_n_Z.value()
+ return self.n_X, self.n_Y, self.n_Z
+
+ def set_intervals(self):
+ """Assign the interval vectors."""
+ v_X_x_str = self.form.input_X_x.text()
+ v_X_y_str = self.form.input_X_y.text()
+ v_X_z_str = self.form.input_X_z.text()
+ self.v_X = App.Vector(_Quantity(v_X_x_str).Value,
+ _Quantity(v_X_y_str).Value,
+ _Quantity(v_X_z_str).Value)
+
+ v_Y_x_str = self.form.input_Y_x.text()
+ v_Y_y_str = self.form.input_Y_y.text()
+ v_Y_z_str = self.form.input_Y_z.text()
+ self.v_Y = App.Vector(_Quantity(v_Y_x_str).Value,
+ _Quantity(v_Y_y_str).Value,
+ _Quantity(v_Y_z_str).Value)
+
+ v_Z_x_str = self.form.input_X_x.text()
+ v_Z_y_str = self.form.input_X_y.text()
+ v_Z_z_str = self.form.input_X_z.text()
+ self.v_Z = App.Vector(_Quantity(v_Z_x_str).Value,
+ _Quantity(v_Z_y_str).Value,
+ _Quantity(v_Z_z_str).Value)
+ return self.v_X, self.v_Y, self.v_Z
+
+ def reset_v(self, interval):
+ """Reset the interval to zero distance."""
+ if interval == "X":
+ self.form.input_X_x.setProperty('rawValue', 100)
+ self.form.input_X_y.setProperty('rawValue', 0)
+ self.form.input_X_z.setProperty('rawValue', 0)
+ _Msg(_tr("Interval X reset:")
+ + " ({0}, {1}, {2})".format(self.v_X.x,
+ self.v_X.y,
+ self.v_X.z))
+ elif interval == "Y":
+ self.form.input_Y_x.setProperty('rawValue', 0)
+ self.form.input_Y_y.setProperty('rawValue', 100)
+ self.form.input_Y_z.setProperty('rawValue', 0)
+ _Msg(_tr("Interval Y reset:")
+ + " ({0}, {1}, {2})".format(self.v_Y.x,
+ self.v_Y.y,
+ self.v_Y.z))
+ elif interval == "Z":
+ self.form.input_Z_x.setProperty('rawValue', 0)
+ self.form.input_Z_y.setProperty('rawValue', 0)
+ self.form.input_Z_z.setProperty('rawValue', 100)
+ _Msg(_tr("Interval Z reset:")
+ + " ({0}, {1}, {2})".format(self.v_Z.x,
+ self.v_Z.y,
+ self.v_Z.z))
+
+ self.n_X, self.n_Y, self.n_Z = self.set_intervals()
+
+ def print_fuse_state(self):
+ """Print the state translated."""
+ if self.fuse:
+ translated_state = QT_TRANSLATE_NOOP("Draft", "True")
+ else:
+ translated_state = QT_TRANSLATE_NOOP("Draft", "False")
+ _Msg(_tr("Fuse:") + " {}".format(translated_state))
+
+ def set_fuse(self):
+ """Run callback when the fuse checkbox changes."""
+ self.fuse = self.form.checkbox_fuse.isChecked()
+ self.print_fuse_state()
+
+ def print_link_state(self):
+ """Print the state translated."""
+ if self.use_link:
+ translated_state = QT_TRANSLATE_NOOP("Draft", "True")
+ else:
+ translated_state = QT_TRANSLATE_NOOP("Draft", "False")
+ _Msg(_tr("Use Link object:") + " {}".format(translated_state))
+
+ def set_link(self):
+ """Run callback when the link checkbox changes."""
+ self.use_link = self.form.checkbox_link.isChecked()
+ self.print_link_state()
+
+ def print_messages(self, selection):
+ """Print messages about the operation."""
+ if len(selection) == 1:
+ sel_obj = selection[0]
+ else:
+ # This can be changed so a compound of multiple
+ # selected objects is produced
+ sel_obj = selection[0]
+ _Msg("{}".format(16*"-"))
+ _Msg("{}".format(self.name))
+ _Msg(_tr("Object:") + " {}".format(sel_obj.Label))
+ _Msg(_tr("Number of X elements:") + " {}".format(self.n_X))
+ _Msg(_tr("Interval X:")
+ + " ({0}, {1}, {2})".format(self.v_X.x,
+ self.v_X.y,
+ self.v_X.z))
+ _Msg(_tr("Number of Y elements:") + " {}".format(self.n_Y))
+ _Msg(_tr("Interval Y:")
+ + " ({0}, {1}, {2})".format(self.v_Y.x,
+ self.v_Y.y,
+ self.v_Y.z))
+ _Msg(_tr("Number of Z elements:") + " {}".format(self.n_Z))
+ _Msg(_tr("Interval Z:")
+ + " ({0}, {1}, {2})".format(self.v_Z.x,
+ self.v_Z.y,
+ self.v_Z.z))
+ self.print_fuse_state()
+ self.print_link_state()
+
+ def reject(self):
+ """Run when clicking the Cancel button."""
+ _Msg(_tr("Aborted:") + " {}".format(self.name))
+ self.finish()
+
+ def finish(self):
+ """Run at the end after OK or Cancel."""
+ # App.ActiveDocument.commitTransaction()
+ Gui.ActiveDocument.resetEdit()
+ # Runs the parent command to complete the call
+ self.source_command.completed()
diff --git a/src/Mod/Draft/draftviewproviders/view_orthoarray.py b/src/Mod/Draft/draftviewproviders/view_orthoarray.py
new file mode 100644
index 0000000000..461475a557
--- /dev/null
+++ b/src/Mod/Draft/draftviewproviders/view_orthoarray.py
@@ -0,0 +1,43 @@
+"""Provide the view provider code for Draft Array."""
+## @package view_orthoarray
+# \ingroup DRAFT
+# \brief Provide the view provider code for Draft Array.
+
+# ***************************************************************************
+# * (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 *
+# * *
+# ***************************************************************************
+
+import Draft
+import Draft_rc
+ViewProviderDraftArray = Draft._ViewProviderDraftArray
+
+# So the resource file doesn't trigger errors from code checkers (flake8)
+True if Draft_rc else False
+
+
+class ViewProviderOrthoArray(ViewProviderDraftArray):
+
+ def __init__(self, vobj):
+ super().__init__(self, vobj)
+
+ def getIcon(self):
+ return ":/icons/Draft_Array"