From 353e9a6228d981504fffdc270f908a3e4532cfce Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 25 Aug 2017 16:40:49 -0300 Subject: [PATCH] Draft: New UI for the Scale tool --- src/Mod/Draft/Draft.py | 23 ++++---- src/Mod/Draft/DraftGui.py | 89 +++++++++++++++++++++++++++++++ src/Mod/Draft/DraftTools.py | 103 ++++++++++++++---------------------- 3 files changed, 142 insertions(+), 73 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index e3a5f8ca2e..111ebe88f0 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1455,14 +1455,15 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy newobj = makeCopy(obj) else: newobj = obj - sh = obj.Shape.copy() - m = FreeCAD.Matrix() - m.scale(delta) - sh = sh.transformGeometry(m) - corr = Vector(center.x,center.y,center.z) - corr.scale(delta.x,delta.y,delta.z) - corr = (corr.sub(center)).negative() - sh.translate(corr) + if obj.isDerivedFrom("Part::Feature"): + sh = obj.Shape.copy() + m = FreeCAD.Matrix() + m.scale(delta) + sh = sh.transformGeometry(m) + corr = Vector(center.x,center.y,center.z) + corr.scale(delta.x,delta.y,delta.z) + corr = (corr.sub(center)).negative() + sh.translate(corr) if getType(obj) == "Rectangle": p = [] for v in sh.Vertexes: p.append(v.Point) @@ -1496,8 +1497,10 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy elif (obj.isDerivedFrom("Part::Feature")): newobj.Shape = sh elif (obj.TypeId == "App::Annotation"): - factor = delta.x * delta.y * delta.z * obj.ViewObject.FontSize.Value - obj.ViewObject.Fontsize = factor + factor = delta.y * obj.ViewObject.FontSize + newobj.ViewObject.FontSize = factor + d = obj.Position.sub(center) + newobj.Position = center.add(Vector(d.x*delta.x,d.y*delta.y,d.z*delta.z)) if copy: formatObject(newobj,obj) newobjlist.append(newobj) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 5be322cc4b..1322b23de5 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -2163,6 +2163,95 @@ class FacebinderTaskPanel: self.title.setText(QtGui.QApplication.translate("draft", "Facebinder elements", None)) +class ScaleTaskPanel: + + '''A Task Panel for the Scale tool''' + + def __init__(self): + self.sourceCmd = None + self.form = QtGui.QWidget() + layout = QtGui.QGridLayout(self.form) + self.xLabel = QtGui.QLabel() + layout.addWidget(self.xLabel,0,0,1,1) + self.xValue = QtGui.QDoubleSpinBox() + self.xValue.setDecimals(Draft.getParam("precision")) + self.xValue.setRange(.0000001,1000000.0) + self.xValue.setValue(1) + layout.addWidget(self.xValue,0,1,1,1) + self.yLabel = QtGui.QLabel() + layout.addWidget(self.yLabel,1,0,1,1) + self.yValue = QtGui.QDoubleSpinBox() + self.yValue.setDecimals(Draft.getParam("precision")) + self.yValue.setRange(.0000001,1000000.0) + self.yValue.setValue(1) + layout.addWidget(self.yValue,1,1,1,1) + self.zLabel = QtGui.QLabel() + layout.addWidget(self.zLabel,2,0,1,1) + self.zValue = QtGui.QDoubleSpinBox() + self.zValue.setDecimals(Draft.getParam("precision")) + self.zValue.setRange(.0000001,1000000.0) + self.zValue.setValue(1) + layout.addWidget(self.zValue,2,1,1,1) + self.lock = QtGui.QCheckBox() + layout.addWidget(self.lock,3,0,1,2) + self.relative = QtGui.QCheckBox() + layout.addWidget(self.relative,4,0,1,2) + self.rLabel = QtGui.QLabel() + layout.addWidget(self.rLabel,5,0,1,2) + self.isClone = QtGui.QRadioButton() + layout.addWidget(self.isClone,6,0,1,2) + self.isClone.setChecked(True) + self.isOriginal = QtGui.QRadioButton() + layout.addWidget(self.isOriginal,7,0,1,2) + self.isCopy = QtGui.QRadioButton() + layout.addWidget(self.isCopy,8,0,1,2) + QtCore.QObject.connect(self.xValue,QtCore.SIGNAL("valueChanged(double)"),self.setValue) + QtCore.QObject.connect(self.yValue,QtCore.SIGNAL("valueChanged(double)"),self.setValue) + QtCore.QObject.connect(self.zValue,QtCore.SIGNAL("valueChanged(double)"),self.setValue) + self.retranslateUi() + + def setValue(self,val=None): + if self.lock.isChecked(): + self.xValue.setValue(val) + self.yValue.setValue(val) + self.zValue.setValue(val) + if self.sourceCmd: + self.sourceCmd.scaleGhost(self.xValue.value(),self.yValue.value(),self.zValue.value(),self.relative.isChecked()) + + def retranslateUi(self,widget=None): + self.form.setWindowTitle(QtGui.QApplication.translate("Draft", "Scale", None)) + self.xLabel.setText(QtGui.QApplication.translate("Draft", "X factor", None)) + self.yLabel.setText(QtGui.QApplication.translate("Draft", "Y factor", None)) + self.zLabel.setText(QtGui.QApplication.translate("Draft", "Z factor", None)) + self.lock.setText(QtGui.QApplication.translate("Draft", "Uniform scaling", None)) + self.relative.setText(QtGui.QApplication.translate("Draft", "Working plane orientation", None)) + self.rLabel.setText(QtGui.QApplication.translate("Draft", "Result", None)) + self.isClone.setText(QtGui.QApplication.translate("Draft", "Create a clone", None)) + self.isOriginal.setText(QtGui.QApplication.translate("Draft", "Modify original", None)) + self.isCopy.setText(QtGui.QApplication.translate("Draft", "Create a copy", None)) + + def accept(self): + if self.sourceCmd: + x = self.xValue.value() + y = self.yValue.value() + z = self.zValue.value() + rel = self.relative.isChecked() + if self.isClone.isChecked(): + mod = 0 + elif self.isOriginal.isChecked(): + mod = 1 + else: + mod = 2 + self.sourceCmd.scale(x,y,z,rel,mod) + FreeCADGui.ActiveDocument.resetEdit() + return True + + def reject(self): + if self.sourceCmd: + self.sourceCmd.finish() + FreeCADGui.ActiveDocument.resetEdit() + return True + if not hasattr(FreeCADGui,"draftToolBar"): FreeCADGui.draftToolBar = DraftToolBar() #----End of Python Features Definitions----# diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index e1d3affc61..b3663e47f7 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -3594,12 +3594,20 @@ class Scale(Modifier): Modifier.finish(self) if self.ghost: self.ghost.finalize() - if cont and self.ui: - if self.ui.continueMode: - FreeCADGui.Selection.clearSelection() - self.Activated() - def scale(self,delta,copy=False): + def scale(self,x,y,z,rel,mode): + delta = Vector(x,y,z) + if rel: + delta = FreeCAD.DraftWorkingPlane.getGlobalCoords(delta) + if mode == 0: + copy = False + legacy = False + elif mode == 1: + copy = False + legacy = True + elif mode == 2: + copy = True + legacy = True "moving the real shapes" sel = '[' for o in self.sel: @@ -3608,14 +3616,22 @@ class Scale(Modifier): sel += 'FreeCAD.ActiveDocument.'+o.Name sel += ']' FreeCADGui.addModule("Draft") - if copy: - self.commit(translate("draft","Copy"), - ['Draft.scale('+sel+',delta='+DraftVecUtils.toString(delta)+',center='+DraftVecUtils.toString(self.node[0])+',copy='+str(copy)+')', - 'FreeCAD.ActiveDocument.recompute()']) - else: - self.commit(translate("draft","Scale"), - ['Draft.scale('+sel+',delta='+DraftVecUtils.toString(delta)+',center='+DraftVecUtils.toString(self.node[0])+',copy='+str(copy)+')', - 'FreeCAD.ActiveDocument.recompute()']) + self.commit(translate("draft","Copy"), + ['Draft.scale('+sel+',delta='+DraftVecUtils.toString(delta)+',center='+DraftVecUtils.toString(self.node[0])+',copy='+str(copy)+',legacy='+str(legacy)+')', + 'FreeCAD.ActiveDocument.recompute()']) + self.finish() + + def scaleGhost(self,x,y,z,rel): + delta = Vector(x,y,z) + if rel: + delta = FreeCAD.DraftWorkingPlane.getGlobalCoords(delta) + self.ghost.scale(delta) + # calculate a correction factor depending on the scaling center + corr = Vector(self.node[0].x,self.node[0].y,self.node[0].z) + corr.scale(delta.x,delta.y,delta.z) + corr = (corr.sub(self.node[0])).negative() + self.ghost.move(corr) + self.ghost.on() def action(self,arg): "scene event handler" @@ -3626,63 +3642,24 @@ class Scale(Modifier): if self.ghost: self.ghost.off() self.point,ctrlPoint,info = getPoint(self,arg,sym=True) - if (len(self.node) > 0): - last = self.node[len(self.node)-1] - delta = self.point.sub(last) - delta = FreeCAD.Vector(delta.x,delta.y,1) - if self.ghost: - self.ghost.scale(delta) - # calculate a correction factor depending on the scaling center - corr = Vector(self.node[0].x,self.node[0].y,self.node[0].z) - corr.scale(delta.x,delta.y,delta.z) - corr = (corr.sub(self.node[0])).negative() - self.ghost.move(corr) - self.ghost.on() - self.ui.zValue.setText("1") - if self.extendedCopy: - if not hasMod(arg,MODALT): self.finish() - redraw3DView() elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): if self.point: self.ui.redraw() - if (self.node == []): - self.node.append(self.point) - self.ui.isRelative.setChecked(True) - self.ui.isCopy.show() - if self.ghost: - self.ghost.on() - msg(translate("draft", "Pick scale factor:\n")) - else: - last = self.node[0] - delta = self.point.sub(last) - delta = FreeCAD.Vector(delta.x,delta.y,1) - if self.ui.isCopy.isChecked() or hasMod(arg,MODALT): - self.scale(delta,True) - else: - self.scale(delta) - if hasMod(arg,MODALT): - self.extendedCopy = True - else: - self.finish(cont=True) + self.numericInput(self.point.x,self.point.y,self.point.z) def numericInput(self,numx,numy,numz): - "this function gets called by the toolbar when valid x, y, and z have been entered there" + "this function gets called by the toolbar when a valid base point has been entered" self.point = Vector(numx,numy,numz) - if not self.node: - self.node.append(self.point) - self.ui.isRelative.show() - self.ui.isCopy.show() - if self.ghost: - self.ghost.on() - msg(translate("draft", "Pick scale factor:\n")) - else: - last = self.node[-1] - if self.ui.isCopy.isChecked(): - self.scale(self.point.sub(last),True) - else: - self.scale(self.point.sub(last)) - self.finish(cont=True) + self.node.append(self.point) + self.ui.offUi() + if self.call: + self.view.removeEventCallback("SoEvent",self.call) + task = DraftGui.ScaleTaskPanel() + task.sourceCmd = self + DraftGui.todo.delay(FreeCADGui.Control.showDialog,task) + if self.ghost: + self.ghost.on() class ToggleConstructionMode():