FreeCAD
233 строки · 9.7 Кб
1# ***************************************************************************
2# * (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> *
3# * (c) 2009, 2010 Ken Cline <cline@frii.com> *
4# * (c) 2020 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
5# * *
6# * This file is part of the FreeCAD CAx development system. *
7# * *
8# * This program is free software; you can redistribute it and/or modify *
9# * it under the terms of the GNU Lesser General Public License (LGPL) *
10# * as published by the Free Software Foundation; either version 2 of *
11# * the License, or (at your option) any later version. *
12# * for detail see the LICENCE text file. *
13# * *
14# * FreeCAD is distributed in the hope that it will be useful, *
15# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17# * GNU Library General Public License for more details. *
18# * *
19# * You should have received a copy of the GNU Library General Public *
20# * License along with FreeCAD; if not, write to the Free Software *
21# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
22# * USA *
23# * *
24# ***************************************************************************
25"""Provides GUI tools to create Label objects.
26
27Labels are similar to text annotations but include a leader line
28and an arrow in order to point to an object and indicate some of its
29properties.
30"""
31## @package gui_labels
32# \ingroup draftguitools
33# \brief Provides GUI tools to create Label objects.
34
35## \addtogroup draftguitools
36# @{
37import math
38from PySide.QtCore import QT_TRANSLATE_NOOP
39
40import FreeCAD as App
41import FreeCADGui as Gui
42import Draft_rc
43import DraftVecUtils
44from draftguitools import gui_base_original
45from draftguitools import gui_tool_utils
46from draftguitools import gui_trackers as trackers
47from draftutils import params
48from draftutils.messages import _toolmsg
49from draftutils.translate import translate
50
51# The module is used to prevent complaints from code checkers (flake8)
52True if Draft_rc.__name__ else False
53
54
55class Label(gui_base_original.Creator):
56"""Gui Command for the Label tool."""
57
58def GetResources(self):
59"""Set icon, menu and tooltip."""
60
61return {'Pixmap': 'Draft_Label',
62'Accel': "D, L",
63'MenuText': QT_TRANSLATE_NOOP("Draft_Label", "Label"),
64'ToolTip': QT_TRANSLATE_NOOP("Draft_Label", "Creates a label, optionally attached to a selected object or subelement.\n\nFirst select a vertex, an edge, or a face of an object, then call this command,\nand then set the position of the leader line and the textual label.\nThe label will be able to display information about this object, and about the selected subelement,\nif any.\n\nIf many objects or many subelements are selected, only the first one in each case\nwill be used to provide information to the label.")}
65
66def Activated(self):
67"""Execute when the command is called."""
68super().Activated(name="Label")
69self.ghost = None
70self.labeltype = params.get_param("labeltype")
71self.sel = Gui.Selection.getSelectionEx()
72if self.sel:
73self.sel = self.sel[0]
74self.ui.labelUi(title=translate("draft",self.featureName), callback=self.setmode)
75self.ui.xValue.setFocus()
76self.ui.xValue.selectAll()
77self.ghost = trackers.lineTracker()
78self.call = self.view.addEventCallback("SoEvent", self.action)
79_toolmsg(translate("draft", "Pick target point"))
80self.ui.isCopy.hide()
81
82def setmode(self, i):
83"""Set the type of label, if it is associated to an object."""
84from draftobjects.label import get_label_types
85self.labeltype = get_label_types()[i]
86params.set_param("labeltype", self.labeltype)
87
88def finish(self, cont=False):
89"""Finish the command."""
90self.end_callbacks(self.call)
91if self.ghost:
92self.ghost.finalize()
93super().finish()
94
95def create(self):
96"""Create the actual object."""
97if len(self.node) == 3:
98targetpoint = self.node[0]
99basepoint = self.node[2]
100v = self.node[2].sub(self.node[1])
101dist = v.Length
102h = self.wp.u
103n = self.wp.axis
104r = self.wp.get_placement().Rotation
105
106if abs(DraftVecUtils.angle(v, h, n)) <= math.pi/4:
107direction = "Horizontal"
108dist = -dist
109elif abs(DraftVecUtils.angle(v, h, n)) >= math.pi*3/4:
110direction = "Horizontal"
111elif DraftVecUtils.angle(v, h, n) > 0:
112direction = "Vertical"
113else:
114direction = "Vertical"
115dist = -dist
116
117tp = DraftVecUtils.toString(targetpoint)
118sel = None
119if self.sel:
120sel = "FreeCAD.ActiveDocument." + self.sel.Object.Name
121
122if self.sel.SubElementNames:
123sub = "'" + self.sel.SubElementNames[0] + "'"
124else:
125sub = "None"
126
127pl = "FreeCAD.Placement"
128pl += "("
129pl += DraftVecUtils.toString(basepoint) + ", "
130pl += "FreeCAD.Rotation" + str(r.Q)
131pl += ")"
132
133Gui.addModule("Draft")
134_cmd = "Draft.make_label"
135_cmd += "("
136_cmd += "target_point=" + tp + ", "
137_cmd += "placement=" + pl + ", "
138if sel:
139_cmd += "target_object=" + sel + ", "
140_cmd += "subelements=" + sub + ", "
141_cmd += "label_type=" + "'" + self.labeltype + "'" + ", "
142# _cmd += "custom_text=" + "'Label'" + ", "
143_cmd += "direction=" + "'" + direction + "'" + ", "
144_cmd += "distance=" + str(dist)
145_cmd += ")"
146
147# Commit the creation instructions through the parent class,
148# the Creator class
149_cmd_list = ['_label_ = ' + _cmd,
150'Draft.autogroup(_label_)',
151'FreeCAD.ActiveDocument.recompute()']
152self.commit(translate("draft", "Create Label"),
153_cmd_list)
154self.finish()
155
156def action(self, arg):
157"""Handle the 3D scene events.
158
159This is installed as an EventCallback in the Inventor view.
160
161Parameters
162----------
163arg: dict
164Dictionary with strings that indicates the type of event received
165from the 3D view.
166"""
167if arg["Type"] == "SoKeyboardEvent":
168if arg["Key"] == "ESCAPE":
169self.finish()
170elif arg["Type"] == "SoLocation2Event":
171if hasattr(Gui, "Snapper"):
172Gui.Snapper.affinity = None # don't keep affinity
173if len(self.node) == 2:
174gui_tool_utils.setMod(arg, gui_tool_utils.get_mod_constrain_key(), True)
175self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg)
176gui_tool_utils.redraw3DView()
177elif arg["Type"] == "SoMouseButtonEvent":
178if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
179if self.point:
180self.ui.redraw()
181if not self.node:
182# first click
183self.node.append(self.point)
184self.ui.isRelative.show()
185_toolmsg(translate("draft",
186"Pick endpoint of leader line"))
187if self.planetrack:
188self.planetrack.set(self.point)
189elif len(self.node) == 1:
190# second click
191self.node.append(self.point)
192if self.ghost:
193self.ghost.p1(self.node[0])
194self.ghost.p2(self.node[1])
195self.ghost.on()
196_toolmsg(translate("draft", "Pick text position"))
197else:
198# third click
199self.node.append(self.point)
200self.create()
201
202def numericInput(self, numx, numy, numz):
203"""Validate the entry fields in the user interface.
204
205This function is called by the toolbar or taskpanel interface
206when valid x, y, and z have been entered in the input fields.
207"""
208self.point = App.Vector(numx, numy, numz)
209if not self.node:
210# first click
211self.node.append(self.point)
212self.ui.isRelative.show()
213_toolmsg(translate("draft", "Pick endpoint of leader line"))
214if self.planetrack:
215self.planetrack.set(self.point)
216elif len(self.node) == 1:
217# second click
218self.node.append(self.point)
219if self.ghost:
220self.ghost.p1(self.node[0])
221self.ghost.p2(self.node[1])
222self.ghost.on()
223_toolmsg(translate("draft", "Pick text position"))
224else:
225# third click
226self.node.append(self.point)
227self.create()
228
229
230Draft_Label = Label
231Gui.addCommand('Draft_Label', Label())
232
233## @}
234