1 /*
2 * Copyright (c) 2013 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "kis_tool_transform_config_widget.h"
20
21 #include <kis_icon.h>
22 #include "rotation_icons.h"
23 #include "kis_canvas2.h"
24 #include <KisSignalMapper.h>
25 #include "kis_liquify_properties.h"
26
27 #include "KisMainWindow.h"
28 #include "KisViewManager.h"
29 #include "kis_transform_utils.h"
30
31
sign(T x)32 template<typename T> inline T sign(T x) {
33 return x > 0 ? 1 : x == (T)0 ? 0 : -1;
34 }
35
36 const int KisToolTransformConfigWidget::DEFAULT_POINTS_PER_LINE = 3;
37
38
KisToolTransformConfigWidget(TransformTransactionProperties * transaction,KisCanvas2 * canvas,bool workRecursively,QWidget * parent)39 KisToolTransformConfigWidget::KisToolTransformConfigWidget(TransformTransactionProperties *transaction, KisCanvas2 *canvas, bool workRecursively, QWidget *parent)
40 : QWidget(parent),
41 m_transaction(transaction),
42 m_notificationsBlocked(0),
43 m_uiSlotsBlocked(0),
44 m_configChanged(false)
45 {
46 setupUi(this);
47 chkWorkRecursively->setIcon(KisIconUtils::loadIcon("krita_tool_transform_recursive"));
48 flipXButton->setIcon(KisIconUtils::loadIcon("transform_icons_mirror_x"));
49 flipYButton->setIcon(KisIconUtils::loadIcon("transform_icons_mirror_y"));
50 rotateCWButton->setIcon(KisIconUtils::loadIcon("transform_icons_rotate_cw"));
51 rotateCCWButton->setIcon(KisIconUtils::loadIcon("transform_icons_rotate_ccw"));
52
53 chkWorkRecursively->setChecked(workRecursively);
54 connect(chkWorkRecursively, SIGNAL(toggled(bool)), this, SIGNAL(sigRestartTransform()));
55
56 // Granularity can only be specified in the power of 2's
57 QStringList granularityValues{"4","8","16","32"};
58 changeGranularity->addItems(granularityValues);
59 changeGranularity->setCurrentIndex(1);
60 granularityPreview->addItems(granularityValues);
61 granularityPreview->setCurrentIndex(2);
62
63 connect(changeGranularity,SIGNAL(currentIndexChanged(QString)),
64 this,SLOT(slotGranularityChanged(QString)));
65 connect(granularityPreview, SIGNAL(currentIndexChanged(QString)),
66 this,SLOT(slotPreviewGranularityChanged(QString)));
67
68 // Init Filter combo
69 cmbFilter->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
70 cmbFilter->setCurrent("Bicubic");
71 cmbFilter->setToolTip(i18nc("@info:tooltip",
72 "<p>Select filtering mode:\n"
73 "<ul>"
74 "<li><b>Nearest neighbor</b> for pixel art. Does not produce new color.</li>"
75 "<li><b>Bilinear</b> for areas with uniform color to avoid artifacts.</li>"
76 "<li><b>Bicubic</b> for smoother results.</li>"
77 "<li><b>Lanczos3</b> for sharp results. May produce aerials.</li>"
78 "</ul></p>"));
79 connect(cmbFilter, SIGNAL(activated(KoID)),
80 this, SLOT(slotFilterChanged(KoID)));
81
82 // Init Warp Type combo
83 cmbWarpType->insertItem(KisWarpTransformWorker::AFFINE_TRANSFORM,i18n("Default (Affine)"));
84 cmbWarpType->insertItem(KisWarpTransformWorker::RIGID_TRANSFORM,i18n("Strong (Rigid)"));
85 cmbWarpType->insertItem(KisWarpTransformWorker::SIMILITUDE_TRANSFORM,i18n("Strongest (Similitude)"));
86 cmbWarpType->setCurrentIndex(KisWarpTransformWorker::AFFINE_TRANSFORM);
87 connect(cmbWarpType, SIGNAL(currentIndexChanged(int)), this, SLOT(slotWarpTypeChanged(int)));
88
89 // Init Rotation Center buttons
90 m_handleDir[0] = QPointF(1, 0);
91 m_handleDir[1] = QPointF(1, -1);
92 m_handleDir[2] = QPointF(0, -1);
93 m_handleDir[3] = QPointF(-1, -1);
94 m_handleDir[4] = QPointF(-1, 0);
95 m_handleDir[5] = QPointF(-1, 1);
96 m_handleDir[6] = QPointF(0, 1);
97 m_handleDir[7] = QPointF(1, 1);
98 m_handleDir[8] = QPointF(0, 0); // also add the center
99
100 m_rotationCenterButtons = new QButtonGroup(0);
101 // we set the ids to match m_handleDir
102 m_rotationCenterButtons->addButton(middleRightButton, 0);
103 m_rotationCenterButtons->addButton(topRightButton, 1);
104 m_rotationCenterButtons->addButton(middleTopButton, 2);
105 m_rotationCenterButtons->addButton(topLeftButton, 3);
106 m_rotationCenterButtons->addButton(middleLeftButton, 4);
107 m_rotationCenterButtons->addButton(bottomLeftButton, 5);
108 m_rotationCenterButtons->addButton(middleBottomButton, 6);
109 m_rotationCenterButtons->addButton(bottomRightButton, 7);
110 m_rotationCenterButtons->addButton(centerButton, 8);
111
112 QToolButton *nothingSelected = new QToolButton(0);
113 nothingSelected->setCheckable(true);
114 nothingSelected->setAutoExclusive(true);
115 nothingSelected->hide(); // a convenient button for when no button is checked in the group
116 m_rotationCenterButtons->addButton(nothingSelected, 9);
117
118
119 // initialize values for free transform sliders
120 shearXBox->setSuffix(QChar(Qt::Key_Percent));
121 shearYBox->setSuffix(QChar(Qt::Key_Percent));
122 shearXBox->setRange(-500, 500, 2);
123 shearYBox->setRange(-500, 500, 2);
124 shearXBox->setSingleStep(1);
125 shearYBox->setSingleStep(1);
126 shearXBox->setValue(0.0);
127 shearYBox->setValue(0.0);
128
129
130 translateXBox->setSuffix(i18n(" px"));
131 translateYBox->setSuffix(i18n(" px"));
132 translateXBox->setRange(-10000, 10000);
133 translateYBox->setRange(-10000, 10000);
134
135
136 scaleXBox->setRange(-10000, 10000);
137 scaleYBox->setRange(-10000, 10000);
138 scaleXBox->setValue(100.0);
139 scaleYBox->setValue(100.0);
140
141 m_scaleRatio = 1.0;
142
143
144 aXBox->setIncreasingDirection(KisAngleGauge::IncreasingDirection_Clockwise);
145 aYBox->setIncreasingDirection(KisAngleGauge::IncreasingDirection_Clockwise);
146 aZBox->setIncreasingDirection(KisAngleGauge::IncreasingDirection_Clockwise);
147 aXBox->setFlipOptionsMode(KisAngleSelector::FlipOptionsMode_MenuButton);
148 aYBox->setFlipOptionsMode(KisAngleSelector::FlipOptionsMode_MenuButton);
149 aZBox->setFlipOptionsMode(KisAngleSelector::FlipOptionsMode_MenuButton);
150
151
152 connect(m_rotationCenterButtons, SIGNAL(buttonPressed(int)), this, SLOT(slotRotationCenterChanged(int)));
153 connect(btnTransformAroundPivotPoint, SIGNAL(clicked(bool)), this, SLOT(slotTransformAroundRotationCenter(bool)));
154
155 // Init Free Transform Values
156 connect(scaleXBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetScaleX(int)));
157 connect(scaleYBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetScaleY(int)));
158 connect(shearXBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetShearX(qreal)));
159 connect(shearYBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetShearY(qreal)));
160 connect(translateXBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetTranslateX(int)));
161 connect(translateYBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetTranslateY(int)));
162 connect(aXBox, SIGNAL(angleChanged(qreal)), this, SLOT(slotSetAX(qreal)));
163 connect(aYBox, SIGNAL(angleChanged(qreal)), this, SLOT(slotSetAY(qreal)));
164 connect(aZBox, SIGNAL(angleChanged(qreal)), this, SLOT(slotSetAZ(qreal)));
165 connect(aspectButton, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slotSetKeepAspectRatio(bool)));
166 connect(flipXButton, SIGNAL(clicked(bool)), this, SLOT(slotFlipX()));
167 connect(flipYButton, SIGNAL(clicked(bool)), this, SLOT(slotFlipY()));
168 connect(rotateCWButton, SIGNAL(clicked(bool)), this, SLOT(slotRotateCW()));
169 connect(rotateCCWButton, SIGNAL(clicked(bool)), this, SLOT(slotRotateCCW()));
170
171 // toggle visibility of different free buttons
172 connect(freeMoveRadioButton, SIGNAL(clicked(bool)), SLOT(slotTransformAreaVisible(bool)));
173 connect(freeRotationRadioButton, SIGNAL(clicked(bool)), SLOT(slotTransformAreaVisible(bool)));
174 connect(freeScaleRadioButton, SIGNAL(clicked(bool)), SLOT(slotTransformAreaVisible(bool)));
175 connect(freeShearRadioButton, SIGNAL(clicked(bool)), SLOT(slotTransformAreaVisible(bool)));
176
177 // only first group for free transform
178 rotationGroup->hide();
179 moveGroup->show();
180 scaleGroup->hide();
181 shearGroup->hide();
182
183
184
185 // Init Warp Transform Values
186 alphaBox->setSingleStep(0.1);
187 alphaBox->setRange(0, 10, 1);
188
189 connect(alphaBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetWarpAlpha(qreal)));
190 connect(densityBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetWarpDensity(int)));
191
192 connect(defaultRadioButton, SIGNAL(clicked(bool)), this, SLOT(slotWarpDefaultPointsButtonClicked(bool)));
193 connect(customRadioButton, SIGNAL(clicked(bool)), this, SLOT(slotWarpCustomPointsButtonClicked(bool)));
194 connect(lockUnlockPointsButton, SIGNAL(clicked()), this, SLOT(slotWarpLockPointsButtonClicked()));
195 connect(resetPointsButton, SIGNAL(clicked()), this, SLOT(slotWarpResetPointsButtonClicked()));
196
197 // Init Cage Transform Values
198 cageTransformButtonGroup->setId(cageAddEditRadio, 0); // we need to set manually since Qt Designer generates negative by default
199 cageTransformButtonGroup->setId(cageDeformRadio, 1);
200 connect(cageTransformButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(slotCageOptionsChanged(int)));
201
202 // Init Liquify Transform Values
203 liquifySizeSlider->setRange(KisLiquifyProperties::minSize(),
204 KisLiquifyProperties::maxSize(), 2);
205 liquifySizeSlider->setExponentRatio(4);
206 liquifySizeSlider->setValue(60.0);
207 connect(liquifySizeSlider, SIGNAL(valueChanged(qreal)), this, SLOT(liquifySizeChanged(qreal)));
208 liquifySizeSlider->setToolTip(i18nc("@info:tooltip", "Size of the deformation brush"));
209
210 liquifyAmountSlider->setRange(0.0, 1.0, 2);
211 liquifyAmountSlider->setValue(0.05);
212 connect(liquifyAmountSlider, SIGNAL(valueChanged(qreal)), this, SLOT(liquifyAmountChanged(qreal)));
213 liquifyAmountSlider->setToolTip(i18nc("@info:tooltip", "Amount of the deformation you get"));
214
215 liquifyFlowSlider->setRange(0.0, 1.0, 2);
216 liquifyFlowSlider->setValue(1.0);
217 connect(liquifyFlowSlider, SIGNAL(valueChanged(qreal)), this, SLOT(liquifyFlowChanged(qreal)));
218 liquifyFlowSlider->setToolTip(i18nc("@info:tooltip", "When in non-buildup mode, shows how fast the deformation limit is reached."));
219
220 buidupModeComboBox->setCurrentIndex(0); // set to build-up mode by default
221 connect(buidupModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(liquifyBuildUpChanged(int)));
222 buidupModeComboBox->setToolTip("<p>" + i18nc("@info:tooltip", "Switch between Build Up and Wash mode of painting. Build Up mode adds deformations one on top of the other without any limits. Wash mode gradually deforms the piece to the selected deformation level.") + "</p>");
223
224 liquifySpacingSlider->setRange(0.0, 3.0, 2);
225 liquifySizeSlider->setExponentRatio(3);
226 liquifySpacingSlider->setSingleStep(0.01);
227 liquifySpacingSlider->setValue(0.2);
228 connect(liquifySpacingSlider, SIGNAL(valueChanged(qreal)), this, SLOT(liquifySpacingChanged(qreal)));
229 liquifySpacingSlider->setToolTip(i18nc("@info:tooltip", "Space between two sequential applications of the deformation"));
230
231 liquifySizePressureBox->setChecked(true);
232 connect(liquifySizePressureBox, SIGNAL(toggled(bool)), this, SLOT(liquifySizePressureChanged(bool)));
233 liquifySizePressureBox->setToolTip(i18nc("@info:tooltip", "Scale <b>Size</b> value according to current stylus pressure"));
234
235 liquifyAmountPressureBox->setChecked(true);
236 connect(liquifyAmountPressureBox, SIGNAL(toggled(bool)), this, SLOT(liquifyAmountPressureChanged(bool)));
237 liquifyAmountPressureBox->setToolTip(i18nc("@info:tooltip", "Scale <b>Amount</b> value according to current stylus pressure"));
238
239 liquifyReverseDirectionChk->setChecked(false);
240 connect(liquifyReverseDirectionChk, SIGNAL(toggled(bool)), this, SLOT(liquifyReverseDirectionChanged(bool)));
241 liquifyReverseDirectionChk->setToolTip(i18nc("@info:tooltip", "Reverse direction of the current deformation tool"));
242
243 KisSignalMapper *liquifyModeMapper = new KisSignalMapper(this);
244 connect(liquifyMove, SIGNAL(toggled(bool)), liquifyModeMapper, SLOT(map()));
245 connect(liquifyScale, SIGNAL(toggled(bool)), liquifyModeMapper, SLOT(map()));
246 connect(liquifyRotate, SIGNAL(toggled(bool)), liquifyModeMapper, SLOT(map()));
247 connect(liquifyOffset, SIGNAL(toggled(bool)), liquifyModeMapper, SLOT(map()));
248 connect(liquifyUndo, SIGNAL(toggled(bool)), liquifyModeMapper, SLOT(map()));
249 liquifyModeMapper->setMapping(liquifyMove, (int)KisLiquifyProperties::MOVE);
250 liquifyModeMapper->setMapping(liquifyScale, (int)KisLiquifyProperties::SCALE);
251 liquifyModeMapper->setMapping(liquifyRotate, (int)KisLiquifyProperties::ROTATE);
252 liquifyModeMapper->setMapping(liquifyOffset, (int)KisLiquifyProperties::OFFSET);
253 liquifyModeMapper->setMapping(liquifyUndo, (int)KisLiquifyProperties::UNDO);
254 connect(liquifyModeMapper, SIGNAL(mapped(int)), SLOT(slotLiquifyModeChanged(int)));
255
256 liquifyMove->setToolTip(i18nc("@info:tooltip", "Move: drag the image along the brush stroke"));
257 liquifyScale->setToolTip(i18nc("@info:tooltip", "Scale: grow/shrink image under cursor"));
258 liquifyRotate->setToolTip(i18nc("@info:tooltip", "Rotate: twirl image under cursor"));
259 liquifyOffset->setToolTip(i18nc("@info:tooltip", "Offset: shift the image to the right of the stroke direction"));
260 liquifyUndo->setToolTip(i18nc("@info:tooltip", "Undo: erase actions of other tools"));
261
262 // Connect all edit boxes to the Editing Finished signal
263 connect(densityBox, SIGNAL(editingFinished()), this, SLOT(notifyEditingFinished()));
264
265
266
267 // Connect other widget (not having editingFinished signal) to
268 // the same slot. From Qt 4.6 onwards the sequence of the signal
269 // delivery is definite.
270 connect(cmbFilter, SIGNAL(activated(KoID)), this, SLOT(notifyEditingFinished()));
271 connect(cmbWarpType, SIGNAL(currentIndexChanged(int)), this, SLOT(notifyEditingFinished()));
272 connect(m_rotationCenterButtons, SIGNAL(buttonPressed(int)), this, SLOT(notifyEditingFinished()));
273 connect(aspectButton, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(notifyEditingFinished()));
274
275 connect(lockUnlockPointsButton, SIGNAL(clicked()), this, SLOT(notifyEditingFinished()));
276 connect(resetPointsButton, SIGNAL(clicked()), this, SLOT(notifyEditingFinished()));
277
278 connect(defaultRadioButton, SIGNAL(clicked(bool)), this, SLOT(notifyEditingFinished()));
279 connect(customRadioButton, SIGNAL(clicked(bool)), this, SLOT(notifyEditingFinished()));
280
281 // Liquify
282 //
283 // liquify brush options do not affect the image directly and are not
284 // saved to undo, so we don't emit notifyEditingFinished() for them
285
286 // Connect Apply/Reset buttons
287 connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(slotButtonBoxClicked(QAbstractButton*)));
288
289 // Mesh. First set up, then connect.
290 intNumRows->setRange(1, 999);
291 intNumColumns->setRange(1, 999);
292
293 connect(chkShowControlPoints, SIGNAL(toggled(bool)), this, SLOT(slotMeshShowHandlesChanged()));
294 connect(chkSymmetricalHandles, SIGNAL(toggled(bool)), this, SLOT(slotMeshSymmetricalHandlesChanged()));
295 connect(chkScaleHandles, SIGNAL(toggled(bool)), this, SLOT(slotMeshScaleHandlesChanged()));
296 connect(intNumColumns, SIGNAL(valueChanged(int)), this, SLOT(slotMeshSizeChanged()));
297 connect(intNumRows, SIGNAL(valueChanged(int)), this, SLOT(slotMeshSizeChanged()));
298 connect(intNumColumns, SIGNAL(editingFinished()), this, SLOT(notifyEditingFinished()));
299 connect(intNumRows, SIGNAL(editingFinished()), this, SLOT(notifyEditingFinished()));
300
301 // Mode switch buttons
302 connect(freeTransformButton, SIGNAL(clicked(bool)), this, SLOT(slotSetFreeTransformModeButtonClicked(bool)));
303 connect(warpButton, SIGNAL(clicked(bool)), this, SLOT(slotSetWarpModeButtonClicked(bool)));
304 connect(cageButton, SIGNAL(clicked(bool)), this, SLOT(slotSetCageModeButtonClicked(bool)));
305 connect(perspectiveTransformButton, SIGNAL(clicked(bool)), this, SLOT(slotSetPerspectiveModeButtonClicked(bool)));
306 connect(liquifyButton, SIGNAL(clicked(bool)), this, SLOT(slotSetLiquifyModeButtonClicked(bool)));
307 connect(meshButton, SIGNAL(clicked(bool)), this, SLOT(slotSetMeshModeButtonClicked(bool)));
308
309
310 tooBigLabelWidget->hide();
311
312 connect(canvas->viewManager()->mainWindow(), SIGNAL(themeChanged()), SLOT(slotUpdateIcons()), Qt::UniqueConnection);
313 slotUpdateIcons();
314 }
315
slotUpdateIcons()316 void KisToolTransformConfigWidget::slotUpdateIcons()
317 {
318 freeTransformButton->setIcon(KisIconUtils::loadIcon("transform_icons_main"));
319 warpButton->setIcon(KisIconUtils::loadIcon("transform_icons_warp"));
320 cageButton->setIcon(KisIconUtils::loadIcon("transform_icons_cage"));
321 perspectiveTransformButton->setIcon(KisIconUtils::loadIcon("transform_icons_perspective"));
322 liquifyButton->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_main"));
323 meshButton->setIcon(KisIconUtils::loadIcon("transform_icons_mesh"));
324
325 liquifyMove->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_move"));
326 liquifyScale->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_resize"));
327 liquifyRotate->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_rotate"));
328 liquifyOffset->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_offset"));
329 liquifyUndo->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_erase"));
330
331
332
333 middleRightButton->setIcon(KisIconUtils::loadIcon("arrow-right"));
334 topRightButton->setIcon(KisIconUtils::loadIcon("arrow-topright"));
335 middleTopButton->setIcon(KisIconUtils::loadIcon("arrow-up"));
336 topLeftButton->setIcon(KisIconUtils::loadIcon("arrow-topleft"));
337 middleLeftButton->setIcon(KisIconUtils::loadIcon("arrow-left"));
338 bottomLeftButton->setIcon(KisIconUtils::loadIcon("arrow-downleft"));
339 middleBottomButton->setIcon(KisIconUtils::loadIcon("arrow-down"));
340 bottomRightButton->setIcon(KisIconUtils::loadIcon("arrow-downright"));
341
342 btnTransformAroundPivotPoint->setIcon(KisIconUtils::loadIcon("pivot-point"));
343
344
345 // pressure icons
346 liquifySizePressureBox->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure"));
347 liquifyAmountPressureBox->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure"));
348 }
349
updateLiquifyControls()350 void KisToolTransformConfigWidget::updateLiquifyControls()
351 {
352 blockUiSlots();
353
354 ToolTransformArgs *config = m_transaction->currentConfig();
355 KisLiquifyProperties *props =
356 config->liquifyProperties();
357
358 const bool useWashMode = props->useWashMode();
359
360 liquifySizeSlider->setValue(props->size());
361 liquifyAmountSlider->setValue(props->amount());
362 liquifyFlowSlider->setValue(props->flow());
363 buidupModeComboBox->setCurrentIndex(useWashMode);
364
365 liquifySpacingSlider->setValue(props->spacing());
366 liquifySizePressureBox->setChecked(props->sizeHasPressure());
367 liquifyAmountPressureBox->setChecked(props->amountHasPressure());
368 liquifyReverseDirectionChk->setChecked(props->reverseDirection());
369
370
371 KisLiquifyProperties::LiquifyMode mode =
372 static_cast<KisLiquifyProperties::LiquifyMode>(props->mode());
373
374 bool canInverseDirection =
375 mode != KisLiquifyProperties::UNDO;
376
377 bool canUseWashMode = mode != KisLiquifyProperties::UNDO;
378
379 liquifyReverseDirectionChk->setEnabled(canInverseDirection);
380 liquifyFlowSlider->setEnabled(canUseWashMode && useWashMode);
381 buidupModeComboBox->setEnabled(canUseWashMode);
382
383 const qreal maxAmount = canUseWashMode ? 5.0 : 1.0;
384 liquifyAmountSlider->setRange(0.0, maxAmount, 2);
385
386 unblockUiSlots();
387 }
388
slotLiquifyModeChanged(int value)389 void KisToolTransformConfigWidget::slotLiquifyModeChanged(int value)
390 {
391 if (m_uiSlotsBlocked) return;
392
393 ToolTransformArgs *config = m_transaction->currentConfig();
394
395 KisLiquifyProperties *props =
396 config->liquifyProperties();
397
398 KisLiquifyProperties::LiquifyMode mode =
399 static_cast<KisLiquifyProperties::LiquifyMode>(value);
400
401 if (mode == props->mode()) return;
402
403 props->setMode(mode);
404 props->loadMode();
405
406 updateLiquifyControls();
407
408 notifyConfigChanged();
409 }
410
liquifySizeChanged(qreal value)411 void KisToolTransformConfigWidget::liquifySizeChanged(qreal value)
412 {
413 if (m_uiSlotsBlocked) return;
414
415 ToolTransformArgs *config = m_transaction->currentConfig();
416 KisLiquifyProperties *props =
417 config->liquifyProperties();
418
419 props->setSize(value);
420 notifyConfigChanged();
421 }
422
liquifyAmountChanged(qreal value)423 void KisToolTransformConfigWidget::liquifyAmountChanged(qreal value)
424 {
425 if (m_uiSlotsBlocked) return;
426
427 ToolTransformArgs *config = m_transaction->currentConfig();
428 KisLiquifyProperties *props =
429 config->liquifyProperties();
430
431 props->setAmount(value);
432 notifyConfigChanged();
433 }
434
liquifyFlowChanged(qreal value)435 void KisToolTransformConfigWidget::liquifyFlowChanged(qreal value)
436 {
437 if (m_uiSlotsBlocked) return;
438
439 ToolTransformArgs *config = m_transaction->currentConfig();
440 KisLiquifyProperties *props =
441 config->liquifyProperties();
442
443 props->setFlow(value);
444 notifyConfigChanged();
445 }
446
liquifyBuildUpChanged(int value)447 void KisToolTransformConfigWidget::liquifyBuildUpChanged(int value)
448 {
449 if (m_uiSlotsBlocked) return;
450
451 ToolTransformArgs *config = m_transaction->currentConfig();
452 KisLiquifyProperties *props =
453 config->liquifyProperties();
454
455 props->setUseWashMode(value); // 0 == build up mode / 1 == wash mode
456
457 notifyConfigChanged();
458
459 // we need to enable/disable flow slider
460 updateLiquifyControls();
461 }
462
liquifySpacingChanged(qreal value)463 void KisToolTransformConfigWidget::liquifySpacingChanged(qreal value)
464 {
465 if (m_uiSlotsBlocked) return;
466
467 ToolTransformArgs *config = m_transaction->currentConfig();
468 KisLiquifyProperties *props =
469 config->liquifyProperties();
470
471 props->setSpacing(value);
472 notifyConfigChanged();
473 }
474
liquifySizePressureChanged(bool value)475 void KisToolTransformConfigWidget::liquifySizePressureChanged(bool value)
476 {
477 if (m_uiSlotsBlocked) return;
478
479 ToolTransformArgs *config = m_transaction->currentConfig();
480 KisLiquifyProperties *props =
481 config->liquifyProperties();
482
483 props->setSizeHasPressure(value);
484 notifyConfigChanged();
485 }
486
liquifyAmountPressureChanged(bool value)487 void KisToolTransformConfigWidget::liquifyAmountPressureChanged(bool value)
488 {
489 if (m_uiSlotsBlocked) return;
490
491 ToolTransformArgs *config = m_transaction->currentConfig();
492 KisLiquifyProperties *props =
493 config->liquifyProperties();
494
495 props->setAmountHasPressure(value);
496 notifyConfigChanged();
497 }
498
liquifyReverseDirectionChanged(bool value)499 void KisToolTransformConfigWidget::liquifyReverseDirectionChanged(bool value)
500 {
501 if (m_uiSlotsBlocked) return;
502
503 ToolTransformArgs *config = m_transaction->currentConfig();
504 KisLiquifyProperties *props =
505 config->liquifyProperties();
506
507 props->setReverseDirection(value);
508 notifyConfigChanged();
509 }
510
updateConfig(const ToolTransformArgs & config)511 void KisToolTransformConfigWidget::updateConfig(const ToolTransformArgs &config)
512 {
513 blockUiSlots();
514
515 if (config.mode() == ToolTransformArgs::FREE_TRANSFORM ||
516 config.mode() == ToolTransformArgs::PERSPECTIVE_4POINT) {
517
518 quickTransformGroup->setEnabled(config.mode() == ToolTransformArgs::FREE_TRANSFORM);
519
520 stackedWidget->setCurrentIndex(0);
521
522 bool freeTransformIsActive = config.mode() == ToolTransformArgs::FREE_TRANSFORM;
523
524 if (freeTransformIsActive)
525 {
526 freeTransformButton->setChecked(true);
527 }
528 else
529 {
530 perspectiveTransformButton->setChecked(true);
531 }
532
533 aXBox->setEnabled(freeTransformIsActive);
534 aYBox->setEnabled(freeTransformIsActive);
535 aZBox->setEnabled(freeTransformIsActive);
536 freeRotationRadioButton->setEnabled(freeTransformIsActive);
537
538 scaleXBox->setValue(config.scaleX() * 100.);
539 scaleYBox->setValue(config.scaleY() * 100.);
540 shearXBox->setValue(config.shearX() * 100.);
541 shearYBox->setValue(config.shearY() * 100.);
542
543 const QPointF anchorPoint = config.originalCenter() + config.rotationCenterOffset();
544 const KisTransformUtils::MatricesPack m(config);
545 const QPointF anchorPointView = m.finalTransform().map(anchorPoint);
546
547 translateXBox->setValue(anchorPointView.x());
548 translateYBox->setValue(anchorPointView.y());
549
550 aXBox->setAngle(normalizeAngleDegrees(kisRadiansToDegrees(config.aX())));
551 aYBox->setAngle(normalizeAngleDegrees(kisRadiansToDegrees(config.aY())));
552 aZBox->setAngle(normalizeAngleDegrees(kisRadiansToDegrees(config.aZ())));
553 aspectButton->setKeepAspectRatio(config.keepAspectRatio());
554 cmbFilter->setCurrent(config.filterId());
555
556 QPointF pt = m_transaction->currentConfig()->rotationCenterOffset();
557 pt.rx() /= m_transaction->originalHalfWidth();
558 pt.ry() /= m_transaction->originalHalfHeight();
559
560 for (int i = 0; i < 9; i++) {
561 if (qFuzzyCompare(m_handleDir[i].x(), pt.x()) &&
562 qFuzzyCompare(m_handleDir[i].y(), pt.y())) {
563
564 m_rotationCenterButtons->button(i)->setChecked(true);
565 break;
566 }
567 }
568
569 btnTransformAroundPivotPoint->setChecked(config.transformAroundRotationCenter());
570
571 } else if (config.mode() == ToolTransformArgs::WARP) {
572
573 stackedWidget->setCurrentIndex(1);
574 warpButton->setChecked(true);
575
576 if (config.defaultPoints()) {
577 densityBox->setValue(std::sqrt(config.numPoints()));
578 }
579
580 cmbWarpType->setCurrentIndex((int)config.warpType());
581 defaultRadioButton->setChecked(config.defaultPoints());
582 customRadioButton->setChecked(!config.defaultPoints());
583 densityBox->setEnabled(config.defaultPoints());
584 customWarpWidget->setEnabled(!config.defaultPoints());
585
586 updateLockPointsButtonCaption();
587
588 } else if (config.mode() == ToolTransformArgs::CAGE) {
589
590 // default UI options
591 resetUIOptions();
592
593 // we need at least 3 point before we can start actively deforming
594 if (config.origPoints().size() >= 3)
595 {
596 cageTransformDirections->setText(i18n("Switch between editing and deforming cage"));
597 cageAddEditRadio->setVisible(true);
598 cageDeformRadio->setVisible(true);
599
600 // update to correct radio button
601 if (config.isEditingTransformPoints())
602 cageAddEditRadio->setChecked(true);
603 else
604 cageDeformRadio->setChecked(true);
605
606 changeGranularity->setCurrentIndex(log2(config.pixelPrecision()) - 2);
607 granularityPreview->setCurrentIndex(log2(config.previewPixelPrecision()) - 2);
608
609 }
610
611 } else if (config.mode() == ToolTransformArgs::LIQUIFY) {
612
613 stackedWidget->setCurrentIndex(3);
614 liquifyButton->setChecked(true);
615
616 const KisLiquifyProperties *props =
617 config.liquifyProperties();
618
619 switch (props->mode()) {
620 case KisLiquifyProperties::MOVE:
621 liquifyMove->setChecked(true);
622 break;
623 case KisLiquifyProperties::SCALE:
624 liquifyScale->setChecked(true);
625 break;
626 case KisLiquifyProperties::ROTATE:
627 liquifyRotate->setChecked(true);
628 break;
629 case KisLiquifyProperties::OFFSET:
630 liquifyOffset->setChecked(true);
631 break;
632 case KisLiquifyProperties::UNDO:
633 liquifyUndo->setChecked(true);
634 break;
635 case KisLiquifyProperties::N_MODES:
636 qFatal("Unsupported mode");
637 }
638
639 updateLiquifyControls();
640 } else if (config.mode() == ToolTransformArgs::MESH) {
641 stackedWidget->setCurrentIndex(4);
642 intNumColumns->setValue(config.meshTransform()->size().width() - 1);
643 intNumRows->setValue(config.meshTransform()->size().height() - 1);
644 chkShowControlPoints->setChecked(config.meshShowHandles());
645 chkSymmetricalHandles->setChecked(config.meshSymmetricalHandles());
646 chkScaleHandles->setChecked(config.meshScaleHandles());
647 }
648
649 unblockUiSlots();
650 }
651
updateLockPointsButtonCaption()652 void KisToolTransformConfigWidget::updateLockPointsButtonCaption()
653 {
654 ToolTransformArgs *config = m_transaction->currentConfig();
655
656 if (config->isEditingTransformPoints()) {
657 lockUnlockPointsButton->setText(i18n("Lock Points"));
658 } else {
659 lockUnlockPointsButton->setText(i18n("Unlock Points"));
660 }
661 }
662
setApplyResetDisabled(bool disabled)663 void KisToolTransformConfigWidget::setApplyResetDisabled(bool disabled)
664 {
665 QAbstractButton *applyButton = buttonBox->button(QDialogButtonBox::Apply);
666 QAbstractButton *resetButton = buttonBox->button(QDialogButtonBox::Reset);
667
668 Q_ASSERT(applyButton);
669 Q_ASSERT(resetButton);
670
671 applyButton->setDisabled(disabled);
672 resetButton->setDisabled(disabled);
673 }
674
resetRotationCenterButtons()675 void KisToolTransformConfigWidget::resetRotationCenterButtons()
676 {
677 int checkedId = m_rotationCenterButtons->checkedId();
678
679 if (checkedId >= 0 && checkedId <= 8) {
680 // uncheck the current checked button
681 m_rotationCenterButtons->button(9)->setChecked(true);
682 }
683 }
684
workRecursively() const685 bool KisToolTransformConfigWidget::workRecursively() const
686 {
687 return chkWorkRecursively->isChecked();
688 }
689
setTooBigLabelVisible(bool value)690 void KisToolTransformConfigWidget::setTooBigLabelVisible(bool value)
691 {
692 tooBigLabelWidget->setVisible(value);
693 }
694
blockNotifications()695 void KisToolTransformConfigWidget::blockNotifications()
696 {
697 m_notificationsBlocked++;
698 }
699
unblockNotifications()700 void KisToolTransformConfigWidget::unblockNotifications()
701 {
702 m_notificationsBlocked--;
703 }
704
notifyConfigChanged()705 void KisToolTransformConfigWidget::notifyConfigChanged()
706 {
707 if (!m_notificationsBlocked) {
708 emit sigConfigChanged();
709 }
710 m_configChanged = true;
711 }
712
blockUiSlots()713 void KisToolTransformConfigWidget::blockUiSlots()
714 {
715 m_uiSlotsBlocked++;
716 }
717
unblockUiSlots()718 void KisToolTransformConfigWidget::unblockUiSlots()
719 {
720 m_uiSlotsBlocked--;
721 }
722
notifyEditingFinished()723 void KisToolTransformConfigWidget::notifyEditingFinished()
724 {
725 if (m_uiSlotsBlocked || m_notificationsBlocked || !m_configChanged) return;
726
727 emit sigEditingFinished();
728 m_configChanged = false;
729 }
730
731
resetUIOptions()732 void KisToolTransformConfigWidget::resetUIOptions()
733 {
734 // reset tool states since we are done (probably can encapsulate this later)
735 ToolTransformArgs *config = m_transaction->currentConfig();
736 if (config->mode() == ToolTransformArgs::CAGE)
737 {
738 cageAddEditRadio->setVisible(false);
739 cageAddEditRadio->setChecked(true);
740 cageDeformRadio->setVisible(false);
741 cageTransformDirections->setText(i18n("Create 3 points on the canvas to begin"));
742
743 // ensure we are on the right options view
744 stackedWidget->setCurrentIndex(2);
745 }
746
747
748
749 }
750
slotButtonBoxClicked(QAbstractButton * button)751 void KisToolTransformConfigWidget::slotButtonBoxClicked(QAbstractButton *button)
752 {
753 QAbstractButton *applyButton = buttonBox->button(QDialogButtonBox::Apply);
754 QAbstractButton *resetButton = buttonBox->button(QDialogButtonBox::Reset);
755
756 resetUIOptions();
757
758 if (button == applyButton) {
759 emit sigApplyTransform();
760 }
761 else if (button == resetButton) {
762 emit sigCancelTransform();
763 }
764
765 }
766
slotSetMeshModeButtonClicked(bool value)767 void KisToolTransformConfigWidget::slotSetMeshModeButtonClicked(bool value)
768 {
769 if (!value) return;
770
771 lblTransformType->setText(meshButton->toolTip());
772
773 emit sigResetTransform(ToolTransformArgs::MESH);
774 }
775
slotSetFreeTransformModeButtonClicked(bool value)776 void KisToolTransformConfigWidget::slotSetFreeTransformModeButtonClicked(bool value)
777 {
778 if (!value) return;
779
780 lblTransformType->setText(freeTransformButton->toolTip());
781
782 emit sigResetTransform(ToolTransformArgs::FREE_TRANSFORM);
783 }
784
slotSetWarpModeButtonClicked(bool value)785 void KisToolTransformConfigWidget::slotSetWarpModeButtonClicked(bool value)
786 {
787 if (!value) return;
788
789 lblTransformType->setText(warpButton->toolTip());
790
791 emit sigResetTransform(ToolTransformArgs::WARP);
792 }
793
slotSetCageModeButtonClicked(bool value)794 void KisToolTransformConfigWidget::slotSetCageModeButtonClicked(bool value)
795 {
796 if (!value) return;
797
798 lblTransformType->setText(cageButton->toolTip());
799
800 emit sigResetTransform(ToolTransformArgs::CAGE);
801 }
802
slotSetLiquifyModeButtonClicked(bool value)803 void KisToolTransformConfigWidget::slotSetLiquifyModeButtonClicked(bool value)
804 {
805 if (!value) return;
806
807 lblTransformType->setText(liquifyButton->toolTip());
808
809 emit sigResetTransform(ToolTransformArgs::LIQUIFY);
810 }
811
slotSetPerspectiveModeButtonClicked(bool value)812 void KisToolTransformConfigWidget::slotSetPerspectiveModeButtonClicked(bool value)
813 {
814 if (!value) return;
815
816 lblTransformType->setText(perspectiveTransformButton->toolTip());
817
818 emit sigResetTransform(ToolTransformArgs::PERSPECTIVE_4POINT);
819 }
820
slotFilterChanged(const KoID & filterId)821 void KisToolTransformConfigWidget::slotFilterChanged(const KoID &filterId)
822 {
823 ToolTransformArgs *config = m_transaction->currentConfig();
824 config->setFilterId(filterId.id());
825 notifyConfigChanged();
826 }
827
slotRotationCenterChanged(int index)828 void KisToolTransformConfigWidget::slotRotationCenterChanged(int index)
829 {
830 if (m_uiSlotsBlocked) return;
831
832 if (index >= 0 && index <= 8) {
833 ToolTransformArgs *config = m_transaction->currentConfig();
834
835 double i = m_handleDir[index].x();
836 double j = m_handleDir[index].y();
837
838 config->setRotationCenterOffset(QPointF(i * m_transaction->originalHalfWidth(),
839 j * m_transaction->originalHalfHeight()));
840
841 notifyConfigChanged();
842 updateConfig(*config);
843 }
844 }
845
slotTransformAroundRotationCenter(bool value)846 void KisToolTransformConfigWidget::slotTransformAroundRotationCenter(bool value)
847 {
848 if (m_uiSlotsBlocked) return;
849
850 ToolTransformArgs *config = m_transaction->currentConfig();
851 config->setTransformAroundRotationCenter(value);
852 notifyConfigChanged();
853 notifyEditingFinished();
854 }
855
slotSetScaleX(int value)856 void KisToolTransformConfigWidget::slotSetScaleX(int value)
857 {
858 if (m_uiSlotsBlocked) return;
859
860 ToolTransformArgs *config = m_transaction->currentConfig();
861
862 {
863 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
864 config->setScaleX(value / 100.);
865 }
866
867 if (config->keepAspectRatio()) {
868
869 blockNotifications();
870 int calculatedValue = int( value/ m_scaleRatio );
871
872 scaleYBox->blockSignals(true);
873 scaleYBox->setValue(calculatedValue);
874 {
875 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
876 config->setScaleY(calculatedValue / 100.);
877 }
878 scaleYBox->blockSignals(false);
879
880 unblockNotifications();
881 }
882
883 notifyConfigChanged();
884 notifyEditingFinished();
885 }
886
slotSetScaleY(int value)887 void KisToolTransformConfigWidget::slotSetScaleY(int value)
888 {
889 if (m_uiSlotsBlocked) return;
890
891 ToolTransformArgs *config = m_transaction->currentConfig();
892
893 {
894 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
895 config->setScaleY(value / 100.);
896 }
897
898 if (config->keepAspectRatio()) {
899 blockNotifications();
900 int calculatedValue = int(m_scaleRatio * value);
901 scaleXBox->blockSignals(true);
902 scaleXBox->setValue(calculatedValue);
903 {
904 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
905 config->setScaleX(calculatedValue / 100.);
906 }
907 scaleXBox->blockSignals(false);
908 unblockNotifications();
909 }
910
911 notifyConfigChanged();
912 notifyEditingFinished();
913 }
914
slotSetShearX(qreal value)915 void KisToolTransformConfigWidget::slotSetShearX(qreal value)
916 {
917 if (m_uiSlotsBlocked) return;
918
919 ToolTransformArgs *config = m_transaction->currentConfig();
920
921 {
922 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
923 config->setShearX((double)value / 100.);
924 }
925
926 notifyConfigChanged();
927 notifyEditingFinished();
928 }
929
slotSetShearY(qreal value)930 void KisToolTransformConfigWidget::slotSetShearY(qreal value)
931 {
932 if (m_uiSlotsBlocked) return;
933
934 ToolTransformArgs *config = m_transaction->currentConfig();
935
936 {
937 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
938 config->setShearY((double)value / 100.);
939 }
940
941
942 notifyConfigChanged();
943 notifyEditingFinished();
944 }
945
slotSetTranslateX(int value)946 void KisToolTransformConfigWidget::slotSetTranslateX(int value)
947 {
948 if (m_uiSlotsBlocked) return;
949
950 ToolTransformArgs *config = m_transaction->currentConfig();
951
952 const QPointF anchorPoint = config->originalCenter() + config->rotationCenterOffset();
953 const KisTransformUtils::MatricesPack m(*config);
954
955 const QPointF anchorPointView = m.finalTransform().map(anchorPoint);
956 const QPointF newAnchorPointView(value, anchorPointView.y());
957 config->setTransformedCenter(config->transformedCenter() + newAnchorPointView - anchorPointView);
958 translateXBox->setValue(value);
959 notifyConfigChanged();
960 }
961
slotSetTranslateY(int value)962 void KisToolTransformConfigWidget::slotSetTranslateY(int value)
963 {
964 if (m_uiSlotsBlocked) return;
965
966 ToolTransformArgs *config = m_transaction->currentConfig();
967
968 const QPointF anchorPoint = config->originalCenter() + config->rotationCenterOffset();
969 const KisTransformUtils::MatricesPack m(*config);
970
971 const QPointF anchorPointView = m.finalTransform().map(anchorPoint);
972 const QPointF newAnchorPointView(anchorPointView.x(), value);
973 config->setTransformedCenter(config->transformedCenter() + newAnchorPointView - anchorPointView);
974 translateYBox->setValue(value);
975 notifyConfigChanged();
976 }
977
slotSetAX(qreal value)978 void KisToolTransformConfigWidget::slotSetAX(qreal value)
979 {
980 if (m_uiSlotsBlocked) return;
981
982 ToolTransformArgs *config = m_transaction->currentConfig();
983 {
984 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
985 config->setAX(normalizeAngle(kisDegreesToRadians(value)));
986 }
987 notifyConfigChanged();
988 notifyEditingFinished();
989 }
990
slotSetAY(qreal value)991 void KisToolTransformConfigWidget::slotSetAY(qreal value)
992 {
993 if (m_uiSlotsBlocked) return;
994
995 ToolTransformArgs *config = m_transaction->currentConfig();
996
997 {
998 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
999 config->setAY(normalizeAngle(kisDegreesToRadians(value)));
1000 }
1001
1002 notifyConfigChanged();
1003 notifyEditingFinished();
1004 }
1005
slotSetAZ(qreal value)1006 void KisToolTransformConfigWidget::slotSetAZ(qreal value)
1007 {
1008 if (m_uiSlotsBlocked) return;
1009
1010 ToolTransformArgs *config = m_transaction->currentConfig();
1011
1012 {
1013 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
1014 config->setAZ(normalizeAngle(kisDegreesToRadians(value)));
1015 }
1016
1017 notifyConfigChanged();
1018 notifyEditingFinished();
1019 }
1020
slotFlipX()1021 void KisToolTransformConfigWidget::slotFlipX()
1022 {
1023 ToolTransformArgs *config = m_transaction->currentConfig();
1024
1025 {
1026 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
1027 config->setScaleX(config->scaleX() * -1);
1028 }
1029
1030 notifyConfigChanged();
1031 notifyEditingFinished();
1032 }
1033
slotFlipY()1034 void KisToolTransformConfigWidget::slotFlipY()
1035 {
1036 ToolTransformArgs *config = m_transaction->currentConfig();
1037
1038 {
1039 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
1040 config->setScaleY(config->scaleY() * -1);
1041 }
1042
1043 notifyConfigChanged();
1044 notifyEditingFinished();
1045 }
1046
slotRotateCW()1047 void KisToolTransformConfigWidget::slotRotateCW()
1048 {
1049 ToolTransformArgs *config = m_transaction->currentConfig();
1050
1051 {
1052 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
1053 config->setAZ(normalizeAngle(config->aZ() + M_PI_2));
1054 }
1055
1056 notifyConfigChanged();
1057 notifyEditingFinished();
1058 }
1059
slotRotateCCW()1060 void KisToolTransformConfigWidget::slotRotateCCW()
1061 {
1062 ToolTransformArgs *config = m_transaction->currentConfig();
1063
1064 {
1065 KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
1066 config->setAZ(normalizeAngle(config->aZ() - M_PI_2));
1067 }
1068
1069 notifyConfigChanged();
1070 notifyEditingFinished();
1071 }
1072
1073
1074 // change free transform setting we want to alter (all radio buttons call this)
slotTransformAreaVisible(bool value)1075 void KisToolTransformConfigWidget::slotTransformAreaVisible(bool value)
1076 {
1077 Q_UNUSED(value);
1078
1079 //QCheckBox sender = (QCheckBox)(*)(QObject::sender());
1080 QString senderName = QObject::sender()->objectName();
1081
1082
1083 // only show setting with what we have selected
1084 rotationGroup->hide();
1085 shearGroup->hide();
1086 scaleGroup->hide();
1087 moveGroup->hide();
1088
1089
1090 if ("freeMoveRadioButton" == senderName)
1091 {
1092 moveGroup->show();
1093 }
1094 else if ("freeShearRadioButton" == senderName)
1095 {
1096 shearGroup->show();
1097 }
1098 else if ("freeScaleRadioButton" == senderName)
1099 {
1100 scaleGroup->show();
1101 }
1102 else
1103 {
1104 rotationGroup->show();
1105 }
1106
1107 }
1108
slotSetKeepAspectRatio(bool value)1109 void KisToolTransformConfigWidget::slotSetKeepAspectRatio(bool value)
1110 {
1111 if (m_uiSlotsBlocked) return;
1112
1113 ToolTransformArgs *config = m_transaction->currentConfig();
1114 config->setKeepAspectRatio(value);
1115
1116 if (value) {
1117 blockNotifications();
1118 int tmpXScaleBox = scaleXBox->value();
1119 int tmpYScaleBox = scaleYBox->value();
1120 m_scaleRatio = (tmpXScaleBox / (double) tmpYScaleBox);
1121 unblockNotifications();
1122 }
1123
1124 notifyConfigChanged();
1125 }
1126
slotSetWarpAlpha(qreal value)1127 void KisToolTransformConfigWidget::slotSetWarpAlpha(qreal value)
1128 {
1129 if (m_uiSlotsBlocked) return;
1130
1131 ToolTransformArgs *config = m_transaction->currentConfig();
1132
1133 config->setAlpha((double)value);
1134 notifyConfigChanged();
1135 notifyEditingFinished();
1136 }
1137
slotSetWarpDensity(int value)1138 void KisToolTransformConfigWidget::slotSetWarpDensity(int value)
1139 {
1140 if (m_uiSlotsBlocked) return;
1141 setDefaultWarpPoints(value);
1142 }
1143
setDefaultWarpPoints(int pointsPerLine)1144 void KisToolTransformConfigWidget::setDefaultWarpPoints(int pointsPerLine)
1145 {
1146 ToolTransformArgs *config = m_transaction->currentConfig();
1147
1148 KisTransformUtils::setDefaultWarpPoints(pointsPerLine, m_transaction, config);
1149 notifyConfigChanged();
1150 }
1151
activateCustomWarpPoints(bool enabled)1152 void KisToolTransformConfigWidget::activateCustomWarpPoints(bool enabled)
1153 {
1154 ToolTransformArgs *config = m_transaction->currentConfig();
1155
1156 densityBox->setEnabled(!enabled);
1157 customWarpWidget->setEnabled(enabled);
1158
1159 if (!enabled) {
1160 config->setEditingTransformPoints(false);
1161 setDefaultWarpPoints(densityBox->value());
1162 config->setWarpCalculation(KisWarpTransformWorker::WarpCalculation::GRID);
1163 } else {
1164 config->setEditingTransformPoints(true);
1165 config->setWarpCalculation(KisWarpTransformWorker::WarpCalculation::DRAW);
1166 setDefaultWarpPoints(0);
1167 }
1168
1169
1170
1171
1172 updateLockPointsButtonCaption();
1173 }
1174
slotWarpDefaultPointsButtonClicked(bool value)1175 void KisToolTransformConfigWidget::slotWarpDefaultPointsButtonClicked(bool value)
1176 {
1177 if (m_uiSlotsBlocked) return;
1178
1179 activateCustomWarpPoints(!value);
1180 }
1181
slotWarpCustomPointsButtonClicked(bool value)1182 void KisToolTransformConfigWidget::slotWarpCustomPointsButtonClicked(bool value)
1183 {
1184 if (m_uiSlotsBlocked) return;
1185
1186 activateCustomWarpPoints(value);
1187 }
1188
slotWarpResetPointsButtonClicked()1189 void KisToolTransformConfigWidget::slotWarpResetPointsButtonClicked()
1190 {
1191 if (m_uiSlotsBlocked) return;
1192
1193 activateCustomWarpPoints(true);
1194 }
1195
slotWarpLockPointsButtonClicked()1196 void KisToolTransformConfigWidget::slotWarpLockPointsButtonClicked()
1197 {
1198 if (m_uiSlotsBlocked) return;
1199
1200 ToolTransformArgs *config = m_transaction->currentConfig();
1201 config->setEditingTransformPoints(!config->isEditingTransformPoints());
1202
1203 if (config->isEditingTransformPoints()) {
1204 // reinit the transf points to their original value
1205 ToolTransformArgs *config = m_transaction->currentConfig();
1206 int nbPoints = config->origPoints().size();
1207 for (int i = 0; i < nbPoints; ++i) {
1208 config->transfPoint(i) = config->origPoint(i);
1209 }
1210 }
1211
1212 updateLockPointsButtonCaption();
1213 notifyConfigChanged();
1214 }
1215
slotWarpTypeChanged(int index)1216 void KisToolTransformConfigWidget::slotWarpTypeChanged(int index)
1217 {
1218 if (m_uiSlotsBlocked) return;
1219
1220 ToolTransformArgs *config = m_transaction->currentConfig();
1221
1222 switch (index) {
1223 case KisWarpTransformWorker::AFFINE_TRANSFORM:
1224 case KisWarpTransformWorker::SIMILITUDE_TRANSFORM:
1225 case KisWarpTransformWorker::RIGID_TRANSFORM:
1226 config->setWarpType((KisWarpTransformWorker::WarpType)index);
1227 break;
1228 default:
1229 config->setWarpType(KisWarpTransformWorker::RIGID_TRANSFORM);
1230 break;
1231 }
1232
1233 notifyConfigChanged();
1234 }
1235
slotCageOptionsChanged(int value)1236 void KisToolTransformConfigWidget::slotCageOptionsChanged(int value)
1237 {
1238 if ( value == 0)
1239 {
1240 slotEditCagePoints(true);
1241 }
1242 else
1243 {
1244 slotEditCagePoints(false);
1245 }
1246
1247 notifyEditingFinished();
1248 }
1249
slotEditCagePoints(bool value)1250 void KisToolTransformConfigWidget::slotEditCagePoints(bool value)
1251 {
1252 if (m_uiSlotsBlocked) return;
1253
1254 ToolTransformArgs *config = m_transaction->currentConfig();
1255 config->refTransformedPoints() = config->origPoints();
1256
1257 config->setEditingTransformPoints(value);
1258 notifyConfigChanged();
1259 }
1260
slotGranularityChanged(QString value)1261 void KisToolTransformConfigWidget::slotGranularityChanged(QString value)
1262 {
1263 if (m_uiSlotsBlocked) return;
1264 KIS_SAFE_ASSERT_RECOVER_RETURN(value.toInt() > 1);
1265 ToolTransformArgs *config = m_transaction->currentConfig();
1266 config->setPixelPrecision(value.toInt());
1267 notifyConfigChanged();
1268 }
1269
slotPreviewGranularityChanged(QString value)1270 void KisToolTransformConfigWidget::slotPreviewGranularityChanged(QString value)
1271 {
1272 if (m_uiSlotsBlocked) return;
1273 KIS_SAFE_ASSERT_RECOVER_RETURN(value.toInt() > 1);
1274 ToolTransformArgs *config = m_transaction->currentConfig();
1275 config->setPreviewPixelPrecision(value.toInt());
1276 notifyConfigChanged();
1277 }
1278
slotMeshSizeChanged()1279 void KisToolTransformConfigWidget::slotMeshSizeChanged()
1280 {
1281 if (m_uiSlotsBlocked) return;
1282
1283 ToolTransformArgs *config = m_transaction->currentConfig();
1284 KisBezierTransformMesh &mesh = *config->meshTransform();
1285
1286 if (mesh.size().width() != intNumColumns->value() + 1) {
1287 mesh.reshapeMeshHorizontally(intNumColumns->value() + 1);
1288 }
1289
1290 if (mesh.size().height() != intNumRows->value() + 1) {
1291 mesh.reshapeMeshVertically(intNumRows->value() + 1);
1292 }
1293
1294 notifyConfigChanged();
1295 }
1296
slotMeshShowHandlesChanged()1297 void KisToolTransformConfigWidget::slotMeshShowHandlesChanged()
1298 {
1299 if (m_uiSlotsBlocked) return;
1300 ToolTransformArgs *config = m_transaction->currentConfig();
1301 config->setMeshShowHandles(this->chkShowControlPoints->isChecked());
1302 notifyConfigChanged();
1303 notifyEditingFinished();
1304 }
1305
slotMeshSymmetricalHandlesChanged()1306 void KisToolTransformConfigWidget::slotMeshSymmetricalHandlesChanged()
1307 {
1308 if (m_uiSlotsBlocked) return;
1309 ToolTransformArgs *config = m_transaction->currentConfig();
1310 config->setMeshSymmetricalHandles(this->chkSymmetricalHandles->isChecked());
1311 notifyConfigChanged();
1312 notifyEditingFinished();
1313 }
1314
slotMeshScaleHandlesChanged()1315 void KisToolTransformConfigWidget::slotMeshScaleHandlesChanged()
1316 {
1317 if (m_uiSlotsBlocked) return;
1318 ToolTransformArgs *config = m_transaction->currentConfig();
1319 config->setMeshScaleHandles(this->chkScaleHandles->isChecked());
1320 notifyConfigChanged();
1321 }
1322