Draft: add new command for Draft CircularArray

Added object, viewprovider, icon; gui command definition, task panel,
add command to InitGui; add callbacks, and delay system.
This commit is contained in:
vocx-fc
2019-10-08 22:27:40 -05:00
committed by Yorik van Havre
parent b1189aef6e
commit 5143369fc9
9 changed files with 1613 additions and 1 deletions

View File

@@ -49,22 +49,26 @@ SET(Draft_tests
SET(Draft_objects
draftobjects/__init__.py
draftobjects/circulararray.py
draftobjects/polararray.py
)
SET(Draft_view_providers
draftviewproviders/__init__.py
draftviewproviders/view_circulararray.py
draftviewproviders/view_polararray.py
)
SET(Draft_GUI_tools
draftguitools/__init__.py
draftguitools/gui_base.py
draftguitools/gui_circulararray.py
draftguitools/gui_polararray.py
)
SET(Draft_task_panels
drafttaskpanels/__init__.py
drafttaskpanels/task_circulararray.py
drafttaskpanels/task_polararray.py
)

View File

@@ -65,6 +65,7 @@ class DraftWorkbench(Workbench):
try:
import os, Draft_rc, DraftTools, DraftGui, DraftFillet
from DraftTools import translate
from draftguitools import gui_circulararray
from draftguitools import gui_polararray
FreeCADGui.addLanguagePath(":/translations")
FreeCADGui.addIconPath(":/icons")
@@ -86,7 +87,7 @@ class DraftWorkbench(Workbench):
"Draft_WireToBSpline", "Draft_AddPoint",
"Draft_DelPoint", "Draft_Shape2DView",
"Draft_Draft2Sketch", "Draft_Array", "Draft_LinkArray",
"Draft_PolarArray",
"Draft_PolarArray", "Draft_CircularArray",
"Draft_PathArray", "Draft_PathLinkArray", "Draft_PointArray", "Draft_Clone",
"Draft_Drawing", "Draft_Mirror", "Draft_Stretch"]
self.treecmdList = ["Draft_ApplyStyle", "Draft_ToggleDisplayMode",

View File

@@ -16,6 +16,7 @@
<file>icons/Draft_BezTanNode.svg</file>
<file>icons/Draft_BSpline.svg</file>
<file>icons/Draft_Circle.svg</file>
<file>icons/Draft_CircularArray.svg</file>
<file>icons/Draft_Clone.svg</file>
<file>icons/Draft_Construction.svg</file>
<file>icons/Draft_CubicBezCurve.svg</file>
@@ -149,6 +150,7 @@
<file>ui/preferences-dxf.ui</file>
<file>ui/preferences-oca.ui</file>
<file>ui/preferences-svg.ui</file>
<file>ui/TaskPanel_CircularArray.ui</file>
<file>ui/TaskPanel_PolarArray.ui</file>
<file>ui/TaskSelectPlane.ui</file>
<file>ui/TaskShapeString.ui</file>

View File

@@ -0,0 +1,667 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg5821"
sodipodi:version="0.32"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="Draft_CircularArray.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/user/Downloads/cad/mystuff/icons/Draft_wb_primitives/Draft_Array/Draft_Array_Ortho_16px.png"
inkscape:export-xdpi="22.5"
inkscape:export-ydpi="22.5">
<defs
id="defs5823">
<linearGradient
inkscape:collect="always"
id="linearGradient6349">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop6351" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop6353" />
</linearGradient>
<linearGradient
id="linearGradient3377">
<stop
style="stop-color:#0019a3;stop-opacity:1;"
offset="0"
id="stop3379" />
<stop
style="stop-color:#0069ff;stop-opacity:1;"
offset="1"
id="stop3381" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="linearGradient3383"
x1="901.1875"
y1="1190.875"
x2="1267.9062"
y2="1190.875"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1,0,0,1,2199.356,0)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective5829" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient6349"
id="radialGradient6355"
cx="1103.6399"
cy="1424.4465"
fx="1103.6399"
fy="1424.4465"
r="194.40614"
gradientTransform="matrix(-1.4307499,-1.3605156e-7,-1.202713e-8,0.1264801,2674.7488,1244.2826)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient3791-6">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3793-7" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3795-5" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3791-6"
id="linearGradient3820"
x1="939.98767"
y1="1097.5122"
x2="893.2572"
y2="989.77716"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient3791-0">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3793-6" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3795-2" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3791-0"
id="linearGradient3896"
x1="939.98767"
y1="1097.5122"
x2="893.2572"
y2="989.77716"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient3791-2">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3793-9" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3795-3" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3791-2"
id="linearGradient3896-1"
x1="939.98767"
y1="1097.5122"
x2="893.2572"
y2="989.77716"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3836">
<stop
id="stop3838"
offset="0"
style="stop-color:#3465a4;stop-opacity:1;" />
<stop
id="stop3840"
offset="1"
style="stop-color:#729fcf;stop-opacity:1;" />
</linearGradient>
<inkscape:perspective
id="perspective3620"
inkscape:persp3d-origin="32 : 21.333333 : 1"
inkscape:vp_z="64 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 32 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective3588" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective3692" />
<linearGradient
id="linearGradient3144-6">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop3146-9" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop3148-2" />
</linearGradient>
<radialGradient
r="34.345188"
fy="672.79736"
fx="225.26402"
cy="672.79736"
cx="225.26402"
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
gradientUnits="userSpaceOnUse"
id="radialGradient3688"
xlink:href="#linearGradient3144-6"
inkscape:collect="always" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective3805" />
<linearGradient
id="linearGradient3864-0-0">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-5-7" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-7-6" />
</linearGradient>
<linearGradient
id="linearGradient3377-3">
<stop
style="stop-color:#ffaa00;stop-opacity:1;"
offset="0"
id="stop3379-6" />
<stop
style="stop-color:#faff2b;stop-opacity:1;"
offset="1"
id="stop3381-7" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective3902" />
<linearGradient
id="linearGradient5048">
<stop
id="stop5050"
offset="0"
style="stop-color:black;stop-opacity:0;" />
<stop
style="stop-color:black;stop-opacity:1;"
offset="0.5"
id="stop5056" />
<stop
id="stop5052"
offset="1"
style="stop-color:black;stop-opacity:0;" />
</linearGradient>
<radialGradient
id="aigrd2"
cx="20.892099"
cy="114.5684"
r="5.256"
fx="20.892099"
fy="114.5684"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#F0F0F0"
id="stop15566" />
<stop
offset="1.0000000"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
id="stop15568" />
</radialGradient>
<radialGradient
id="aigrd3"
cx="20.892099"
cy="64.567902"
r="5.257"
fx="20.892099"
fy="64.567902"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#F0F0F0"
id="stop15573" />
<stop
offset="1.0000000"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
id="stop15575" />
</radialGradient>
<linearGradient
id="linearGradient15662">
<stop
id="stop15664"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop15666"
offset="1.0000000"
style="stop-color:#f8f8f8;stop-opacity:1.0000000;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient259"
id="radialGradient4452"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.96049297,0,0,1.041132,-52.144249,-702.33158)"
cx="33.966679"
cy="35.736916"
fx="33.966679"
fy="35.736916"
r="86.70845" />
<linearGradient
id="linearGradient259">
<stop
id="stop260"
offset="0.0000000"
style="stop-color:#fafafa;stop-opacity:1.0000000;" />
<stop
id="stop261"
offset="1.0000000"
style="stop-color:#bbbbbb;stop-opacity:1.0000000;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient269"
id="radialGradient4454"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.96827297,0,0,1.032767,-48.790699,-701.68513)"
cx="8.824419"
cy="3.7561285"
fx="8.824419"
fy="3.7561285"
r="37.751713" />
<linearGradient
id="linearGradient269">
<stop
id="stop270"
offset="0.0000000"
style="stop-color:#a3a3a3;stop-opacity:1.0000000;" />
<stop
id="stop271"
offset="1.0000000"
style="stop-color:#4c4c4c;stop-opacity:1.0000000;" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective4947" />
<linearGradient
id="linearGradient4095">
<stop
id="stop4097"
offset="0"
style="stop-color:#005bff;stop-opacity:1;" />
<stop
id="stop4099"
offset="1"
style="stop-color:#c1e3f7;stop-opacity:1;" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective5027" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective5076" />
<linearGradient
gradientTransform="matrix(0.94231826,0,0,0.94231826,23.727549,8.8262536)"
gradientUnits="userSpaceOnUse"
y2="140.22731"
x2="434.73947"
y1="185.1304"
x1="394.15784"
id="linearGradient4253"
xlink:href="#linearGradient4247"
inkscape:collect="always" />
<linearGradient
id="linearGradient4247">
<stop
id="stop4249"
offset="0"
style="stop-color:#2e8207;stop-opacity:1;" />
<stop
id="stop4251"
offset="1"
style="stop-color:#52ff00;stop-opacity:1;" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective5141" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective5225" />
<linearGradient
y2="485.54004"
x2="54.509644"
y1="453.55045"
x1="11.390151"
gradientTransform="matrix(1.050705,0.0195272,0.0195272,1.0567846,61.906432,41.415953)"
gradientUnits="userSpaceOnUse"
id="linearGradient3922"
xlink:href="#linearGradient3836"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3836"
id="linearGradient1217"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.050705,0.0195272,0.0195272,1.0567846,61.906432,41.415953)"
x1="11.390151"
y1="453.55045"
x2="54.509644"
y2="485.54004" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3836"
id="linearGradient1233"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.050705,0.0195272,0.0195272,1.0567846,61.906432,41.415953)"
x1="11.390151"
y1="453.55045"
x2="54.509644"
y2="485.54004" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3836"
id="linearGradient1241"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.050705,0.0195272,0.0195272,1.0567846,61.906432,41.415953)"
x1="11.390151"
y1="453.55045"
x2="54.509644"
y2="485.54004" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3836"
id="linearGradient1259"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.050705,0.0195272,0.0195272,1.0567846,61.906432,41.415953)"
x1="11.390151"
y1="453.55045"
x2="54.509644"
y2="485.54004" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3836"
id="linearGradient4972"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.050705,0.0195272,0.0195272,1.0567846,61.906432,41.415953)"
x1="11.390151"
y1="453.55045"
x2="54.509644"
y2="485.54004" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3836"
id="linearGradient4980"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.050705,0.0195272,0.0195272,1.0567846,61.906432,41.415953)"
x1="11.390151"
y1="453.55045"
x2="54.509644"
y2="485.54004" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="10.299484"
inkscape:cx="25.584457"
inkscape:cy="28.799058"
inkscape:current-layer="g3360"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1853"
inkscape:window-height="1025"
inkscape:window-x="1433"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-global="true"
inkscape:snap-bbox="true">
<inkscape:grid
type="xygrid"
id="grid3010"
units="px"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="1"
spacingy="1"
originx="0"
originy="0" />
</sodipodi:namedview>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3360"
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
inkscape:export-xdpi="3.2478156"
inkscape:export-ydpi="3.2478156"
transform="matrix(0.1367863,0,0,0.1367863,-119.15519,-134.86962)">
<g
transform="matrix(-1.0281913,-0.88047731,0.88051744,-1.0281444,734.46171,1854.2651)"
id="g3906"
style="stroke:#3465a4;stroke-width:0.8096711">
<path
inkscape:connector-curvature="0"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:10.80131626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4250"
d="m 147.07465,535.89484 a 48.571431,48.571431 0 1 1 -97.14285,0 48.571431,48.571431 0 1 1 97.14285,0 z" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient3922);fill-opacity:1;stroke:#729fcf;stroke-width:10.80131435;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4250-7"
d="m 136.22359,535.86575 a 37.80547,37.803747 49.467268 1 1 -75.60894,-0.002 37.80547,37.803747 49.467268 0 1 75.60894,0.002 z" />
</g>
<g
transform="matrix(-1.0281913,-0.88047731,0.88051744,-1.0281444,891.57365,1854.2651)"
id="g1215"
style="stroke:#3465a4;stroke-width:0.8096711">
<path
inkscape:connector-curvature="0"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:10.80131626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1211"
d="m 147.07465,535.89484 a 48.571431,48.571431 0 1 1 -97.14285,0 48.571431,48.571431 0 1 1 97.14285,0 z" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient1217);fill-opacity:1;stroke:#729fcf;stroke-width:10.80131435;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1213"
d="m 136.22359,535.86575 a 37.80547,37.803747 49.467268 1 1 -75.60894,-0.002 37.80547,37.803747 49.467268 0 1 75.60894,0.002 z" />
</g>
<g
transform="matrix(-1.0281913,-0.88047731,0.88051744,-1.0281444,650.32142,1707.8349)"
id="g1231"
style="stroke:#3465a4;stroke-width:0.8096711">
<path
inkscape:connector-curvature="0"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:10.80131626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1227"
d="m 147.07465,535.89484 a 48.571431,48.571431 0 1 1 -97.14285,0 48.571431,48.571431 0 1 1 97.14285,0 z" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient1233);fill-opacity:1;stroke:#729fcf;stroke-width:10.80131435;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1229"
d="m 136.22359,535.86575 a 37.80547,37.803747 49.467268 1 1 -75.60894,-0.002 37.80547,37.803747 49.467268 0 1 75.60894,0.002 z" />
</g>
<g
style="stroke:#3465a4;stroke-width:0.8096711"
id="g1239"
transform="matrix(-1.0281913,-0.88047731,0.88051744,-1.0281444,650.32142,2007.5725)">
<path
d="m 147.07465,535.89484 a 48.571431,48.571431 0 1 1 -97.14285,0 48.571431,48.571431 0 1 1 97.14285,0 z"
id="path1235"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:10.80131626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
d="m 136.22359,535.86575 a 37.80547,37.803747 49.467268 1 1 -75.60894,-0.002 37.80547,37.803747 49.467268 0 1 75.60894,0.002 z"
id="path1237"
style="fill:url(#linearGradient1241);fill-opacity:1;stroke:#729fcf;stroke-width:10.80131435;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
</g>
<g
style="stroke:#3465a4;stroke-width:0.8096711"
id="g1257"
transform="matrix(-1.0281913,-0.88047731,0.88051744,-1.0281444,577.21468,1854.2651)">
<path
d="m 147.07465,535.89484 a 48.571431,48.571431 0 1 1 -97.14285,0 48.571431,48.571431 0 1 1 97.14285,0 z"
id="path1253"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:10.80131626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
d="m 136.22359,535.86575 a 37.80547,37.803747 49.467268 1 1 -75.60894,-0.002 37.80547,37.803747 49.467268 0 1 75.60894,0.002 z"
id="path1255"
style="fill:url(#linearGradient1259);fill-opacity:1;stroke:#729fcf;stroke-width:10.80131435;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
</g>
<g
style="stroke:#3465a4;stroke-width:0.8096711"
id="g4970"
transform="matrix(-1.0281913,-0.88047731,0.88051744,-1.0281444,818.46691,1707.8349)">
<path
d="m 147.07465,535.89484 a 48.571431,48.571431 0 1 1 -97.14285,0 48.571431,48.571431 0 1 1 97.14285,0 z"
id="path4966"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:10.80131626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
d="m 136.22359,535.86575 a 37.80547,37.803747 49.467268 1 1 -75.60894,-0.002 37.80547,37.803747 49.467268 0 1 75.60894,0.002 z"
id="path4968"
style="fill:url(#linearGradient4972);fill-opacity:1;stroke:#729fcf;stroke-width:10.80131435;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(-1.0281913,-0.88047731,0.88051744,-1.0281444,818.46691,2007.5725)"
id="g4978"
style="stroke:#3465a4;stroke-width:0.8096711">
<path
inkscape:connector-curvature="0"
style="fill:#3465a4;fill-opacity:1;stroke:#0b1521;stroke-width:10.80131626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4974"
d="m 147.07465,535.89484 a 48.571431,48.571431 0 1 1 -97.14285,0 48.571431,48.571431 0 1 1 97.14285,0 z" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient4980);fill-opacity:1;stroke:#729fcf;stroke-width:10.80131435;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4976"
d="m 136.22359,535.86575 a 37.80547,37.803747 49.467268 1 1 -75.60894,-0.002 37.80547,37.803747 49.467268 0 1 75.60894,0.002 z" />
</g>
</g>
</g>
<metadata
id="metadata3357">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Draft_Array</dc:title>
<cc:license
rdf:resource="" />
<dc:date>Sat Dec 10 18:31:32 2011 +0000</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[yorikvanhavre]</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Draft/Resources/icons/Draft_Array.svg</dc:identifier>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
<dc:description>Six rectangles in a 2 x 3 linear array</dc:description>
<dc:subject>
<rdf:Bag>
<rdf:li>rectangle</rdf:li>
<rdf:li>array</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,292 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DraftCircularArrayTaskPanel</class>
<widget class="QWidget" name="DraftCircularArrayTaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>445</width>
<height>488</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Circular array</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QGroupBox" name="main_group">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="9" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QGroupBox" name="group_center">
<property name="toolTip">
<string>The coordinates of the point through which the axis of rotation passes.</string>
</property>
<property name="title">
<string>Center of rotation</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_c_z">
<property name="text">
<string>Z</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_c_x">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_c_y">
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::InputField" name="input_c_z">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::InputField" name="input_c_y">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::InputField" name="input_c_x">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="button_reset">
<property name="toolTip">
<string>Reset the coordinates of the center of rotation</string>
</property>
<property name="text">
<string>Reset point</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="6" column="0">
<layout class="QVBoxLayout" name="vertical_layout">
<item>
<widget class="QCheckBox" name="checkbox_fuse">
<property name="toolTip">
<string>If checked, the resulting objects in the array will be fused if they touch each other</string>
</property>
<property name="text">
<string>Fuse</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkbox_link">
<property name="toolTip">
<string>If checked, the resulting objects in the array will be Links instead of simple copies</string>
</property>
<property name="text">
<string>Use Links</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="grid_values">
<item row="1" column="0">
<widget class="QLabel" name="label_tan_distance">
<property name="toolTip">
<string>Distance from one element in the array to the next element in the same layer. It cannot be zero.</string>
</property>
<property name="text">
<string>Tangential distance</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::QuantitySpinBox" name="spinbox_tan_distance">
<property name="toolTip">
<string>Distance from one element in the array to the next element in the same layer. It cannot be zero.</string>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_r_distance">
<property name="toolTip">
<string>Distance from the center of the array to the outer layers</string>
</property>
<property name="text">
<string>Radial distance</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::QuantitySpinBox" name="spinbox_r_distance">
<property name="toolTip">
<string>Distance from the center of the array to the outer layers</string>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
<property name="value">
<double>200.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinbox_symmetry">
<property name="toolTip">
<string>Number that controls how the objects will be distributed</string>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spinbox_number">
<property name="toolTip">
<string>Number of circular arrays to create, including a copy of the original object. It must be at least 2.</string>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_number">
<property name="toolTip">
<string>Number of circular arrays to create, including a copy of the original object. It must be at least 2.</string>
</property>
<property name="text">
<string>Number of circular layers</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_symmetry">
<property name="toolTip">
<string>Number that controls how the objects will be distributed</string>
</property>
<property name="text">
<string>Symmetry</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_icon">
<property name="text">
<string>(Placeholder for the icon)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::InputField</class>
<extends>QLineEdit</extends>
<header>Gui/InputField.h</header>
</customwidget>
<customwidget>
<class>Gui::QuantitySpinBox</class>
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>spinbox_r_distance</tabstop>
<tabstop>spinbox_tan_distance</tabstop>
<tabstop>spinbox_number</tabstop>
<tabstop>spinbox_symmetry</tabstop>
<tabstop>input_c_x</tabstop>
<tabstop>input_c_y</tabstop>
<tabstop>input_c_z</tabstop>
<tabstop>button_reset</tabstop>
<tabstop>checkbox_fuse</tabstop>
<tabstop>checkbox_link</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,155 @@
"""This module provides the Draft CircularArray tool.
"""
## @package gui_circulararray
# \ingroup DRAFT
# \brief This module provides the Draft CircularArray tool.
# ***************************************************************************
# * (c) 2019 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
# * *
# * 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_circulararray
if App.GuiUp:
from PySide.QtCore import QT_TRANSLATE_NOOP
# import DraftTools
from DraftGui 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):
"""Function to 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.__name__ else False
class GuiCommandCircularArray(gui_base.GuiCommandBase):
"""Gui command for the CircularArray tool"""
def __init__(self):
super().__init__()
self.command_name = "CircularArray"
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):
_msg = ("Creates copies of a selected object, "
"and places the copies in a circular 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_CircularArray',
'MenuText': QT_TRANSLATE_NOOP("Draft", "Circular array"),
'ToolTip': QT_TRANSLATE_NOOP("Draft", _msg)}
return d
def Activated(self):
"""This is called when the command is executed.
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_circulararray.TaskPanelCircularArray()
# 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 move(self, event_cb):
"""This is a callback for when the mouse pointer moves in the 3D view.
It should automatically update the coordinates in the widgets
of the task panel.
"""
event = event_cb.getEvent()
mousepos = event.getPosition().getValue()
ctrl = event.wasCtrlDown()
self.point = Gui.Snapper.snap(mousepos, active=ctrl)
if self.ui:
self.ui.display_point(self.point)
def click(self, event_cb=None):
"""This is a 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):
"""This is called 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_CircularArray', GuiCommandCircularArray())

View File

@@ -0,0 +1,45 @@
"""This module provides the object code for Draft CircularArray.
"""
## @package circulararray
# \ingroup DRAFT
# \brief This module provides the object code for Draft CircularArray.
# ***************************************************************************
# * (c) 2019 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
# * *
# * 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_circular_array(obj,
r_distance=100, tan_distance=100,
axis=App.Vector(0, 0, 1), center=App.Vector(0, 0, 0),
number=2, symmetry=1,
use_link=False):
"""Create a circular array from the given object.
"""
obj = Draft.makeArray(obj,
arg1=r_distance, arg2=tan_distance,
arg3=axis, arg4=center, arg5=number, arg6=symmetry,
useLink=use_link)
return obj

View File

@@ -0,0 +1,402 @@
"""This module provides the task panel for the Draft CircularArray tool.
"""
## @package task_circulararray
# \ingroup DRAFT
# \brief This module provides the task panel code for the CircularArray tool.
# ***************************************************************************
# * (c) 2019 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
# * *
# * 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.QtCore as QtCore
import PySide.QtGui as QtGui
from PySide.QtCore import QT_TRANSLATE_NOOP
# import DraftTools
from DraftGui 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):
"""Function to 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.__name__ else False
class TaskPanelCircularArray:
"""TaskPanel code for the CircularArray 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.<name>`
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_CircularArray.ui"
self.form = Gui.PySideUic.loadUi(ui_file)
self.name = self.form.windowTitle()
icon_name = "Draft_CircularArray"
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_distance = _Quantity(1000.0, App.Units.Length)
distance_unit = start_distance.getUserPreferred()[2]
self.form.spinbox_r_distance.setProperty('rawValue',
2 * start_distance.Value)
self.form.spinbox_r_distance.setProperty('unit', distance_unit)
self.form.spinbox_tan_distance.setProperty('rawValue',
start_distance.Value)
self.form.spinbox_tan_distance.setProperty('unit', distance_unit)
self.r_distance = 2 * start_distance.Value
self.tan_distance = start_distance.Value
self.form.spinbox_number.setValue(3)
self.form.spinbox_symmetry.setValue(1)
self.number = self.form.spinbox_number.value()
self.symmetry = self.form.spinbox_symmetry.value()
self.axis = App.Vector(0, 0, 1)
start_point = _Quantity(0.0, App.Units.Length)
length_unit = start_point.getUserPreferred()[2]
self.form.input_c_x.setProperty('rawValue', start_point.Value)
self.form.input_c_x.setProperty('unit', length_unit)
self.form.input_c_y.setProperty('rawValue', start_point.Value)
self.form.input_c_y.setProperty('unit', length_unit)
self.form.input_c_z.setProperty('rawValue', start_point.Value)
self.form.input_c_z.setProperty('unit', length_unit)
self.valid_input = True
self.c_x_str = ""
self.c_y_str = ""
self.c_z_str = ""
self.center = App.Vector(0, 0, 0)
# Old style for Qt4
# QtCore.QObject.connect(self.form.button_reset,
# QtCore.SIGNAL("clicked()"),
# self.reset_point)
# New style for Qt5
self.form.button_reset.clicked.connect(self.reset_point)
# The mask is not used at the moment, but could be used in the future
# by a callback to restrict the coordinates of the pointer.
self.mask = ""
# When the checkbox changes, change the fuse value
self.fuse = False
QtCore.QObject.connect(self.form.checkbox_fuse,
QtCore.SIGNAL("stateChanged(int)"),
self.set_fuse)
self.use_link = False
QtCore.QObject.connect(self.form.checkbox_link,
QtCore.SIGNAL("stateChanged(int)"),
self.set_link)
def accept(self):
"""Function that executes when clicking the OK button"""
selection = Gui.Selection.getSelection()
self.number = self.form.spinbox_number.value()
tan_d_str = self.form.spinbox_tan_distance.text()
self.tan_distance = _Quantity(tan_d_str).Value
self.valid_input = self.validate_input(selection,
self.number,
self.tan_distance)
if self.valid_input:
self.create_object(selection)
self.print_messages(selection)
self.finish()
def validate_input(self, selection, number, tan_distance):
"""Check that the input is valid"""
if not selection:
_Wrn(_tr("At least one element must be selected"))
return False
if number < 2:
_Wrn(_tr("Number of elements must be at least 2"))
return False
# Todo: each of the elements of the selection could be tested,
# not only the first one.
if selection[0].isDerivedFrom("App::FeaturePython"):
_Wrn(_tr("Selection is not suitable for array"))
_Wrn(_tr("Object:") + " {}".format(selection[0].Label))
return False
if tan_distance == 0:
_Wrn(_tr("Tangential distance cannot be zero"))
return False
return True
def create_object(self, selection):
"""Create the actual object"""
r_d_str = self.form.spinbox_r_distance.text()
tan_d_str = self.form.spinbox_tan_distance.text()
self.r_distance = _Quantity(r_d_str).Value
self.tan_distance = _Quantity(tan_d_str).Value
self.number = self.form.spinbox_number.value()
self.symmetry = self.form.spinbox_symmetry.value()
self.center = self.set_point()
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.center, self.angle, self.number)
# 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=" + str(self.r_distance) + ", "
_cmd += "arg2=" + str(self.tan_distance) + ", "
_cmd += "arg3=" + DraftVecUtils.toString(self.axis) + ", "
_cmd += "arg4=" + DraftVecUtils.toString(self.center) + ", "
_cmd += "arg5=" + str(self.number) + ", "
_cmd += "arg6=" + str(self.symmetry) + ", "
_cmd += "useLink=" + str(self.use_link) + ")"
_cmd_list = ["FreeCADGui.addModule('Draft')",
_cmd,
"obj.Fuse = " + str(self.fuse),
"Draft.autogroup(obj)",
"FreeCAD.ActiveDocument.recompute()"]
self.source_command.commit("Circular array", _cmd_list)
def set_point(self):
"""Assign the values to the center"""
self.c_x_str = self.form.input_c_x.text()
self.c_y_str = self.form.input_c_y.text()
self.c_z_str = self.form.input_c_z.text()
center = App.Vector(_Quantity(self.c_x_str).Value,
_Quantity(self.c_y_str).Value,
_Quantity(self.c_z_str).Value)
return center
def reset_point(self):
"""Reset the point to the original distance"""
self.form.input_c_x.setProperty('rawValue', 0)
self.form.input_c_y.setProperty('rawValue', 0)
self.form.input_c_z.setProperty('rawValue', 0)
self.center = self.set_point()
_Msg(_tr("Center reset:")
+ " ({0}, {1}, {2})".format(self.center.x,
self.center.y,
self.center.z))
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):
"""This function is called 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):
"""This function is called when the fuse 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("Radial distance:") + " {}".format(self.r_distance))
_Msg(_tr("Tangential distance:") + " {}".format(self.tan_distance))
_Msg(_tr("Number of circular layers:") + " {}".format(self.number))
_Msg(_tr("Symmetry parameter:") + " {}".format(self.symmetry))
_Msg(_tr("Center of rotation:")
+ " ({0}, {1}, {2})".format(self.center.x,
self.center.y,
self.center.z))
self.print_fuse_state()
self.print_link_state()
def display_point(self, point=None, plane=None, mask=None):
"""Displays the coordinates in the x, y, and z widgets.
This function should be used in a Coin callback so that
the coordinate values are automatically updated when the
mouse pointer moves.
This was copied from `DraftGui.py` but needs to be improved
for this particular command.
point :
is a vector that arrives by the callback.
plane :
is a `WorkingPlane` instance, for example,
`App.DraftWorkingPlane`. It is not used at the moment,
but could be used to set up the grid.
mask :
is a string that specifies which coordinate is being
edited. It is used to restrict edition of a single coordinate.
It is not used at the moment but could be used with a callback.
"""
# Get the coordinates to display
dp = None
if point:
dp = point
# Set the widgets to the value of the mouse pointer.
#
# setProperty() is used if the widget is a FreeCAD widget like
# Gui::InputField or Gui::QuantitySpinBox, which are based on
# QLineEdit and QAbstractSpinBox.
#
# setText() is used to set the text inside the widget, this may be
# useful in some circumstances.
#
# The mask allows editing only one field, that is, only one coordinate.
# sbx = self.form.spinbox_c_x
# sby = self.form.spinbox_c_y
# sbz = self.form.spinbox_c_z
if dp:
if self.mask in ('y', 'z'):
# sbx.setText(displayExternal(dp.x, None, 'Length'))
self.form.input_c_x.setProperty('rawValue', dp.x)
else:
# sbx.setText(displayExternal(dp.x, None, 'Length'))
self.form.input_c_x.setProperty('rawValue', dp.x)
if self.mask in ('x', 'z'):
# sby.setText(displayExternal(dp.y, None, 'Length'))
self.form.input_c_y.setProperty('rawValue', dp.y)
else:
# sby.setText(displayExternal(dp.y, None, 'Length'))
self.form.input_c_y.setProperty('rawValue', dp.y)
if self.mask in ('x', 'y'):
# sbz.setText(displayExternal(dp.z, None, 'Length'))
self.form.input_c_z.setProperty('rawValue', dp.z)
else:
# sbz.setText(displayExternal(dp.z, None, 'Length'))
self.form.input_c_z.setProperty('rawValue', dp.z)
# Set masks
if (mask == "x") or (self.mask == "x"):
self.form.input_c_x.setEnabled(True)
self.form.input_c_y.setEnabled(False)
self.form.input_c_z.setEnabled(False)
self.set_focus("x")
elif (mask == "y") or (self.mask == "y"):
self.form.input_c_x.setEnabled(False)
self.form.input_c_y.setEnabled(True)
self.form.input_c_z.setEnabled(False)
self.set_focus("y")
elif (mask == "z") or (self.mask == "z"):
self.form.input_c_x.setEnabled(False)
self.form.input_c_y.setEnabled(False)
self.form.input_c_z.setEnabled(True)
self.set_focus("z")
else:
self.form.input_c_x.setEnabled(True)
self.form.input_c_y.setEnabled(True)
self.form.input_c_z.setEnabled(True)
self.set_focus()
def set_focus(self, key=None):
"""Set the focus on the widget that receives the key signal"""
if key is None or key == "x":
self.form.input_c_x.setFocus()
self.form.input_c_x.selectAll()
elif key == "y":
self.form.input_c_y.setFocus()
self.form.input_c_y.selectAll()
elif key == "z":
self.form.input_c_z.setFocus()
self.form.input_c_z.selectAll()
def reject(self):
"""Function that executes when clicking the Cancel button"""
_Msg(_tr("Aborted:") + " {}".format(self.name))
self.finish()
def finish(self):
"""Function that runs 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()

View File

@@ -0,0 +1,44 @@
"""This module provides the view provider code for Draft CircularArray.
"""
## @package view_circulararray
# \ingroup DRAFT
# \brief This module provides the view provider code for Draft CircularArray.
# ***************************************************************************
# * (c) 2019 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
# * *
# * 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.__name__ else False
class ViewProviderCircularArray(ViewProviderDraftArray):
def __init__(self, vobj):
super().__init__(self, vobj)
def getIcon(self):
return ":/icons/Draft_CircularArray"