1 
2 
3 #include "tools/tooloptions.h"
4 
5 // TnzTools includes
6 #include "tools/tool.h"
7 #include "tools/toolhandle.h"
8 #include "tools/toolcommandids.h"
9 
10 #include "selectiontool.h"
11 #include "vectorselectiontool.h"
12 #include "rasterselectiontool.h"
13 #include "toonzrasterbrushtool.h"
14 #include "fullcolorbrushtool.h"
15 #include "toonzvectorbrushtool.h"
16 #include "tooloptionscontrols.h"
17 
18 //#include "rgbpickertool.h"
19 #include "rulertool.h"
20 #include "shifttracetool.h"
21 
22 // TnzQt includes
23 #include "toonzqt/dvdialog.h"
24 #include "toonzqt/menubarcommand.h"
25 #include "toonzqt/gutil.h"
26 #include "toonzqt/dvscrollwidget.h"
27 #include "toonzqt/lutcalibrator.h"
28 #include "toonzqt/viewcommandids.h"
29 
30 // TnzLib includes
31 #include "toonz/tobjecthandle.h"
32 #include "toonz/tstageobject.h"
33 #include "toonz/txsheethandle.h"
34 #include "toonz/tstageobjectspline.h"
35 #include "toonz/tframehandle.h"
36 #include "toonz/tpalettehandle.h"
37 #include "toonz/palettecontroller.h"
38 #include "toonz/txshlevelhandle.h"
39 #include "toonz/preferences.h"
40 #include "toonz/tstageobjecttree.h"
41 #include "toonz/mypaintbrushstyle.h"
42 #include "toonz/tonionskinmaskhandle.h"
43 
44 // TnzCore includes
45 #include "tproperty.h"
46 #include "tenv.h"
47 
48 // Qt includes
49 #include <QPainter>
50 #include <QToolBar>
51 #include <QDockWidget>
52 #include <QHBoxLayout>
53 #include <QComboBox>
54 #include <QLabel>
55 #include <QPushButton>
56 #include <QToolButton>
57 #include <QResizeEvent>
58 #include <QList>
59 #include <QSignalMapper>
60 #include <QPropertyAnimation>
61 #include <QEasingCurve>
62 #include <QStackedWidget>
63 
64 TEnv::IntVar ArrowGlobalKeyFrame("EditToolGlobalKeyFrame", 0);
65 
66 //=============================================================================
67 // ToolOptionToolBar
68 
ToolOptionToolBar(QWidget * parent)69 ToolOptionToolBar::ToolOptionToolBar(QWidget *parent) : QToolBar(parent) {
70   setObjectName("toolOptionsPanel");
71   setMaximumHeight(25);
72 }
73 
74 //-----------------------------------------------------------------------------
75 
addSpacing(int width)76 void ToolOptionToolBar::addSpacing(int width) {
77   QWidget *spaceW = new QWidget(this);
78   spaceW->setFixedWidth(width);
79   addWidget(spaceW);
80 }
81 
82 //=============================================================================
83 // ToolOptionsBox
84 
ToolOptionsBox(QWidget * parent,bool isScrollable)85 ToolOptionsBox::ToolOptionsBox(QWidget *parent, bool isScrollable)
86     : QFrame(parent) {
87   setObjectName("toolOptionsPanel");
88   setStyleSheet("#toolOptionsPanel {border: 0px; margin: 1px;}");
89 
90   setFrameStyle(QFrame::StyledPanel);
91   setFixedHeight(26);
92 
93   m_layout = new QHBoxLayout;
94   m_layout->setMargin(0);
95   m_layout->setSpacing(5);
96   m_layout->addSpacing(5);
97 
98   if (isScrollable) {
99     QHBoxLayout *hLayout = new QHBoxLayout;
100     hLayout->setMargin(0);
101     hLayout->setSpacing(0);
102     setLayout(hLayout);
103 
104     // Build the scroll widget vin which the toolbar will be placed
105     DvScrollWidget *scrollWidget = new DvScrollWidget;
106     hLayout->addWidget(scrollWidget);
107 
108     // In the scrollable layout we add a widget of 24 height
109     // which contains the tooloptionBar. This is necessary
110     // to make the hboxlayout adjust the bar's vertical position.
111     QWidget *toolContainer = new QWidget;
112     scrollWidget->setWidget(toolContainer);
113 
114     toolContainer->setSizePolicy(QSizePolicy::MinimumExpanding,
115                                  QSizePolicy::Fixed);
116     toolContainer->setFixedHeight(24);
117     toolContainer->setObjectName("toolOptionsPanel");
118     toolContainer->setLayout(m_layout);
119   } else
120     setLayout(m_layout);
121 }
122 
123 //-----------------------------------------------------------------------------
124 
~ToolOptionsBox()125 ToolOptionsBox::~ToolOptionsBox() {
126   std::for_each(m_controls.begin(), m_controls.end(),
127                 std::default_delete<ToolOptionControl>());
128   std::for_each(m_labels.begin(), m_labels.end(),
129                 std::default_delete<QLabel>());
130 }
131 
132 //-----------------------------------------------------------------------------
133 
addLabel(QString name)134 QLabel *ToolOptionsBox::addLabel(QString name) {
135   QLabel *label = new QLabel(name);
136   label->setFixedHeight(20);
137   m_layout->addWidget(label);
138   m_labels[name.toStdString()] = label;
139   return label;
140 }
141 
142 //-----------------------------------------------------------------------------
143 
addLabel(std::string propName,QLabel * label)144 void ToolOptionsBox::addLabel(std::string propName, QLabel *label) {
145   m_labels[propName] = label;
146 }
147 
148 //-----------------------------------------------------------------------------
149 
addSeparator()150 void ToolOptionsBox::addSeparator() {
151   DVGui::Separator *separator = new DVGui::Separator();
152   separator->setOrientation(false);
153   separator->setFixedWidth(17);
154   m_layout->addWidget(separator, 0);
155 }
156 
157 //-----------------------------------------------------------------------------
158 
addControl(ToolOptionControl * control)159 void ToolOptionsBox::addControl(ToolOptionControl *control) {
160   m_controls[control->propertyName()] = control;
161 }
162 
163 //-----------------------------------------------------------------------------
164 
control(const std::string & controlName) const165 ToolOptionControl *ToolOptionsBox::control(
166     const std::string &controlName) const {
167   QMap<std::string, ToolOptionControl *>::const_iterator ct =
168       m_controls.find(controlName);
169 
170   return (ct == m_controls.end()) ? 0 : ct.value();
171 }
172 
173 //-----------------------------------------------------------------------------
174 
updateStatus()175 void ToolOptionsBox::updateStatus() {
176   QMap<std::string, ToolOptionControl *>::iterator it;
177   for (it = m_controls.begin(); it != m_controls.end(); it++)
178     it.value()->updateStatus();
179 }
180 
181 //=============================================================================
182 // ToolOptionControlBuilder
183 
ToolOptionControlBuilder(ToolOptionsBox * panel,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)184 ToolOptionControlBuilder::ToolOptionControlBuilder(ToolOptionsBox *panel,
185                                                    TTool *tool,
186                                                    TPaletteHandle *pltHandle,
187                                                    ToolHandle *toolHandle)
188     : m_panel(panel)
189     , m_tool(tool)
190     , m_pltHandle(pltHandle)
191     , m_toolHandle(toolHandle)
192     , m_singleValueWidgetType(SLIDER)
193     , m_enumWidgetType(COMBOBOX) {}
194 
195 //-----------------------------------------------------------------------------
196 
addLabel(TProperty * p)197 QLabel *ToolOptionControlBuilder::addLabel(TProperty *p) {
198   QLabel *label = new QLabel(p->getQStringName());
199   hLayout()->addWidget(label, 0);
200   return label;
201 }
202 
203 //-----------------------------------------------------------------------------
204 
visit(TDoubleProperty * p)205 void ToolOptionControlBuilder::visit(TDoubleProperty *p) {
206   QLabel *label = addLabel(p);
207   m_panel->addLabel(p->getName(), label);
208   ToolOptionSlider *control = new ToolOptionSlider(m_tool, p, m_toolHandle);
209   hLayout()->addWidget(control, 100);
210   // storing the control in the map for updating values later
211   m_panel->addControl(control);
212   CommandManager *cm = CommandManager::instance();
213   if (p->getName() == "Size:") {
214     QAction *a;
215     a = cm->getAction("A_IncreaseMaxBrushThickness");
216     control->addAction(a);
217     QObject::connect(a, SIGNAL(triggered()), control, SLOT(increase()));
218     a = cm->getAction("A_DecreaseMaxBrushThickness");
219     control->addAction(a);
220     QObject::connect(a, SIGNAL(triggered()), control, SLOT(decrease()));
221   }
222   if (p->getName() == "ModifierSize") {
223     QAction *a;
224     a = cm->getAction("A_IncreaseMaxBrushThickness");
225     control->addAction(a);
226     QObject::connect(a, SIGNAL(triggered()), control,
227                      SLOT(increaseFractional()));
228     a = cm->getAction("A_DecreaseMaxBrushThickness");
229     control->addAction(a);
230     QObject::connect(a, SIGNAL(triggered()), control,
231                      SLOT(decreaseFractional()));
232   }
233   if (p->getName() == "Hardness:") {
234     QAction *a;
235     a = cm->getAction("A_IncreaseBrushHardness");
236     control->addAction(a);
237     QObject::connect(a, SIGNAL(triggered()), control, SLOT(increase()));
238     a = cm->getAction("A_DecreaseBrushHardness");
239     control->addAction(a);
240     QObject::connect(a, SIGNAL(triggered()), control, SLOT(decrease()));
241   }
242   hLayout()->addSpacing(5);
243 }
244 
245 //-----------------------------------------------------------------------------
246 
visit(TDoublePairProperty * p)247 void ToolOptionControlBuilder::visit(TDoublePairProperty *p) {
248   QLabel *label = addLabel(p);
249   m_panel->addLabel(p->getName(), label);
250   ToolOptionPairSlider *control = new ToolOptionPairSlider(
251       m_tool, p, QObject::tr("Min:"), QObject::tr("Max:"), m_toolHandle);
252   hLayout()->addWidget(control, 150);
253   m_panel->addControl(control);
254   if (p->getName() == "Size:" || p->getName() == "Size") {
255     CommandManager *cm = CommandManager::instance();
256     QAction *a;
257     a = cm->getAction("A_IncreaseMaxBrushThickness");
258     control->addAction(a);
259     QObject::connect(a, SIGNAL(triggered()), control, SLOT(increaseMaxValue()));
260     a = cm->getAction("A_DecreaseMaxBrushThickness");
261     control->addAction(a);
262     QObject::connect(a, SIGNAL(triggered()), control, SLOT(decreaseMaxValue()));
263 
264     a = cm->getAction("A_IncreaseMinBrushThickness");
265     control->addAction(a);
266     QObject::connect(a, SIGNAL(triggered()), control, SLOT(increaseMinValue()));
267     a = cm->getAction("A_DecreaseMinBrushThickness");
268     control->addAction(a);
269     QObject::connect(a, SIGNAL(triggered()), control, SLOT(decreaseMinValue()));
270   }
271   hLayout()->addSpacing(5);
272 }
273 
274 //-----------------------------------------------------------------------------
275 
visit(TIntPairProperty * p)276 void ToolOptionControlBuilder::visit(TIntPairProperty *p) {
277   QLabel *label = addLabel(p);
278   m_panel->addLabel(p->getName(), label);
279   ToolOptionIntPairSlider *control = new ToolOptionIntPairSlider(
280       m_tool, p, QObject::tr("Min:"), QObject::tr("Max:"), m_toolHandle);
281   hLayout()->addWidget(control, 100);
282   m_panel->addControl(control);
283   if (p->getName() == "Size:" || p->getName() == "Thickness" ||
284       p->getName() == "Size") {
285     CommandManager *cm = CommandManager::instance();
286     QAction *a;
287     a = cm->getAction("A_IncreaseMaxBrushThickness");
288     control->addAction(a);
289     QObject::connect(a, SIGNAL(triggered()), control, SLOT(increaseMaxValue()));
290     a = cm->getAction("A_DecreaseMaxBrushThickness");
291     control->addAction(a);
292     QObject::connect(a, SIGNAL(triggered()), control, SLOT(decreaseMaxValue()));
293 
294     a = cm->getAction("A_IncreaseMinBrushThickness");
295     control->addAction(a);
296     QObject::connect(a, SIGNAL(triggered()), control, SLOT(increaseMinValue()));
297     a = cm->getAction("A_DecreaseMinBrushThickness");
298     control->addAction(a);
299     QObject::connect(a, SIGNAL(triggered()), control, SLOT(decreaseMinValue()));
300   }
301   hLayout()->addSpacing(5);
302 }
303 
304 //-----------------------------------------------------------------------------
305 
visit(TIntProperty * p)306 void ToolOptionControlBuilder::visit(TIntProperty *p) {
307   QLabel *label = addLabel(p);
308   m_panel->addLabel(p->getName(), label);
309 
310   ToolOptionIntSlider *control =
311       new ToolOptionIntSlider(m_tool, p, m_toolHandle);
312 
313   if (m_singleValueWidgetType == FIELD) {
314     control->enableSlider(false);
315     control->setFixedWidth(45);
316   }
317   hLayout()->addWidget(control, 100);
318   m_panel->addControl(control);
319   if (p->getName() == "Size:") {
320     CommandManager *cm = CommandManager::instance();
321     QAction *a;
322     a = cm->getAction("A_IncreaseMaxBrushThickness");
323     control->addAction(a);
324     QObject::connect(a, SIGNAL(triggered()), control, SLOT(increase()));
325     a = cm->getAction("A_DecreaseMaxBrushThickness");
326     control->addAction(a);
327     QObject::connect(a, SIGNAL(triggered()), control, SLOT(decrease()));
328   }
329   hLayout()->addSpacing(5);
330 }
331 
332 //-----------------------------------------------------------------------------
333 
visit(TBoolProperty * p)334 void ToolOptionControlBuilder::visit(TBoolProperty *p) {
335   ToolOptionCheckbox *control = new ToolOptionCheckbox(m_tool, p, m_toolHandle);
336   hLayout()->addWidget(control, 0);
337 
338   m_panel->addControl(control);
339 
340   if (p->getId() != "") {
341     std::string actionName = "A_ToolOption_" + p->getId();
342     QAction *a = CommandManager::instance()->getAction(actionName.c_str());
343     if (a) {
344       a->setCheckable(true);
345       control->addAction(a);
346       QObject::connect(a, SIGNAL(triggered(bool)), control,
347                        SLOT(doClick(bool)));
348     }
349   }
350   hLayout()->addSpacing(5);
351 }
352 
353 //-----------------------------------------------------------------------------
354 
visit(TStringProperty * p)355 void ToolOptionControlBuilder::visit(TStringProperty *p) {
356   QLabel *label = addLabel(p);
357   m_panel->addLabel(p->getName(), label);
358 
359   ToolOptionTextField *control = new ToolOptionTextField(m_tool, p);
360   m_panel->addControl(control);
361 
362   hLayout()->addWidget(control);
363   hLayout()->addSpacing(5);
364 }
365 
366 //-----------------------------------------------------------------------------
367 
visit(TEnumProperty * p)368 void ToolOptionControlBuilder::visit(TEnumProperty *p) {
369   QWidget *widget;
370   ToolOptionControl *control;
371   switch (m_enumWidgetType) {
372   case POPUPBUTTON: {
373     ToolOptionPopupButton *obj = new ToolOptionPopupButton(m_tool, p);
374     obj->setToolTip(p->getQStringName());
375     control = obj;
376     widget  = obj;
377     break;
378   }
379 
380   case FONTCOMBOBOX: {
381     if (p->getQStringName() != "") {
382       QLabel *label = addLabel(p);
383       m_panel->addLabel(p->getName(), label);
384     }
385     ToolOptionFontCombo *obj = new ToolOptionFontCombo(m_tool, p, m_toolHandle);
386     control                  = obj;
387     widget                   = obj;
388     break;
389   }
390 
391   case COMBOBOX:
392   default: {
393     if (p->getQStringName() != "") {
394       QLabel *label = addLabel(p);
395       m_panel->addLabel(p->getName(), label);
396     }
397     ToolOptionCombo *obj = new ToolOptionCombo(m_tool, p, m_toolHandle);
398     control              = obj;
399     widget               = obj;
400     break;
401   }
402   }
403 
404   hLayout()->addWidget(widget, 100);
405   m_panel->addControl(control);
406   hLayout()->addSpacing(5);
407 
408   if (p->getId() != "") {
409     std::string actionName = "A_ToolOption_" + p->getId();
410     QAction *a = CommandManager::instance()->getAction(actionName.c_str());
411     if (a) {
412       widget->addAction(a);
413       QObject::connect(a, SIGNAL(triggered()), widget, SLOT(doShowPopup()));
414     }
415 
416     TEnumProperty::Range range = p->getRange();
417     TEnumProperty::Range::iterator it;
418     QSignalMapper *signalMapper = 0;
419     int index                   = 0;
420     for (it = range.begin(); it != range.end(); ++it, ++index) {
421       std::string item           = ::to_string(*it);
422       std::string itemActionName = actionName + ":" + item;
423       a = CommandManager::instance()->getAction(itemActionName.c_str());
424       if (a) {
425         widget->addAction(a);
426         if (signalMapper == 0) {
427           signalMapper = new QSignalMapper(widget);
428           QObject::connect(signalMapper, SIGNAL(mapped(int)), widget,
429                            SLOT(doOnActivated(int)));
430         }
431         QObject::connect(a, SIGNAL(triggered()), signalMapper, SLOT(map()));
432         signalMapper->setMapping(a, index);
433       }
434     }
435   }
436 }
437 
438 //-----------------------------------------------------------------------------
439 
visit(TStyleIndexProperty * p)440 void ToolOptionControlBuilder::visit(TStyleIndexProperty *p) {
441   QLabel *label = addLabel(p);
442   m_panel->addLabel(p->getName(), label);
443   StyleIndexFieldAndChip *chip =
444       new StyleIndexFieldAndChip(m_tool, p, m_pltHandle, m_toolHandle);
445   hLayout()->addWidget(chip, 0);
446   m_panel->addControl(chip);
447 }
448 
449 //----------------------------------------------------------------------------------
450 
visit(TPointerProperty * p)451 void ToolOptionControlBuilder::visit(TPointerProperty *p) {
452   assert(!"not implemented");
453 }
454 
455 //=============================================================================
456 // GenericToolOptionsBox
457 
GenericToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,int propertyGroupIdx,ToolHandle * toolHandle,bool scrollable)458 GenericToolOptionsBox::GenericToolOptionsBox(QWidget *parent, TTool *tool,
459                                              TPaletteHandle *pltHandle,
460                                              int propertyGroupIdx,
461                                              ToolHandle *toolHandle,
462                                              bool scrollable)
463     : ToolOptionsBox(parent, scrollable) {
464   setObjectName("toolOptionsPanel");
465 
466   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
467   if (tool && tool->getProperties(propertyGroupIdx))
468     tool->getProperties(propertyGroupIdx)->accept(builder);
469 
470   m_layout->addStretch(1);
471 }
472 
473 //-----------------------------------------------------------------------------
474 
475 // show 17x17 icon without style dependency
476 class SimpleIconViewField : public DraggableIconView {
477   QIcon m_icon;
478 
479 public:
SimpleIconViewField(const QString & iconName,const QString & toolTipStr="",QWidget * parent=0)480   SimpleIconViewField(const QString &iconName, const QString &toolTipStr = "",
481                       QWidget *parent = 0)
482       : DraggableIconView(parent), m_icon(createQIcon(iconName.toUtf8())) {
483     setMinimumSize(18, 18);
484     setToolTip(toolTipStr);
485   }
486 
487 protected:
paintEvent(QPaintEvent * e)488   void paintEvent(QPaintEvent *e) {
489     QPainter p(this);
490     p.drawPixmap(QRect(0, 2, 18, 18), m_icon.pixmap(18, 18));
491   }
492 };
493 
494 //-----------------------------------------------------------------------------
495 
ArrowToolOptionsBox(QWidget * parent,TTool * tool,TPropertyGroup * pg,TFrameHandle * frameHandle,TObjectHandle * objHandle,TXsheetHandle * xshHandle,ToolHandle * toolHandle)496 ArrowToolOptionsBox::ArrowToolOptionsBox(
497     QWidget *parent, TTool *tool, TPropertyGroup *pg, TFrameHandle *frameHandle,
498     TObjectHandle *objHandle, TXsheetHandle *xshHandle, ToolHandle *toolHandle)
499     : ToolOptionsBox(parent, true)
500     , m_pg(pg)
501     , m_splined(false)
502     , m_tool(tool)
503     , m_frameHandle(frameHandle)
504     , m_objHandle(objHandle)
505     , m_xshHandle(xshHandle) {
506   setFrameStyle(QFrame::StyledPanel);
507   setObjectName("toolOptionsPanel");
508   setFixedHeight(26);
509 
510   m_axisOptionWidgets = new QWidget *[AllAxis];
511 
512   /* --- General Parts --- */
513 
514   // enable to choose target pegbar with combobox
515   m_currentStageObjectCombo = new QComboBox(this);
516 
517   TEnumProperty *activeAxisProp =
518       dynamic_cast<TEnumProperty *>(m_pg->getProperty("Active Axis"));
519   if (activeAxisProp)
520     m_chooseActiveAxisCombo =
521         new ToolOptionCombo(m_tool, activeAxisProp, toolHandle);
522   TEnumProperty *autoSelectProp =
523       dynamic_cast<TEnumProperty *>(m_pg->getProperty("Auto Select Column"));
524   if (autoSelectProp)
525     m_pickCombo = new ToolOptionCombo(m_tool, autoSelectProp, toolHandle);
526 
527   m_pickWidget = new QWidget(this);
528 
529   /* --- Position --- */
530   m_motionPathPosField =
531       new PegbarChannelField(m_tool, TStageObject::T_Path, "field", frameHandle,
532                              objHandle, xshHandle, this);
533   m_ewPosField =
534       new PegbarChannelField(m_tool, TStageObject::T_X, "field", frameHandle,
535                              objHandle, xshHandle, this);
536   m_nsPosField =
537       new PegbarChannelField(m_tool, TStageObject::T_Y, "field", frameHandle,
538                              objHandle, xshHandle, this);
539   m_zField        = new PegbarChannelField(m_tool, TStageObject::T_Z, "field",
540                                     frameHandle, objHandle, xshHandle, this);
541   m_noScaleZField = new NoScaleField(m_tool, "field");
542 
543   m_zLabel             = new ClickableLabel(tr("Z:"), this);
544   m_motionPathPosLabel = new ClickableLabel(tr("Position:"), this);
545   m_ewPosLabel         = new ClickableLabel(tr("X:"), this);
546   m_nsPosLabel         = new ClickableLabel(tr("Y:"), this);
547 
548   // Lock X
549   TBoolProperty *lockProp =
550       dynamic_cast<TBoolProperty *>(m_pg->getProperty("Lock Position X"));
551   if (lockProp)
552     m_lockEWPosCheckbox =
553         new ToolOptionCheckbox(m_tool, lockProp, toolHandle, this);
554   // Lock Y
555   lockProp =
556       dynamic_cast<TBoolProperty *>(m_pg->getProperty("Lock Position Y"));
557   if (lockProp)
558     m_lockNSPosCheckbox =
559         new ToolOptionCheckbox(m_tool, lockProp, toolHandle, this);
560   // stacking order
561   m_soLabel = new ClickableLabel(tr("SO:"), this);
562   m_soField = new PegbarChannelField(m_tool, TStageObject::T_SO, "field",
563                                      frameHandle, objHandle, xshHandle, this);
564 
565   /* --- Rotation --- */
566   m_rotationLabel = new ClickableLabel(tr("Rotation:"), this);
567   m_rotationField =
568       new PegbarChannelField(m_tool, TStageObject::T_Angle, "field",
569                              frameHandle, objHandle, xshHandle, this);
570 
571   /* --- Scale --- */
572   m_globalScaleField =
573       new PegbarChannelField(m_tool, TStageObject::T_Scale, "field",
574                              frameHandle, objHandle, xshHandle, this);
575   m_scaleHField =
576       new PegbarChannelField(m_tool, TStageObject::T_ScaleX, "field",
577                              frameHandle, objHandle, xshHandle, this);
578   m_scaleVField =
579       new PegbarChannelField(m_tool, TStageObject::T_ScaleY, "field",
580                              frameHandle, objHandle, xshHandle, this);
581 
582   m_globalScaleLabel = new ClickableLabel(tr("Global:"), this);
583   m_scaleHLabel      = new ClickableLabel(tr("H:"), this);
584   m_scaleVLabel      = new ClickableLabel(tr("V:"), this);
585 
586   TEnumProperty *scaleConstraintProp =
587       dynamic_cast<TEnumProperty *>(m_pg->getProperty("Scale Constraint:"));
588   if (scaleConstraintProp)
589     m_maintainCombo =
590         new ToolOptionCombo(m_tool, scaleConstraintProp, toolHandle);
591   // Lock Scale H
592   lockProp = dynamic_cast<TBoolProperty *>(m_pg->getProperty("Lock Scale H"));
593   if (lockProp)
594     m_lockScaleHCheckbox =
595         new ToolOptionCheckbox(m_tool, lockProp, toolHandle, this);
596   // Lock Scale V
597   lockProp = dynamic_cast<TBoolProperty *>(m_pg->getProperty("Lock Scale V"));
598   if (lockProp)
599     m_lockScaleVCheckbox =
600         new ToolOptionCheckbox(m_tool, lockProp, toolHandle, this);
601 
602   /* --- Shear --- */
603   m_shearHField =
604       new PegbarChannelField(m_tool, TStageObject::T_ShearX, "field",
605                              frameHandle, objHandle, xshHandle, this);
606   m_shearVField =
607       new PegbarChannelField(m_tool, TStageObject::T_ShearY, "field",
608                              frameHandle, objHandle, xshHandle, this);
609   m_shearHLabel = new ClickableLabel(tr("H:"), this);
610   m_shearVLabel = new ClickableLabel(tr("V:"), this);
611 
612   // Lock Shear H
613   lockProp = dynamic_cast<TBoolProperty *>(m_pg->getProperty("Lock Shear H"));
614   if (lockProp)
615     m_lockShearHCheckbox =
616         new ToolOptionCheckbox(m_tool, lockProp, toolHandle, this);
617   // Lock Scale V
618   lockProp = dynamic_cast<TBoolProperty *>(m_pg->getProperty("Lock Shear V"));
619   if (lockProp)
620     m_lockShearVCheckbox =
621         new ToolOptionCheckbox(m_tool, lockProp, toolHandle, this);
622 
623   /* --- Center Position --- */
624   m_ewCenterField =
625       new PegbarCenterField(m_tool, 0, "field", objHandle, xshHandle, this);
626   m_nsCenterField =
627       new PegbarCenterField(m_tool, 1, "field", objHandle, xshHandle, this);
628   m_ewCenterLabel = new ClickableLabel(tr("X:"), this);
629   m_nsCenterLabel = new ClickableLabel(tr("Y:"), this);
630 
631   // Lock X Center
632   lockProp = dynamic_cast<TBoolProperty *>(m_pg->getProperty("Lock Center X"));
633   if (lockProp)
634     m_lockEWCenterCheckbox =
635         new ToolOptionCheckbox(m_tool, lockProp, toolHandle, this);
636   // Lock Y Center
637   lockProp = dynamic_cast<TBoolProperty *>(m_pg->getProperty("Lock Center Y"));
638   if (lockProp)
639     m_lockNSCenterCheckbox =
640         new ToolOptionCheckbox(m_tool, lockProp, toolHandle, this);
641 
642   TBoolProperty *globalKeyProp =
643       dynamic_cast<TBoolProperty *>(m_pg->getProperty("Global Key"));
644   if (globalKeyProp)
645     m_globalKey =
646         new ToolOptionCheckbox(m_tool, globalKeyProp, toolHandle, this);
647 
648   m_lockEWPosCheckbox->setObjectName("EditToolLockButton");
649   m_lockNSPosCheckbox->setObjectName("EditToolLockButton");
650   m_lockEWCenterCheckbox->setObjectName("EditToolLockButton");
651   m_lockNSCenterCheckbox->setObjectName("EditToolLockButton");
652   m_lockScaleHCheckbox->setObjectName("EditToolLockButton");
653   m_lockScaleVCheckbox->setObjectName("EditToolLockButton");
654   m_lockShearHCheckbox->setObjectName("EditToolLockButton");
655   m_lockShearVCheckbox->setObjectName("EditToolLockButton");
656   m_lockEWPosCheckbox->setText("");
657   m_lockNSPosCheckbox->setText("");
658   m_lockEWCenterCheckbox->setText("");
659   m_lockNSCenterCheckbox->setText("");
660   m_lockScaleHCheckbox->setText("");
661   m_lockScaleVCheckbox->setText("");
662   m_lockShearHCheckbox->setText("");
663   m_lockShearVCheckbox->setText("");
664 
665   m_zField->setPrecision(4);
666   m_noScaleZField->setPrecision(4);
667 
668   bool splined = isCurrentObjectSplined();
669   if (splined != m_splined) m_splined = splined;
670   setSplined(m_splined);
671 
672   const int ITEM_SPACING  = 10;
673   const int LABEL_SPACING = 3;
674   /* --- Layout --- */
675   QHBoxLayout *mainLay = m_layout;
676   {
677     mainLay->addWidget(m_currentStageObjectCombo, 0);
678     mainLay->addWidget(m_chooseActiveAxisCombo, 0);
679 
680     // Pick combobox only available on "All" axis mode
681     QHBoxLayout *pickLay = new QHBoxLayout();
682     pickLay->setMargin(0);
683     pickLay->setSpacing(0);
684     {
685       pickLay->addSpacing(5);
686       pickLay->addWidget(new QLabel(tr("Pick:"), this), 0);
687       pickLay->addWidget(m_pickCombo, 0);
688     }
689     m_pickWidget->setLayout(pickLay);
690     mainLay->addWidget(m_pickWidget, 0);
691 
692     addSeparator();
693 
694     {
695       // Position
696       QFrame *posFrame    = new QFrame(this);
697       QHBoxLayout *posLay = new QHBoxLayout();
698       posLay->setMargin(0);
699       posLay->setSpacing(0);
700       posFrame->setLayout(posLay);
701       {
702         posLay->addWidget(
703             new SimpleIconViewField("edit_position", tr("Position"), this), 0);
704         posLay->addSpacing(LABEL_SPACING * 2);
705         posLay->addWidget(m_motionPathPosLabel, 0);
706         posLay->addWidget(m_motionPathPosField, 0);
707 
708         posLay->addWidget(m_ewPosLabel, 0);
709         posLay->addSpacing(LABEL_SPACING);
710         posLay->addWidget(m_ewPosField, 10);
711         posLay->addWidget(m_lockEWPosCheckbox, 0);
712 
713         posLay->addSpacing(ITEM_SPACING);
714 
715         posLay->addWidget(m_nsPosLabel, 0);
716         posLay->addSpacing(LABEL_SPACING);
717         posLay->addWidget(m_nsPosField, 10);
718         posLay->addWidget(m_lockNSPosCheckbox, 0);
719 
720         posLay->addSpacing(ITEM_SPACING);
721 
722         posLay->addWidget(m_zLabel, 0);
723         posLay->addSpacing(LABEL_SPACING);
724         posLay->addWidget(m_zField, 10);
725         posLay->addSpacing(LABEL_SPACING);
726         posLay->addWidget(new QLabel(tr("("), this), 0);
727         posLay->addWidget(m_noScaleZField, 10);
728         posLay->addWidget(new QLabel(tr(")"), this), 0);
729 
730         posLay->addSpacing(ITEM_SPACING);
731 
732         posLay->addWidget(m_soLabel, 0);
733         posLay->addWidget(m_soField, 10);
734 
735         posLay->addSpacing(ITEM_SPACING);
736         posLay->addWidget(new DVGui::Separator("", this, false));
737 
738         posLay->addStretch(1);
739       }
740       m_axisOptionWidgets[Position] = posFrame;
741       mainLay->addWidget(m_axisOptionWidgets[Position], 0);
742 
743       // Rotation
744       QFrame *rotFrame    = new QFrame(this);
745       QHBoxLayout *rotLay = new QHBoxLayout();
746       rotLay->setMargin(0);
747       rotLay->setSpacing(0);
748       rotFrame->setLayout(rotLay);
749       {
750         rotLay->addWidget(
751             new SimpleIconViewField("edit_rotation", tr("Rotation"), this), 0);
752         rotLay->addSpacing(LABEL_SPACING * 2);
753         rotLay->addWidget(m_rotationLabel, 0);
754         rotLay->addSpacing(LABEL_SPACING);
755         rotLay->addWidget(m_rotationField, 10);
756 
757         rotLay->addSpacing(ITEM_SPACING);
758         rotLay->addWidget(new DVGui::Separator("", this, false));
759 
760         rotLay->addStretch(1);
761       }
762       m_axisOptionWidgets[Rotation] = rotFrame;
763       mainLay->addWidget(m_axisOptionWidgets[Rotation], 0);
764 
765       // Scale
766       QFrame *scaleFrame    = new QFrame(this);
767       QHBoxLayout *scaleLay = new QHBoxLayout();
768       scaleLay->setMargin(0);
769       scaleLay->setSpacing(0);
770       scaleFrame->setLayout(scaleLay);
771       {
772         scaleLay->addWidget(
773             new SimpleIconViewField("edit_scale", tr("Scale"), this), 0);
774         scaleLay->addSpacing(LABEL_SPACING * 2);
775 
776         scaleLay->addWidget(m_globalScaleLabel, 0);
777         scaleLay->addSpacing(LABEL_SPACING);
778         scaleLay->addWidget(m_globalScaleField, 10);
779 
780         scaleLay->addSpacing(ITEM_SPACING);
781 
782         scaleLay->addWidget(m_scaleHLabel, 0);
783         scaleLay->addSpacing(LABEL_SPACING);
784         scaleLay->addWidget(m_scaleHField, 10);
785         scaleLay->addWidget(m_lockScaleHCheckbox, 0);
786 
787         scaleLay->addSpacing(ITEM_SPACING);
788 
789         scaleLay->addWidget(m_scaleVLabel, 0);
790         scaleLay->addSpacing(LABEL_SPACING);
791         scaleLay->addWidget(m_scaleVField, 10);
792         scaleLay->addWidget(m_lockScaleVCheckbox, 0);
793 
794         scaleLay->addSpacing(ITEM_SPACING);
795 
796         scaleLay->addWidget(new QLabel(tr("Maintain:"), this), 0);
797         scaleLay->addSpacing(LABEL_SPACING);
798         scaleLay->addWidget(m_maintainCombo, 0);
799 
800         scaleLay->addSpacing(ITEM_SPACING);
801         scaleLay->addWidget(new DVGui::Separator("", this, false));
802 
803         scaleLay->addStretch(1);
804       }
805       m_axisOptionWidgets[Scale] = scaleFrame;
806       mainLay->addWidget(m_axisOptionWidgets[Scale], 0);
807 
808       // Shear
809       QFrame *shearFrame    = new QFrame(this);
810       QHBoxLayout *shearLay = new QHBoxLayout();
811       shearLay->setMargin(0);
812       shearLay->setSpacing(0);
813       shearFrame->setLayout(shearLay);
814       {
815         shearLay->addWidget(
816             new SimpleIconViewField("edit_shear", tr("Shear"), this), 0);
817         shearLay->addSpacing(LABEL_SPACING * 2);
818 
819         shearLay->addWidget(m_shearHLabel, 0);
820         shearLay->addSpacing(LABEL_SPACING);
821         shearLay->addWidget(m_shearHField, 10);
822         shearLay->addWidget(m_lockShearHCheckbox, 0);
823 
824         shearLay->addSpacing(ITEM_SPACING);
825 
826         shearLay->addWidget(m_shearVLabel, 0);
827         shearLay->addSpacing(LABEL_SPACING);
828         shearLay->addWidget(m_shearVField, 10);
829         shearLay->addWidget(m_lockShearVCheckbox, 0);
830 
831         shearLay->addSpacing(ITEM_SPACING);
832 
833         shearLay->addWidget(new DVGui::Separator("", this, false));
834 
835         shearLay->addStretch(1);
836       }
837       m_axisOptionWidgets[Shear] = shearFrame;
838       mainLay->addWidget(m_axisOptionWidgets[Shear], 0);
839 
840       // Center Position
841       QFrame *centerPosFrame    = new QFrame(this);
842       QHBoxLayout *centerPosLay = new QHBoxLayout();
843       centerPosLay->setMargin(0);
844       centerPosLay->setSpacing(0);
845       centerPosFrame->setLayout(centerPosLay);
846       {
847         centerPosLay->addWidget(
848             new SimpleIconViewField("edit_center", tr("Center Position"), this),
849             0);
850         centerPosLay->addSpacing(LABEL_SPACING * 2);
851 
852         centerPosLay->addWidget(m_ewCenterLabel, 0);
853         centerPosLay->addSpacing(LABEL_SPACING);
854         centerPosLay->addWidget(m_ewCenterField, 10);
855         centerPosLay->addWidget(m_lockEWCenterCheckbox, 0);
856 
857         centerPosLay->addSpacing(ITEM_SPACING);
858 
859         centerPosLay->addWidget(m_nsCenterLabel, 0);
860         centerPosLay->addSpacing(LABEL_SPACING);
861         centerPosLay->addWidget(m_nsCenterField, 10);
862         centerPosLay->addWidget(m_lockNSCenterCheckbox, 0);
863 
864         centerPosLay->addSpacing(ITEM_SPACING);
865         centerPosLay->addWidget(new DVGui::Separator("", this, false));
866 
867         centerPosLay->addStretch(1);
868       }
869       m_axisOptionWidgets[CenterPosition] = centerPosFrame;
870       mainLay->addWidget(m_axisOptionWidgets[CenterPosition], 0);
871     }
872 
873     mainLay->addWidget(m_globalKey, 0);
874 
875     mainLay->addSpacing(ITEM_SPACING);
876   }
877 
878   /* --- signal-slot connections --- */
879   // swap page when the active axis is changed
880   connect(m_chooseActiveAxisCombo, SIGNAL(currentIndexChanged(int)), this,
881           SLOT(onCurrentAxisChanged(int)));
882   // when the current stage object is changed via combo box, then switch the
883   // current stage object in the scene
884   connect(m_currentStageObjectCombo, SIGNAL(activated(int)), this,
885           SLOT(onCurrentStageObjectComboActivated(int)));
886 
887   /* --- Assigning shortcut keys --- */
888   if (activeAxisProp->getId() != "") {
889     std::string actionName = "A_ToolOption_" + activeAxisProp->getId();
890     QAction *a = CommandManager::instance()->getAction(actionName.c_str());
891 
892     if (a) {
893       m_chooseActiveAxisCombo->addAction(a);
894       QObject::connect(a, SIGNAL(triggered()), m_chooseActiveAxisCombo,
895                        SLOT(doShowPopup()));
896     }
897 
898     TEnumProperty::Range range = activeAxisProp->getRange();
899     TEnumProperty::Range::iterator it;
900     QSignalMapper *signalMapper = 0;
901     int index                   = 0;
902     for (it = range.begin(); it != range.end(); ++it, ++index) {
903       std::string item           = ::to_string(*it);
904       std::string itemActionName = actionName + ":" + item;
905       a = CommandManager::instance()->getAction(itemActionName.c_str());
906       if (a) {
907         m_chooseActiveAxisCombo->addAction(a);
908         if (signalMapper == 0) {
909           signalMapper = new QSignalMapper(m_chooseActiveAxisCombo);
910           QObject::connect(signalMapper, SIGNAL(mapped(int)),
911                            m_chooseActiveAxisCombo, SLOT(doOnActivated(int)));
912         }
913         QObject::connect(a, SIGNAL(triggered()), signalMapper, SLOT(map()));
914         signalMapper->setMapping(a, index);
915       }
916     }
917   }
918 
919   if (scaleConstraintProp) {
920     m_scaleHField->onScaleTypeChanged(m_maintainCombo->currentIndex());
921     m_scaleVField->onScaleTypeChanged(m_maintainCombo->currentIndex());
922     connect(m_maintainCombo, SIGNAL(currentIndexChanged(int)), m_scaleHField,
923             SLOT(onScaleTypeChanged(int)));
924     connect(m_maintainCombo, SIGNAL(currentIndexChanged(int)), m_scaleVField,
925             SLOT(onScaleTypeChanged(int)));
926   }
927 
928   // enables adjusting value by dragging on the label
929   connectLabelAndField(m_motionPathPosLabel, m_motionPathPosField);
930   connectLabelAndField(m_ewPosLabel, m_ewPosField);
931   connectLabelAndField(m_nsPosLabel, m_nsPosField);
932   connectLabelAndField(m_zLabel, m_zField);
933   connectLabelAndField(m_soLabel, m_soField);
934   connectLabelAndField(m_rotationLabel, m_rotationField);
935   connectLabelAndField(m_globalScaleLabel, m_globalScaleField);
936   connectLabelAndField(m_scaleHLabel, m_scaleHField);
937   connectLabelAndField(m_scaleVLabel, m_scaleVField);
938   connectLabelAndField(m_shearHLabel, m_shearHField);
939   connectLabelAndField(m_shearVLabel, m_shearVField);
940   connectLabelAndField(m_ewCenterLabel, m_ewCenterField);
941   connectLabelAndField(m_nsCenterLabel, m_nsCenterField);
942 
943   if (globalKeyProp) {
944     std::string actionName = "A_ToolOption_" + globalKeyProp->getId();
945     QAction *a = CommandManager::instance()->getAction(actionName.c_str());
946     if (a) {
947       a->setCheckable(true);
948       m_globalKey->addAction(a);
949       connect(a, SIGNAL(triggered(bool)), m_globalKey, SLOT(doClick(bool)));
950     }
951   }
952 
953   onCurrentAxisChanged(activeAxisProp->getIndex());
954 }
955 
956 //-----------------------------------------------------------------------------
957 // enables adjusting value by dragging on the label
958 
connectLabelAndField(ClickableLabel * label,MeasuredValueField * field)959 void ArrowToolOptionsBox::connectLabelAndField(ClickableLabel *label,
960                                                MeasuredValueField *field) {
961   connect(label, SIGNAL(onMousePress(QMouseEvent *)), field,
962           SLOT(receiveMousePress(QMouseEvent *)));
963   connect(label, SIGNAL(onMouseMove(QMouseEvent *)), field,
964           SLOT(receiveMouseMove(QMouseEvent *)));
965   connect(label, SIGNAL(onMouseRelease(QMouseEvent *)), field,
966           SLOT(receiveMouseRelease(QMouseEvent *)));
967 }
968 
969 //-----------------------------------------------------------------------------
970 
showEvent(QShowEvent *)971 void ArrowToolOptionsBox::showEvent(QShowEvent *) {
972   connect(m_frameHandle, SIGNAL(frameSwitched()), SLOT(onFrameSwitched()));
973   // if some stage object is added/removed, then reflect it to the combobox
974   connect(m_xshHandle, SIGNAL(xsheetSwitched()), this,
975           SLOT(updateStageObjectComboItems()));
976   connect(m_xshHandle, SIGNAL(xsheetChanged()), this,
977           SLOT(updateStageObjectComboItems()));
978   // If the current stage object is switched, then synchronize it to the
979   // combobox
980   connect(m_objHandle, SIGNAL(objectSwitched()), this,
981           SLOT(syncCurrentStageObjectComboItem()));
982 
983   // update the item list in m_currentStageObjectCombo
984   updateStageObjectComboItems();
985 }
986 
987 //-----------------------------------------------------------------------------
988 
hideEvent(QShowEvent *)989 void ArrowToolOptionsBox::hideEvent(QShowEvent *) {
990   disconnect(m_frameHandle, SIGNAL(frameSwitched()), this,
991              SLOT(onFrameSwitched()));
992 
993   disconnect(m_xshHandle, SIGNAL(xsheetSwitched()), this,
994              SLOT(updateStageObjectComboItems()));
995   disconnect(m_xshHandle, SIGNAL(xsheetChanged()), this,
996              SLOT(updateStageObjectComboItems()));
997   disconnect(m_objHandle, SIGNAL(objectSwitched()), this,
998              SLOT(syncCurrentStageObjectComboItem()));
999 }
1000 
1001 //-----------------------------------------------------------------------------
1002 
setSplined(bool on)1003 void ArrowToolOptionsBox::setSplined(bool on) {
1004   m_splined = on;
1005   // Activate on selecting spline
1006   m_motionPathPosLabel->setVisible(on);
1007   m_motionPathPosField->setVisible(on);
1008   // DEactivate on selecting spline
1009   m_ewPosField->setVisible(!on);
1010   m_nsPosField->setVisible(!on);
1011   m_ewPosLabel->setVisible(!on);
1012   m_nsPosLabel->setVisible(!on);
1013   m_lockEWPosCheckbox->setVisible(!on);
1014   m_lockNSPosCheckbox->setVisible(!on);
1015 }
1016 
1017 //-----------------------------------------------------------------------------
1018 
isCurrentObjectSplined() const1019 bool ArrowToolOptionsBox::isCurrentObjectSplined() const {
1020   TStageObjectId objId = m_objHandle->getObjectId();
1021   return m_xshHandle->getXsheet()->getStageObject(objId)->getSpline() != 0;
1022 }
1023 
1024 //-----------------------------------------------------------------------------
1025 
updateStatus()1026 void ArrowToolOptionsBox::updateStatus() {
1027   // General
1028   m_chooseActiveAxisCombo->updateStatus();
1029   m_pickCombo->updateStatus();
1030 
1031   // Position
1032   m_motionPathPosField->updateStatus();
1033   m_ewPosField->updateStatus();
1034   m_nsPosField->updateStatus();
1035   m_zField->updateStatus();
1036   m_noScaleZField->updateStatus();
1037   m_soField->updateStatus();
1038 
1039   // Rotation
1040   m_rotationField->updateStatus();
1041 
1042   // Scale
1043   m_globalScaleField->updateStatus();
1044   m_scaleHField->updateStatus();
1045   m_scaleVField->updateStatus();
1046   m_maintainCombo->updateStatus();
1047 
1048   // Shear
1049   m_shearHField->updateStatus();
1050   m_shearVField->updateStatus();
1051 
1052   // Center Position
1053   m_ewCenterField->updateStatus();
1054   m_nsCenterField->updateStatus();
1055 
1056   bool splined = isCurrentObjectSplined();
1057   if (splined != m_splined) setSplined(splined);
1058 }
1059 
1060 //-----------------------------------------------------------------------------
1061 
onStageObjectChange()1062 void ArrowToolOptionsBox::onStageObjectChange() { updateStatus(); }
1063 
1064 //-----------------------------------------------------------------------------
1065 /*! update the object list in combobox
1066  */
updateStageObjectComboItems()1067 void ArrowToolOptionsBox::updateStageObjectComboItems() {
1068   // clear items
1069   m_currentStageObjectCombo->clear();
1070 
1071   TXsheet *xsh = m_xshHandle->getXsheet();
1072 
1073   TStageObjectId id;
1074   for (int i = 0; i < xsh->getStageObjectTree()->getStageObjectCount(); i++) {
1075     id = xsh->getStageObjectTree()->getStageObject(i)->getId();
1076     if (id.isColumn()) {
1077       int columnIndex = id.getIndex();
1078       if (xsh->isColumnEmpty(columnIndex)) continue;
1079     }
1080 
1081     TStageObject *pegbar = xsh->getStageObject(id);
1082     QString itemName     = (id.isTable())
1083                            ? tr("Table")
1084                            : QString::fromStdString(pegbar->getName());
1085     // store the item with ObjectId data
1086     m_currentStageObjectCombo->addItem(itemName, (int)id.getCode());
1087   }
1088 
1089   // synchronize
1090   syncCurrentStageObjectComboItem();
1091 }
1092 
1093 //------------------------------------------------------------------------------
1094 /*! syncronize the current item in the combobox to the selected stage object
1095  */
syncCurrentStageObjectComboItem()1096 void ArrowToolOptionsBox::syncCurrentStageObjectComboItem() {
1097   TStageObjectId curObjId = m_objHandle->getObjectId();
1098 
1099   int index = m_currentStageObjectCombo->findData((int)curObjId.getCode());
1100 
1101   // if the item is found
1102   if (index >= 0) m_currentStageObjectCombo->setCurrentIndex(index);
1103   // if not found, add a new item. (This may happens when selecting the empty
1104   // column.)
1105   else {
1106     TStageObject *pegbar = m_xshHandle->getXsheet()->getStageObject(curObjId);
1107     QString itemName     = QString::fromStdString(pegbar->getName());
1108     // store the item with ObjectId data
1109     m_currentStageObjectCombo->addItem(itemName, (int)curObjId.getCode());
1110     // move the current index to it
1111     m_currentStageObjectCombo->setCurrentIndex(
1112         m_currentStageObjectCombo->findText(itemName));
1113   }
1114 }
1115 
1116 //------------------------------------------------------------------------------
1117 /*!change the current stage object when user changes it via combobox by hand
1118  */
onCurrentStageObjectComboActivated(int index)1119 void ArrowToolOptionsBox::onCurrentStageObjectComboActivated(int index) {
1120   int code = m_currentStageObjectCombo->itemData(index).toInt();
1121   TStageObjectId id;
1122   id.setCode(code);
1123   if (id == TStageObjectId::NoneId) {
1124     std::cout << "Warning: "
1125                  "ArrowToolOptionsBox::onCurrentStageObjectComboActivated \nNo "
1126                  "stage object linked to the selected item found in the scene."
1127               << std::endl;
1128     return;
1129   }
1130   // switch the current object
1131   m_objHandle->setObjectId(id);
1132   if (id.isCamera()) {
1133     TXsheet *xsh = m_xshHandle->getXsheet();
1134     if (xsh->getCameraColumnIndex() != id.getIndex())
1135       m_xshHandle->changeXsheetCamera(id.getIndex());
1136   }
1137 }
1138 
1139 //------------------------------------------------------------------------------
1140 
onCurrentAxisChanged(int axisId)1141 void ArrowToolOptionsBox::onCurrentAxisChanged(int axisId) {
1142   // Show the specified axis options, hide all the others
1143   for (int a = 0; a != AllAxis; ++a)
1144     m_axisOptionWidgets[a]->setVisible(a == axisId || axisId == AllAxis);
1145 
1146   m_pickWidget->setVisible(axisId == AllAxis);
1147 }
1148 
1149 //=============================================================================
1150 //
1151 // SelectionToolOptionsBox
1152 //
1153 //=============================================================================
1154 
IconViewField(QWidget * parent,IconType iconType)1155 IconViewField::IconViewField(QWidget *parent, IconType iconType)
1156     : DraggableIconView(parent), m_iconType(iconType) {
1157   setMinimumSize(21, 25);
1158 }
1159 
paintEvent(QPaintEvent * e)1160 void IconViewField::paintEvent(QPaintEvent *e) {
1161   QPainter p(this);
1162   // La pixmap e' alta 17 px, il widget 23. Per centrarla faccio il draw a 3 px.
1163   p.drawPixmap(QRect(0, 3, 21, 17), m_pm[m_iconType]);
1164 }
1165 
mousePressEvent(QMouseEvent * event)1166 void DraggableIconView::mousePressEvent(QMouseEvent *event) {
1167   emit onMousePress(event);
1168 }
1169 
mouseMoveEvent(QMouseEvent * event)1170 void DraggableIconView::mouseMoveEvent(QMouseEvent *event) {
1171   emit onMouseMove(event);
1172 }
1173 
mouseReleaseEvent(QMouseEvent * event)1174 void DraggableIconView::mouseReleaseEvent(QMouseEvent *event) {
1175   emit onMouseRelease(event);
1176 }
1177 
1178 //-----------------------------------------------------------------------------
1179 
SelectionToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)1180 SelectionToolOptionsBox::SelectionToolOptionsBox(QWidget *parent, TTool *tool,
1181                                                  TPaletteHandle *pltHandle,
1182                                                  ToolHandle *toolHandle)
1183     : ToolOptionsBox(parent)
1184     , m_tool(tool)
1185     , m_isVectorSelction(false)
1186     , m_setSaveboxCheckbox(0) {
1187   TPropertyGroup *props = tool->getProperties(0);
1188   assert(props->getPropertyCount() > 0);
1189 
1190   RasterSelectionTool *rasterSelectionTool =
1191       dynamic_cast<RasterSelectionTool *>(tool);
1192 
1193   SelectionTool *selectionTool = dynamic_cast<SelectionTool *>(tool);
1194 
1195   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
1196   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
1197 
1198   m_scaleXLabel = new ClickableLabel(tr("H:"), this);
1199   m_scaleXField = new SelectionScaleField(selectionTool, 0, "Scale X");
1200   m_scaleYLabel = new ClickableLabel(tr("V:"), this);
1201   m_scaleYField = new SelectionScaleField(selectionTool, 1, "Scale Y");
1202   m_scaleLink   = new DVGui::CheckBox(tr("Link"), this);
1203 
1204   SimpleIconViewField *rotIconView =
1205       new SimpleIconViewField("edit_rotation", tr("Rotation"));
1206   m_rotationField = new SelectionRotationField(selectionTool, tr("Rotation"));
1207 
1208   m_moveXLabel = new ClickableLabel(tr("X:"), this);
1209   m_moveXField = new SelectionMoveField(selectionTool, 0, "Move X");
1210   m_moveYLabel = new ClickableLabel(tr("Y:"), this);
1211   m_moveYField = new SelectionMoveField(selectionTool, 1, "Move Y");
1212 
1213   if (rasterSelectionTool) {
1214     TBoolProperty *modifySetSaveboxProp =
1215         rasterSelectionTool->getModifySaveboxProperty();
1216     if (modifySetSaveboxProp)
1217       m_setSaveboxCheckbox =
1218           new ToolOptionCheckbox(rasterSelectionTool, modifySetSaveboxProp);
1219   }
1220 
1221   m_scaleXLabel->setEnabled(false);
1222   m_scaleYLabel->setEnabled(false);
1223   m_moveXLabel->setEnabled(false);
1224   m_moveYLabel->setEnabled(false);
1225 
1226   //--- layout ----
1227 
1228   addSeparator();
1229 
1230   hLayout()->addWidget(new SimpleIconViewField("edit_scale", tr("Scale"), this),
1231                        0);
1232   hLayout()->addWidget(m_scaleXLabel, 0);
1233   hLayout()->addWidget(m_scaleXField, 10);
1234   hLayout()->addWidget(m_scaleYLabel, 0);
1235   hLayout()->addWidget(m_scaleYField, 10);
1236   hLayout()->addSpacing(4);
1237   hLayout()->addWidget(m_scaleLink, 0);
1238 
1239   addSeparator();
1240 
1241   hLayout()->addWidget(rotIconView, 0);
1242   hLayout()->addWidget(m_rotationField, 10);
1243 
1244   addSeparator();
1245 
1246   hLayout()->addWidget(
1247       new SimpleIconViewField("edit_position", tr("Position"), this), 0);
1248   hLayout()->addWidget(m_moveXLabel, 0);
1249   hLayout()->addWidget(m_moveXField, 10);
1250   hLayout()->addWidget(m_moveYLabel, 0);
1251   hLayout()->addWidget(m_moveYField, 10);
1252   if (m_setSaveboxCheckbox) {
1253     addSeparator();
1254     hLayout()->addWidget(m_setSaveboxCheckbox, 0);
1255   }
1256 
1257   VectorSelectionTool *vectorSelectionTool =
1258       dynamic_cast<VectorSelectionTool *>(tool);
1259   if (vectorSelectionTool) {
1260     m_isVectorSelction = true;
1261 
1262     // change Thick
1263     SimpleIconViewField *thicknessIconView =
1264         new SimpleIconViewField("thickness", tr("Thickness"), this);
1265     m_thickChangeField = new ThickChangeField(selectionTool, tr("Thickness"));
1266 
1267     connect(thicknessIconView, SIGNAL(onMousePress(QMouseEvent *)),
1268             m_thickChangeField, SLOT(receiveMousePress(QMouseEvent *)));
1269     connect(thicknessIconView, SIGNAL(onMouseMove(QMouseEvent *)),
1270             m_thickChangeField, SLOT(receiveMouseMove(QMouseEvent *)));
1271     connect(thicknessIconView, SIGNAL(onMouseRelease(QMouseEvent *)),
1272             m_thickChangeField, SLOT(receiveMouseRelease(QMouseEvent *)));
1273 
1274     addSeparator();
1275     hLayout()->addWidget(thicknessIconView, 0);
1276     hLayout()->addWidget(m_thickChangeField, 10);
1277     // Outline options
1278     ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
1279     builder.setEnumWidgetType(ToolOptionControlBuilder::POPUPBUTTON);
1280     builder.setSingleValueWidgetType(ToolOptionControlBuilder::FIELD);
1281 
1282     addSeparator();
1283     if (tool && tool->getProperties(1)) tool->getProperties(1)->accept(builder);
1284 
1285     m_capStyle = dynamic_cast<ToolOptionPopupButton *>(m_controls.value("Cap"));
1286     m_joinStyle =
1287         dynamic_cast<ToolOptionPopupButton *>(m_controls.value("Join"));
1288 
1289     m_miterField =
1290         dynamic_cast<ToolOptionIntSlider *>(m_controls.value("Miter:"));
1291     m_miterField->setEnabled(m_joinStyle->currentIndex() ==
1292                              TStroke::OutlineOptions::MITER_JOIN);
1293 
1294     onPropertyChanged();
1295   }
1296 
1297   hLayout()->addStretch(1);
1298   // assert(ret);
1299   bool ret = connect(m_scaleXField, SIGNAL(valueChange(bool)),
1300                      SLOT(onScaleXValueChanged(bool)));
1301   ret      = ret && connect(m_scaleYField, SIGNAL(valueChange(bool)),
1302                        SLOT(onScaleYValueChanged(bool)));
1303   if (m_setSaveboxCheckbox)
1304     ret = ret && connect(m_setSaveboxCheckbox, SIGNAL(toggled(bool)),
1305                          SLOT(onSetSaveboxCheckboxChanged(bool)));
1306   connect(m_scaleXLabel, SIGNAL(onMousePress(QMouseEvent *)), m_scaleXField,
1307           SLOT(receiveMousePress(QMouseEvent *)));
1308   connect(m_scaleXLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_scaleXField,
1309           SLOT(receiveMouseMove(QMouseEvent *)));
1310   connect(m_scaleXLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_scaleXField,
1311           SLOT(receiveMouseRelease(QMouseEvent *)));
1312   connect(m_scaleYLabel, SIGNAL(onMousePress(QMouseEvent *)), m_scaleYField,
1313           SLOT(receiveMousePress(QMouseEvent *)));
1314   connect(m_scaleYLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_scaleYField,
1315           SLOT(receiveMouseMove(QMouseEvent *)));
1316   connect(m_scaleYLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_scaleYField,
1317           SLOT(receiveMouseRelease(QMouseEvent *)));
1318   connect(rotIconView, SIGNAL(onMousePress(QMouseEvent *)), m_rotationField,
1319           SLOT(receiveMousePress(QMouseEvent *)));
1320   connect(rotIconView, SIGNAL(onMouseMove(QMouseEvent *)), m_rotationField,
1321           SLOT(receiveMouseMove(QMouseEvent *)));
1322   connect(rotIconView, SIGNAL(onMouseRelease(QMouseEvent *)), m_rotationField,
1323           SLOT(receiveMouseRelease(QMouseEvent *)));
1324   connect(m_moveXLabel, SIGNAL(onMousePress(QMouseEvent *)), m_moveXField,
1325           SLOT(receiveMousePress(QMouseEvent *)));
1326   connect(m_moveXLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_moveXField,
1327           SLOT(receiveMouseMove(QMouseEvent *)));
1328   connect(m_moveXLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_moveXField,
1329           SLOT(receiveMouseRelease(QMouseEvent *)));
1330   connect(m_moveYLabel, SIGNAL(onMousePress(QMouseEvent *)), m_moveYField,
1331           SLOT(receiveMousePress(QMouseEvent *)));
1332   connect(m_moveYLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_moveYField,
1333           SLOT(receiveMouseMove(QMouseEvent *)));
1334   connect(m_moveYLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_moveYField,
1335           SLOT(receiveMouseRelease(QMouseEvent *)));
1336   // assert(ret);
1337 
1338   updateStatus();
1339 }
1340 
1341 //-----------------------------------------------------------------------------
1342 
updateStatus()1343 void SelectionToolOptionsBox::updateStatus() {
1344   QMap<std::string, ToolOptionControl *>::iterator it;
1345   for (it = m_controls.begin(); it != m_controls.end(); it++)
1346     it.value()->updateStatus();
1347 
1348   if (m_setSaveboxCheckbox) {
1349     bool disable = m_setSaveboxCheckbox->checkState() == Qt::Checked;
1350     for (int i = 0; i < hLayout()->count(); i++) {
1351       QWidget *w = hLayout()->itemAt(i)->widget();
1352       if (w && w != m_setSaveboxCheckbox) w->setEnabled(!disable);
1353     }
1354     if (disable) return;
1355   }
1356 
1357   m_scaleXField->updateStatus();
1358   m_scaleXLabel->setEnabled(m_scaleXField->isEnabled());
1359   m_scaleYField->updateStatus();
1360   m_scaleYLabel->setEnabled(m_scaleXField->isEnabled());
1361   m_rotationField->updateStatus();
1362   m_moveXField->updateStatus();
1363   m_moveXLabel->setEnabled(m_moveXField->isEnabled());
1364   m_moveYField->updateStatus();
1365   m_moveYLabel->setEnabled(m_moveYField->isEnabled());
1366 
1367   if (m_isVectorSelction) {
1368     m_thickChangeField->updateStatus();
1369     onPropertyChanged();
1370   }
1371 }
1372 
1373 //-----------------------------------------------------------------------------
1374 
onScaleXValueChanged(bool addToUndo)1375 void SelectionToolOptionsBox::onScaleXValueChanged(bool addToUndo) {
1376   if (!m_scaleLink->isChecked() ||
1377       m_scaleXField->getValue() == m_scaleYField->getValue())
1378     return;
1379   m_scaleYField->setValue(m_scaleXField->getValue());
1380   m_scaleYField->applyChange(addToUndo);
1381 }
1382 
1383 //-----------------------------------------------------------------------------
1384 
onScaleYValueChanged(bool addToUndo)1385 void SelectionToolOptionsBox::onScaleYValueChanged(bool addToUndo) {
1386   if (!m_scaleLink->isChecked() ||
1387       m_scaleXField->getValue() == m_scaleYField->getValue())
1388     return;
1389   m_scaleXField->setValue(m_scaleYField->getValue());
1390   m_scaleXField->applyChange(addToUndo);
1391 }
1392 
1393 //-----------------------------------------------------------------------------
1394 
onSetSaveboxCheckboxChanged(bool)1395 void SelectionToolOptionsBox::onSetSaveboxCheckboxChanged(bool) {
1396   updateStatus();
1397 }
1398 
1399 //-----------------------------------------------------------------------------
1400 
onPropertyChanged()1401 void SelectionToolOptionsBox::onPropertyChanged() {
1402   // Check the selection's outline styles group.
1403   VectorSelectionTool *tool = (VectorSelectionTool *)m_tool;
1404 
1405   int capStyle, joinStyle;
1406   tool->selectionOutlineStyle(capStyle, joinStyle);
1407 
1408   // Show a void icon when no homogeneous style is found
1409   if (capStyle < 0)
1410     m_capStyle->setIcon(QPixmap());
1411   else
1412     // m_capStyle->setIcon(m_capStyle->currentItem()->icon());
1413     m_capStyle->setCurrentIndex(capStyle);
1414 
1415   if (joinStyle < 0)
1416     m_joinStyle->setIcon(QPixmap());
1417   else
1418     m_joinStyle->setCurrentIndex(joinStyle);
1419   // m_joinStyle->setIcon(m_joinStyle->currentItem()->icon());
1420 
1421   // Enable the miter field only in case the join is of type miter
1422   m_miterField->setEnabled(joinStyle == TStroke::OutlineOptions::MITER_JOIN);
1423 }
1424 
1425 //=============================================================================
1426 //
1427 // GeometricToolOptionsBox
1428 //
1429 //=============================================================================
1430 
GeometricToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)1431 GeometricToolOptionsBox::GeometricToolOptionsBox(QWidget *parent, TTool *tool,
1432                                                  TPaletteHandle *pltHandle,
1433                                                  ToolHandle *toolHandle)
1434     : ToolOptionsBox(parent)
1435     , m_targetType(tool->getTargetType())
1436     , m_poligonSideLabel(0)
1437     , m_hardnessLabel(0)
1438     , m_hardnessField(0)
1439     , m_poligonSideField(0)
1440     , m_shapeField(0)
1441     , m_snapCheckbox(0)
1442     , m_smoothCheckbox(0)
1443     , m_snapSensitivityCombo(0)
1444     , m_tool(tool)
1445     , m_pencilMode(0) {
1446   setFrameStyle(QFrame::StyledPanel);
1447   setFixedHeight(26);
1448   TPropertyGroup *props = tool->getProperties(0);
1449   assert(props->getPropertyCount() > 0);
1450 
1451   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
1452   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
1453   builder.setEnumWidgetType(ToolOptionControlBuilder::POPUPBUTTON);
1454   builder.setSingleValueWidgetType(ToolOptionControlBuilder::FIELD);
1455   addSeparator();
1456   if (tool && tool->getProperties(1)) tool->getProperties(1)->accept(builder);
1457 
1458   hLayout()->addStretch(1);
1459   m_hardnessField =
1460       dynamic_cast<ToolOptionSlider *>(m_controls.value("Hardness:"));
1461   if (m_hardnessField)
1462     m_hardnessLabel = m_labels.value(m_hardnessField->propertyName());
1463 
1464   m_shapeField = dynamic_cast<ToolOptionCombo *>(m_controls.value("Shape:"));
1465   m_poligonSideField =
1466       dynamic_cast<ToolOptionIntSlider *>(m_controls.value("Polygon Sides:"));
1467   if (m_poligonSideField)
1468     m_poligonSideLabel = m_labels.value(m_poligonSideField->propertyName());
1469   m_pencilMode =
1470       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Pencil Mode"));
1471 
1472   if (m_shapeField->getProperty()->getValue() != L"Polygon") {
1473     m_poligonSideLabel->setEnabled(false);
1474     m_poligonSideField->setEnabled(false);
1475   }
1476 
1477   m_smoothCheckbox =
1478       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Smooth"));
1479   if (m_shapeField->getProperty()->getValue() != L"MultiArc") {
1480     m_smoothCheckbox->setEnabled(false);
1481   }
1482 
1483   bool ret = connect(m_shapeField, SIGNAL(currentIndexChanged(int)), this,
1484                      SLOT(onShapeValueChanged(int)));
1485 
1486   if (m_pencilMode) {
1487     if (m_pencilMode->isChecked()) {
1488       m_hardnessLabel->setEnabled(false);
1489       m_hardnessField->setEnabled(false);
1490     }
1491     ret = ret && connect(m_pencilMode, SIGNAL(toggled(bool)), this,
1492                          SLOT(onPencilModeToggled(bool)));
1493   }
1494 
1495   if (tool->getTargetType() & TTool::Vectors) {
1496     m_snapCheckbox =
1497         dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Snap"));
1498     m_snapSensitivityCombo =
1499         dynamic_cast<ToolOptionCombo *>(m_controls.value("Sensitivity:"));
1500     m_snapSensitivityCombo->setHidden(!m_snapCheckbox->isChecked());
1501   }
1502 
1503   ToolOptionPopupButton *m_joinStyle =
1504       dynamic_cast<ToolOptionPopupButton *>(m_controls.value("Join"));
1505   m_miterField =
1506       dynamic_cast<ToolOptionIntSlider *>(m_controls.value("Miter:"));
1507   m_miterField->setEnabled(m_joinStyle->currentIndex() ==
1508                            TStroke::OutlineOptions::MITER_JOIN);
1509 
1510   assert(m_joinStyle && m_miterField);
1511   connect(m_joinStyle, SIGNAL(activated(int)), this,
1512           SLOT(onJoinStyleChanged(int)));
1513 
1514   assert(ret);
1515 }
1516 
1517 //-----------------------------------------------------------------------------
1518 
updateStatus()1519 void GeometricToolOptionsBox::updateStatus() {
1520   QMap<std::string, ToolOptionControl *>::iterator it;
1521   for (it = m_controls.begin(); it != m_controls.end(); it++)
1522     it.value()->updateStatus();
1523   if (m_tool->getTargetType() & TTool::Vectors) {
1524     m_snapSensitivityCombo->setHidden(!m_snapCheckbox->isChecked());
1525   }
1526 }
1527 
1528 //-----------------------------------------------------------------------------
1529 
onShapeValueChanged(int index)1530 void GeometricToolOptionsBox::onShapeValueChanged(int index) {
1531   const TEnumProperty::Range &range = m_shapeField->getProperty()->getRange();
1532   bool polygonEnabled               = range[index] == L"Polygon";
1533   m_poligonSideLabel->setEnabled(polygonEnabled);
1534   m_poligonSideField->setEnabled(polygonEnabled);
1535 
1536   m_smoothCheckbox->setEnabled(range[index] == L"MultiArc");
1537 }
1538 
1539 //-----------------------------------------------------------------------------
1540 
onPencilModeToggled(bool value)1541 void GeometricToolOptionsBox::onPencilModeToggled(bool value) {
1542   m_hardnessLabel->setEnabled(!value);
1543   m_hardnessField->setEnabled(!value);
1544 }
1545 
1546 //-----------------------------------------------------------------------------
1547 
onJoinStyleChanged(int joinStyle)1548 void GeometricToolOptionsBox::onJoinStyleChanged(int joinStyle) {
1549   m_miterField->setEnabled(joinStyle == TStroke::OutlineOptions::MITER_JOIN);
1550 }
1551 
1552 //=============================================================================
1553 //
1554 // TypeToolOptionsBox
1555 //
1556 //=============================================================================
1557 
TypeToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)1558 TypeToolOptionsBox::TypeToolOptionsBox(QWidget *parent, TTool *tool,
1559                                        TPaletteHandle *pltHandle,
1560                                        ToolHandle *toolHandle)
1561     : ToolOptionsBox(parent), m_tool(tool) {
1562   TPropertyGroup *props = tool->getProperties(0);
1563   assert(props->getPropertyCount() > 0);
1564 
1565   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
1566   builder.setEnumWidgetType(ToolOptionControlBuilder::FONTCOMBOBOX);
1567   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
1568   builder.setEnumWidgetType(ToolOptionControlBuilder::COMBOBOX);
1569   if (tool && tool->getProperties(1)) tool->getProperties(1)->accept(builder);
1570 
1571   m_layout->addStretch(0);
1572 
1573   bool ret = true;
1574 
1575   ToolOptionFontCombo *fontField =
1576       dynamic_cast<ToolOptionFontCombo *>(m_controls.value("Font:"));
1577   ret &&connect(fontField, SIGNAL(currentIndexChanged(int)), this,
1578                 SLOT(onFieldChanged()));
1579 
1580   //#ifndef MACOSX
1581   ToolOptionCombo *styleField =
1582       dynamic_cast<ToolOptionCombo *>(m_controls.value("Style:"));
1583   ret &&connect(styleField, SIGNAL(currentIndexChanged(int)), this,
1584                 SLOT(onFieldChanged()));
1585   ret &&connect(toolHandle, SIGNAL(toolComboBoxListChanged(std::string)),
1586                 styleField, SLOT(reloadComboBoxList(std::string)));
1587   //#endif
1588 
1589   ToolOptionCombo *sizeField =
1590       dynamic_cast<ToolOptionCombo *>(m_controls.value("Size:"));
1591   ret &&connect(sizeField, SIGNAL(currentIndexChanged(int)), this,
1592                 SLOT(onFieldChanged()));
1593 
1594   ToolOptionCheckbox *orientationField = dynamic_cast<ToolOptionCheckbox *>(
1595       m_controls.value("Vertical Orientation"));
1596   ret = ret && connect(orientationField, SIGNAL(stateChanged(int)), this,
1597                        SLOT(onFieldChanged()));
1598 
1599   assert(ret);
1600 }
1601 
1602 //-----------------------------------------------------------------------------
1603 
updateStatus()1604 void TypeToolOptionsBox::updateStatus() {
1605   QMap<std::string, ToolOptionControl *>::iterator it;
1606   for (it = m_controls.begin(); it != m_controls.end(); it++)
1607     it.value()->updateStatus();
1608 }
1609 
1610 //-----------------------------------------------------------------------------
1611 
onFieldChanged()1612 void TypeToolOptionsBox::onFieldChanged() {
1613   assert(m_tool);
1614   m_tool->getViewer()->setFocus();
1615 }
1616 
1617 //=============================================================================
1618 //
1619 // PaintbrushToolOptionsBox
1620 //
1621 //=============================================================================
1622 
PaintbrushToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)1623 PaintbrushToolOptionsBox::PaintbrushToolOptionsBox(QWidget *parent, TTool *tool,
1624                                                    TPaletteHandle *pltHandle,
1625                                                    ToolHandle *toolHandle)
1626     : ToolOptionsBox(parent) {
1627   TPropertyGroup *props = tool->getProperties(0);
1628   assert(props->getPropertyCount() > 0);
1629 
1630   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
1631   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
1632   hLayout()->addStretch(1);
1633 
1634   m_colorMode = dynamic_cast<ToolOptionCombo *>(m_controls.value("Mode:"));
1635   m_selectiveMode =
1636       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Selective"));
1637 
1638   if (m_colorMode->getProperty()->getValue() == L"Lines")
1639     m_selectiveMode->setVisible(false);
1640 
1641   bool ret = connect(m_colorMode, SIGNAL(currentIndexChanged(int)), this,
1642                      SLOT(onColorModeChanged(int)));
1643   assert(ret);
1644 }
1645 
1646 //-----------------------------------------------------------------------------
1647 
updateStatus()1648 void PaintbrushToolOptionsBox::updateStatus() {
1649   QMap<std::string, ToolOptionControl *>::iterator it;
1650   for (it = m_controls.begin(); it != m_controls.end(); it++)
1651     it.value()->updateStatus();
1652 }
1653 
1654 //-----------------------------------------------------------------------------
1655 
onColorModeChanged(int index)1656 void PaintbrushToolOptionsBox::onColorModeChanged(int index) {
1657   const TEnumProperty::Range &range = m_colorMode->getProperty()->getRange();
1658   bool enabled                      = range[index] != L"Lines";
1659   m_selectiveMode->setVisible(enabled);
1660 }
1661 
1662 //=============================================================================
1663 //
1664 // FullColorFillToolOptionsBox
1665 //
1666 //=============================================================================
1667 
FullColorFillToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)1668 FullColorFillToolOptionsBox::FullColorFillToolOptionsBox(
1669     QWidget *parent, TTool *tool, TPaletteHandle *pltHandle,
1670     ToolHandle *toolHandle)
1671     : ToolOptionsBox(parent) {
1672   TPropertyGroup *props = tool->getProperties(0);
1673   assert(props->getPropertyCount() > 0);
1674 
1675   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
1676   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
1677 
1678   m_layout->addStretch(0);
1679 }
1680 
1681 //=============================================================================
1682 //
1683 // FillToolOptionsBox
1684 //
1685 //=============================================================================
1686 
FillToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)1687 FillToolOptionsBox::FillToolOptionsBox(QWidget *parent, TTool *tool,
1688                                        TPaletteHandle *pltHandle,
1689                                        ToolHandle *toolHandle)
1690     : ToolOptionsBox(parent)
1691     , m_targetType(tool->getTargetType())
1692     , m_fillDepthLabel(0)
1693     , m_fillDepthField(0)
1694     , m_segmentMode(0) {
1695   TPropertyGroup *props = tool->getProperties(0);
1696   assert(props->getPropertyCount() > 0);
1697 
1698   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
1699   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
1700 
1701   m_layout->addStretch(0);
1702 
1703   m_toolType  = dynamic_cast<ToolOptionCombo *>(m_controls.value("Type:"));
1704   m_colorMode = dynamic_cast<ToolOptionCombo *>(m_controls.value("Mode:"));
1705   m_selectiveMode =
1706       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Selective"));
1707   m_fillDepthField =
1708       dynamic_cast<ToolOptionPairSlider *>(m_controls.value("Fill Depth"));
1709   if (m_fillDepthField)
1710     m_fillDepthLabel = m_labels.value(m_fillDepthField->propertyName());
1711   m_segmentMode =
1712       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Segment"));
1713   m_onionMode =
1714       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Onion Skin"));
1715   m_multiFrameMode =
1716       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Frame Range"));
1717   m_autopaintMode =
1718       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Autopaint Lines"));
1719 
1720   bool ret = connect(m_colorMode, SIGNAL(currentIndexChanged(int)), this,
1721                      SLOT(onColorModeChanged(int)));
1722   ret      = ret && connect(m_toolType, SIGNAL(currentIndexChanged(int)), this,
1723                        SLOT(onToolTypeChanged(int)));
1724   ret      = ret && connect(m_onionMode, SIGNAL(toggled(bool)), this,
1725                        SLOT(onOnionModeToggled(bool)));
1726   ret      = ret && connect(m_multiFrameMode, SIGNAL(toggled(bool)), this,
1727                        SLOT(onMultiFrameModeToggled(bool)));
1728   assert(ret);
1729   if (m_colorMode->getProperty()->getValue() == L"Lines") {
1730     m_selectiveMode->setEnabled(false);
1731     if (m_fillDepthLabel && m_fillDepthField) {
1732       m_fillDepthLabel->setEnabled(false);
1733       m_fillDepthField->setEnabled(false);
1734     }
1735     if (m_toolType->getProperty()->getValue() == L"Normal" ||
1736         m_multiFrameMode->isChecked())
1737       m_onionMode->setEnabled(false);
1738     if (m_autopaintMode) m_autopaintMode->setEnabled(false);
1739   }
1740   if (m_toolType->getProperty()->getValue() != L"Normal") {
1741     if (m_segmentMode) m_segmentMode->setEnabled(false);
1742     if (m_colorMode->getProperty()->getValue() == L"Lines" ||
1743         m_multiFrameMode->isChecked())
1744       m_onionMode->setEnabled(false);
1745   }
1746   if (m_onionMode->isChecked()) m_multiFrameMode->setEnabled(false);
1747 }
1748 
1749 //-----------------------------------------------------------------------------
1750 
updateStatus()1751 void FillToolOptionsBox::updateStatus() {
1752   QMap<std::string, ToolOptionControl *>::iterator it;
1753   for (it = m_controls.begin(); it != m_controls.end(); it++)
1754     it.value()->updateStatus();
1755 }
1756 
1757 //-----------------------------------------------------------------------------
1758 
onColorModeChanged(int index)1759 void FillToolOptionsBox::onColorModeChanged(int index) {
1760   const TEnumProperty::Range &range = m_colorMode->getProperty()->getRange();
1761   bool enabled                      = range[index] != L"Lines";
1762   m_selectiveMode->setEnabled(enabled);
1763   if (m_autopaintMode) m_autopaintMode->setEnabled(enabled);
1764   if (m_fillDepthLabel && m_fillDepthField) {
1765     m_fillDepthLabel->setEnabled(enabled);
1766     m_fillDepthField->setEnabled(enabled);
1767   }
1768   if (m_segmentMode) {
1769     enabled = range[index] != L"Areas";
1770     m_segmentMode->setEnabled(
1771         enabled ? m_toolType->getProperty()->getValue() == L"Normal" : false);
1772   }
1773   enabled = range[index] != L"Lines" && !m_multiFrameMode->isChecked();
1774   m_onionMode->setEnabled(enabled);
1775 }
1776 
1777 //-----------------------------------------------------------------------------
1778 
onToolTypeChanged(int index)1779 void FillToolOptionsBox::onToolTypeChanged(int index) {
1780   const TEnumProperty::Range &range = m_toolType->getProperty()->getRange();
1781   bool enabled                      = range[index] == L"Normal";
1782   if (m_segmentMode)
1783     m_segmentMode->setEnabled(
1784         enabled ? m_colorMode->getProperty()->getValue() != L"Areas" : false);
1785   enabled = enabled || (m_colorMode->getProperty()->getValue() != L"Lines" &&
1786                         !m_multiFrameMode->isChecked());
1787   m_onionMode->setEnabled(enabled);
1788 }
1789 
1790 //-----------------------------------------------------------------------------
1791 
onOnionModeToggled(bool value)1792 void FillToolOptionsBox::onOnionModeToggled(bool value) {
1793   m_multiFrameMode->setEnabled(!value);
1794 }
1795 
1796 //-----------------------------------------------------------------------------
1797 
onMultiFrameModeToggled(bool value)1798 void FillToolOptionsBox::onMultiFrameModeToggled(bool value) {
1799   m_onionMode->setEnabled(!value);
1800 }
1801 
1802 //=============================================================================
1803 //
1804 // BrushToolOptionsBox classes
1805 //
1806 //=============================================================================
1807 
1808 class BrushToolOptionsBox::PresetNamePopup final : public DVGui::Dialog {
1809   DVGui::LineEdit *m_nameFld;
1810 
1811 public:
PresetNamePopup()1812   PresetNamePopup() : Dialog(0, true) {
1813     setWindowTitle(tr("Preset Name"));
1814     m_nameFld = new DVGui::LineEdit();
1815     addWidget(m_nameFld);
1816 
1817     QPushButton *okBtn = new QPushButton(tr("OK"), this);
1818     okBtn->setDefault(true);
1819     QPushButton *cancelBtn = new QPushButton(tr("Cancel"), this);
1820     connect(okBtn, SIGNAL(clicked()), this, SLOT(accept()));
1821     connect(cancelBtn, SIGNAL(clicked()), this, SLOT(reject()));
1822 
1823     addButtonBarWidget(okBtn, cancelBtn);
1824   }
1825 
getName()1826   QString getName() { return m_nameFld->text(); }
removeName()1827   void removeName() { m_nameFld->setText(QString("")); }
1828 };
1829 
1830 //=============================================================================
1831 //
1832 // BrushToolOptionsBox
1833 //
1834 //=============================================================================
1835 
BrushToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)1836 BrushToolOptionsBox::BrushToolOptionsBox(QWidget *parent, TTool *tool,
1837                                          TPaletteHandle *pltHandle,
1838                                          ToolHandle *toolHandle)
1839     : ToolOptionsBox(parent)
1840     , m_tool(tool)
1841     , m_presetNamePopup(0)
1842     , m_pencilMode(0)
1843     , m_hardnessLabel(0)
1844     , m_joinStyleCombo(0)
1845     , m_snapCheckbox(0)
1846     , m_snapSensitivityCombo(0)
1847     , m_miterField(0) {
1848   TPropertyGroup *props = tool->getProperties(0);
1849   assert(props->getPropertyCount() > 0);
1850 
1851   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
1852   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
1853 
1854   m_hardnessField =
1855       dynamic_cast<ToolOptionSlider *>(m_controls.value("Hardness:"));
1856   if (m_hardnessField)
1857     m_hardnessLabel = m_labels.value(m_hardnessField->propertyName());
1858   m_pencilMode = dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Pencil"));
1859   m_presetCombo = dynamic_cast<ToolOptionCombo *>(m_controls.value("Preset:"));
1860 
1861   // Preset +/- buttons
1862   m_addPresetButton    = new QPushButton(QString("+"));
1863   m_removePresetButton = new QPushButton(QString("-"));
1864 
1865   m_addPresetButton->setFixedSize(QSize(20, 20));
1866   m_removePresetButton->setFixedSize(QSize(20, 20));
1867 
1868   hLayout()->addWidget(m_addPresetButton);
1869   hLayout()->addWidget(m_removePresetButton);
1870 
1871   connect(m_addPresetButton, SIGNAL(clicked()), this, SLOT(onAddPreset()));
1872   connect(m_removePresetButton, SIGNAL(clicked()), this,
1873           SLOT(onRemovePreset()));
1874 
1875   if (tool->getTargetType() & TTool::ToonzImage) {
1876     assert(m_pencilMode);
1877     bool ret = connect(m_pencilMode, SIGNAL(toggled(bool)), this,
1878                        SLOT(onPencilModeToggled(bool)));
1879     assert(ret);
1880 
1881     if (m_pencilMode->isChecked()) {
1882       m_hardnessLabel->setEnabled(false);
1883       m_hardnessField->setEnabled(false);
1884     }
1885   } else if (tool->getTargetType() & TTool::Vectors) {
1886     // Further vector options
1887     builder.setEnumWidgetType(ToolOptionControlBuilder::POPUPBUTTON);
1888     builder.setSingleValueWidgetType(ToolOptionControlBuilder::FIELD);
1889 
1890     addSeparator();
1891     m_snapCheckbox =
1892         dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Snap"));
1893     m_snapSensitivityCombo =
1894         dynamic_cast<ToolOptionCombo *>(m_controls.value("Sensitivity:"));
1895 
1896     if (tool && tool->getProperties(1)) tool->getProperties(1)->accept(builder);
1897     m_joinStyleCombo =
1898         dynamic_cast<ToolOptionPopupButton *>(m_controls.value("Join"));
1899     m_miterField =
1900         dynamic_cast<ToolOptionIntSlider *>(m_controls.value("Miter:"));
1901     m_miterField->setEnabled(m_joinStyleCombo->currentIndex() ==
1902                              TStroke::OutlineOptions::MITER_JOIN);
1903   }
1904   hLayout()->addStretch(1);
1905   filterControls();
1906 }
1907 
1908 //-----------------------------------------------------------------------------
1909 
filterControls()1910 void BrushToolOptionsBox::filterControls() {
1911   // show or hide widgets which modify imported brush (mypaint)
1912 
1913   bool showModifiers = false;
1914   if (m_tool->getTargetType() & TTool::RasterImage) {
1915     FullColorBrushTool *fullColorBrushTool =
1916         dynamic_cast<FullColorBrushTool *>(m_tool);
1917     showModifiers = fullColorBrushTool->getBrushStyle();
1918   } else if (m_tool->getTargetType() & TTool::ToonzImage) {
1919     ToonzRasterBrushTool *toonzRasterBrushTool =
1920         dynamic_cast<ToonzRasterBrushTool *>(m_tool);
1921     showModifiers = toonzRasterBrushTool->isMyPaintStyleSelected();
1922   } else {  // (m_tool->getTargetType() & TTool::Vectors)
1923     m_snapSensitivityCombo->setHidden(!m_snapCheckbox->isChecked());
1924     return;
1925   }
1926 
1927   for (QMap<std::string, QLabel *>::iterator it = m_labels.begin();
1928        it != m_labels.end(); it++) {
1929     bool isModifier = (it.key().substr(0, 8) == "Modifier");
1930     bool isCommon   = (it.key() == "Pressure" || it.key() == "Preset:");
1931     bool visible    = isCommon || (isModifier == showModifiers);
1932     it.value()->setVisible(visible);
1933   }
1934 
1935   for (QMap<std::string, ToolOptionControl *>::iterator it = m_controls.begin();
1936        it != m_controls.end(); it++) {
1937     bool isModifier = (it.key().substr(0, 8) == "Modifier");
1938     bool isCommon   = (it.key() == "Pressure" || it.key() == "Preset:");
1939     bool visible    = isCommon || (isModifier == showModifiers);
1940     if (QWidget *widget = dynamic_cast<QWidget *>(it.value()))
1941       widget->setVisible(visible);
1942   }
1943 }
1944 
1945 //-----------------------------------------------------------------------------
1946 
updateStatus()1947 void BrushToolOptionsBox::updateStatus() {
1948   filterControls();
1949 
1950   QMap<std::string, ToolOptionControl *>::iterator it;
1951   for (it = m_controls.begin(); it != m_controls.end(); it++)
1952     it.value()->updateStatus();
1953 
1954   if (m_miterField)
1955     m_miterField->setEnabled(m_joinStyleCombo->currentIndex() ==
1956                              TStroke::OutlineOptions::MITER_JOIN);
1957   if (m_snapCheckbox)
1958     m_snapSensitivityCombo->setHidden(!m_snapCheckbox->isChecked());
1959 }
1960 
1961 //-----------------------------------------------------------------------------
1962 
onPencilModeToggled(bool value)1963 void BrushToolOptionsBox::onPencilModeToggled(bool value) {
1964   m_hardnessLabel->setEnabled(!value);
1965   m_hardnessField->setEnabled(!value);
1966 }
1967 
1968 //-----------------------------------------------------------------------------
1969 
onAddPreset()1970 void BrushToolOptionsBox::onAddPreset() {
1971   // Initialize preset name popup
1972   if (!m_presetNamePopup) m_presetNamePopup = new PresetNamePopup;
1973 
1974   if (!m_presetNamePopup->getName().isEmpty()) m_presetNamePopup->removeName();
1975 
1976   // Retrieve the preset name
1977   bool ret = m_presetNamePopup->exec();
1978   if (!ret) return;
1979 
1980   QString name(m_presetNamePopup->getName());
1981   m_presetNamePopup->removeName();
1982 
1983   switch (m_tool->getTargetType() & TTool::CommonImages) {
1984   case TTool::VectorImage: {
1985     static_cast<ToonzVectorBrushTool *>(m_tool)->addPreset(name);
1986     break;
1987   }
1988   case TTool::ToonzImage: {
1989     static_cast<ToonzRasterBrushTool *>(m_tool)->addPreset(name);
1990     break;
1991   }
1992 
1993   case TTool::RasterImage: {
1994     static_cast<FullColorBrushTool *>(m_tool)->addPreset(name);
1995     break;
1996   }
1997   }
1998 
1999   m_presetCombo->loadEntries();
2000 }
2001 
2002 //-----------------------------------------------------------------------------
2003 
onRemovePreset()2004 void BrushToolOptionsBox::onRemovePreset() {
2005   switch (m_tool->getTargetType() & TTool::CommonImages) {
2006   case TTool::VectorImage: {
2007     static_cast<ToonzVectorBrushTool *>(m_tool)->removePreset();
2008     break;
2009   }
2010   case TTool::ToonzImage: {
2011     static_cast<ToonzRasterBrushTool *>(m_tool)->removePreset();
2012     break;
2013   }
2014 
2015   case TTool::RasterImage: {
2016     static_cast<FullColorBrushTool *>(m_tool)->removePreset();
2017     break;
2018   }
2019   }
2020 
2021   m_presetCombo->loadEntries();
2022 }
2023 
2024 //=============================================================================
2025 //
2026 // EraserToolOptionsBox
2027 //
2028 //=============================================================================
2029 
EraserToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)2030 EraserToolOptionsBox::EraserToolOptionsBox(QWidget *parent, TTool *tool,
2031                                            TPaletteHandle *pltHandle,
2032                                            ToolHandle *toolHandle)
2033     : ToolOptionsBox(parent), m_pencilMode(0), m_colorMode(0) {
2034   TPropertyGroup *props = tool->getProperties(0);
2035   assert(props->getPropertyCount() > 0);
2036 
2037   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
2038   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
2039 
2040   hLayout()->addStretch(1);
2041 
2042   m_toolType = dynamic_cast<ToolOptionCombo *>(m_controls.value("Type:"));
2043   m_hardnessField =
2044       dynamic_cast<ToolOptionSlider *>(m_controls.value("Hardness:"));
2045   if (m_hardnessField)
2046     m_hardnessLabel = m_labels.value(m_hardnessField->propertyName());
2047   m_colorMode  = dynamic_cast<ToolOptionCombo *>(m_controls.value("Mode:"));
2048   m_invertMode = dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Invert"));
2049   m_multiFrameMode =
2050       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Frame Range"));
2051   m_pencilMode =
2052       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Pencil Mode"));
2053 
2054   bool ret = true;
2055   if (m_pencilMode) {
2056     ret = ret && connect(m_pencilMode, SIGNAL(toggled(bool)), this,
2057                          SLOT(onPencilModeToggled(bool)));
2058     ret = ret && connect(m_colorMode, SIGNAL(currentIndexChanged(int)), this,
2059                          SLOT(onColorModeChanged(int)));
2060   }
2061 
2062   ret = ret && connect(m_toolType, SIGNAL(currentIndexChanged(int)), this,
2063                        SLOT(onToolTypeChanged(int)));
2064 
2065   if (m_pencilMode && m_pencilMode->isChecked()) {
2066     assert(m_hardnessField && m_hardnessLabel);
2067     m_hardnessField->setEnabled(false);
2068     m_hardnessLabel->setEnabled(false);
2069   }
2070 
2071   if (m_toolType && m_toolType->getProperty()->getValue() == L"Normal") {
2072     m_invertMode->setEnabled(false);
2073     m_multiFrameMode->setEnabled(false);
2074   }
2075 
2076   if (m_colorMode && m_colorMode->getProperty()->getValue() == L"Areas") {
2077     assert(m_hardnessField && m_hardnessLabel && m_pencilMode);
2078     m_pencilMode->setEnabled(false);
2079     m_hardnessField->setEnabled(false);
2080     m_hardnessLabel->setEnabled(false);
2081   }
2082 }
2083 
2084 //-----------------------------------------------------------------------------
2085 
updateStatus()2086 void EraserToolOptionsBox::updateStatus() {
2087   QMap<std::string, ToolOptionControl *>::iterator it;
2088   for (it = m_controls.begin(); it != m_controls.end(); it++)
2089     it.value()->updateStatus();
2090 }
2091 
2092 //-----------------------------------------------------------------------------
2093 
onPencilModeToggled(bool value)2094 void EraserToolOptionsBox::onPencilModeToggled(bool value) {
2095   if (m_hardnessField && m_hardnessLabel) {
2096     m_hardnessField->setEnabled(!value);
2097     m_hardnessLabel->setEnabled(!value);
2098   }
2099 }
2100 
2101 //-----------------------------------------------------------------------------
2102 
onToolTypeChanged(int index)2103 void EraserToolOptionsBox::onToolTypeChanged(int index) {
2104   const TEnumProperty::Range &range = m_toolType->getProperty()->getRange();
2105   bool value                        = range[index] != L"Normal";
2106   m_invertMode->setEnabled(value);
2107   m_multiFrameMode->setEnabled(value);
2108 }
2109 
2110 //-----------------------------------------------------------------------------
2111 
onColorModeChanged(int index)2112 void EraserToolOptionsBox::onColorModeChanged(int index) {
2113   const TEnumProperty::Range &range = m_colorMode->getProperty()->getRange();
2114   bool enabled                      = range[index] != L"Areas";
2115   if (m_pencilMode && m_hardnessField && m_hardnessLabel) {
2116     m_pencilMode->setEnabled(enabled);
2117     m_hardnessField->setEnabled(enabled ? !m_pencilMode->isChecked() : false);
2118     m_hardnessLabel->setEnabled(enabled ? !m_pencilMode->isChecked() : false);
2119   }
2120 }
2121 
2122 //=============================================================================
2123 //
2124 // RulerToolOptionsBox
2125 //
2126 //=============================================================================
2127 class ToolOptionsBarSeparator final : public QWidget {
2128 public:
ToolOptionsBarSeparator(QWidget * parent)2129   ToolOptionsBarSeparator(QWidget *parent) : QWidget(parent) {
2130     setFixedSize(2, 26);
2131   }
2132 
paintEvent(QPaintEvent *)2133   void paintEvent(QPaintEvent *) {
2134     QPainter p(this);
2135     p.setPen(QColor(64, 64, 64));
2136     p.drawLine(0, 0, 0, 25);
2137     p.setPen(QColor(0, 0, 0, 125));
2138     p.drawLine(1, 0, 1, 25);
2139   }
2140 };
2141 
RulerToolOptionsBox(QWidget * parent,TTool * tool)2142 RulerToolOptionsBox::RulerToolOptionsBox(QWidget *parent, TTool *tool)
2143     : ToolOptionsBox(parent), m_tool(tool) {
2144   setFrameStyle(QFrame::StyledPanel);
2145   setFixedHeight(26);
2146 
2147   m_Xfld = new MeasuredValueField(this);
2148   m_Yfld = new MeasuredValueField(this);
2149   m_Wfld = new MeasuredValueField(this);
2150   m_Hfld = new MeasuredValueField(this);
2151   m_Afld = new MeasuredValueField(this);
2152   m_Lfld = new MeasuredValueField(this);
2153 
2154   m_XpixelFld = new QLabel(this);
2155   m_YpixelFld = new QLabel(this);
2156   m_WpixelFld = new QLabel(this);
2157   m_HpixelFld = new QLabel(this);
2158 
2159   m_Afld->setMeasure("angle");
2160 
2161   if (Preferences::instance()->getUnits() == "pixel") {
2162     m_Xfld->setMeasure("length.x");
2163     m_Yfld->setMeasure("length.y");
2164     m_Wfld->setMeasure("length.x");
2165     m_Hfld->setMeasure("length.y");
2166     m_Lfld->setMeasure("length.x");
2167   }
2168 
2169   m_Xfld->setObjectName("RulerToolOptionValues");
2170   m_Yfld->setObjectName("RulerToolOptionValues");
2171   m_Wfld->setObjectName("RulerToolOptionValues");
2172   m_Hfld->setObjectName("RulerToolOptionValues");
2173   m_Afld->setObjectName("RulerToolOptionValues");
2174   m_Lfld->setObjectName("RulerToolOptionValues");
2175   setStyleSheet(
2176       "#RulerToolOptionValues {border:0px; background: rgb(196,196,196);}");
2177 
2178   m_Xfld->setMaximumWidth(70);
2179   m_Yfld->setMaximumWidth(70);
2180   m_Wfld->setMaximumWidth(70);
2181   m_Hfld->setMaximumWidth(70);
2182   m_Afld->setMaximumWidth(70);
2183   m_Lfld->setMaximumWidth(70);
2184 
2185   m_Xfld->setReadOnly(true);
2186   m_Yfld->setReadOnly(true);
2187   m_Wfld->setReadOnly(true);
2188   m_Hfld->setReadOnly(true);
2189   m_Afld->setReadOnly(true);
2190   m_Lfld->setReadOnly(true);
2191 
2192   // layout
2193   QHBoxLayout *lay = new QHBoxLayout();
2194   lay->setMargin(0);
2195   lay->setSpacing(3);
2196   {
2197     lay->addWidget(new QLabel(tr("X:", "ruler tool option"), this), 0);
2198     lay->addWidget(m_Xfld, 0);
2199     lay->addWidget(m_XpixelFld, 0);
2200 
2201     lay->addSpacing(3);
2202 
2203     lay->addWidget(new QLabel(tr("Y:", "ruler tool option"), this), 0);
2204     lay->addWidget(m_Yfld, 0);
2205     lay->addWidget(m_YpixelFld, 0);
2206 
2207     lay->addSpacing(3);
2208     lay->addWidget(new ToolOptionsBarSeparator(this), 0);
2209     lay->addSpacing(3);
2210 
2211     lay->addWidget(new QLabel(tr("W:", "ruler tool option"), this), 0);
2212     lay->addWidget(m_Wfld, 0);
2213     lay->addWidget(m_WpixelFld, 0);
2214 
2215     lay->addSpacing(3);
2216 
2217     lay->addWidget(new QLabel(tr("H:", "ruler tool option"), this), 0);
2218     lay->addWidget(m_Hfld, 0);
2219     lay->addWidget(m_HpixelFld, 0);
2220 
2221     lay->addSpacing(3);
2222     lay->addWidget(new ToolOptionsBarSeparator(this), 0);
2223     lay->addSpacing(3);
2224 
2225     lay->addWidget(new QLabel(tr("A:", "ruler tool option"), this), 0);
2226     lay->addWidget(m_Afld, 0);
2227 
2228     lay->addSpacing(3);
2229 
2230     lay->addWidget(new QLabel(tr("L:", "ruler tool option"), this), 0);
2231     lay->addWidget(m_Lfld, 0);
2232   }
2233   m_layout->addLayout(lay, 0);
2234   m_layout->addStretch(1);
2235 }
2236 
updateValues(bool isRasterLevelEditing,double X,double Y,double W,double H,double A,double L,int Xpix,int Ypix,int Wpix,int Hpix)2237 void RulerToolOptionsBox::updateValues(bool isRasterLevelEditing, double X,
2238                                        double Y, double W, double H, double A,
2239                                        double L, int Xpix, int Ypix, int Wpix,
2240                                        int Hpix) {
2241   m_Xfld->setValue(X);
2242   m_Yfld->setValue(Y);
2243   m_Wfld->setValue(W);
2244   m_Hfld->setValue(H);
2245   m_Afld->setValue(A);
2246   m_Lfld->setValue(L);
2247 
2248   m_XpixelFld->setVisible(isRasterLevelEditing);
2249   m_YpixelFld->setVisible(isRasterLevelEditing);
2250   m_WpixelFld->setVisible(isRasterLevelEditing);
2251   m_HpixelFld->setVisible(isRasterLevelEditing);
2252 
2253   if (isRasterLevelEditing) {
2254     m_XpixelFld->setText(QString("(%1)").arg(Xpix));
2255     m_YpixelFld->setText(QString("(%1)").arg(Ypix));
2256     m_WpixelFld->setText(QString("(%1)").arg(Wpix));
2257     m_HpixelFld->setText(QString("(%1)").arg(Hpix));
2258   }
2259   repaint();
2260 }
2261 
resetValues()2262 void RulerToolOptionsBox::resetValues() {
2263   m_Xfld->setValue(0);
2264   m_Yfld->setValue(0);
2265   m_Wfld->setValue(0);
2266   m_Hfld->setValue(0);
2267   m_Afld->setValue(0);
2268   m_Lfld->setValue(0);
2269 
2270   m_XpixelFld->setVisible(false);
2271   m_YpixelFld->setVisible(false);
2272   m_WpixelFld->setVisible(false);
2273   m_HpixelFld->setVisible(false);
2274 
2275   update();
2276 }
2277 
2278 //=============================================================================
2279 //
2280 // TapeToolOptionsBox
2281 //
2282 //=============================================================================
2283 
TapeToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)2284 TapeToolOptionsBox::TapeToolOptionsBox(QWidget *parent, TTool *tool,
2285                                        TPaletteHandle *pltHandle,
2286                                        ToolHandle *toolHandle)
2287     : ToolOptionsBox(parent)
2288     , m_smoothMode(0)
2289     , m_joinStrokesMode(0)
2290     , m_toolMode(0)
2291     , m_autocloseLabel(0)
2292     , m_autocloseField(0) {
2293   TPropertyGroup *props = tool->getProperties(0);
2294   assert(props->getPropertyCount() > 0);
2295 
2296   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
2297   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
2298 
2299   hLayout()->addStretch(1);
2300   if (!(tool->getTargetType() & TTool::Vectors)) return;
2301 
2302   m_smoothMode = dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Smooth"));
2303   m_joinStrokesMode =
2304       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("JoinStrokes"));
2305   m_toolMode = dynamic_cast<ToolOptionCombo *>(m_controls.value("Mode"));
2306   m_typeMode = dynamic_cast<ToolOptionCombo *>(m_controls.value("Type"));
2307   m_autocloseField =
2308       dynamic_cast<ToolOptionSlider *>(m_controls.value("Distance"));
2309   if (m_autocloseField)
2310     m_autocloseLabel = m_labels.value(m_autocloseField->propertyName());
2311 
2312   bool isNormalType = m_typeMode->getProperty()->getValue() == L"Normal";
2313   m_toolMode->setEnabled(isNormalType);
2314   m_autocloseField->setEnabled(!isNormalType);
2315   m_autocloseLabel->setEnabled(!isNormalType);
2316 
2317   bool isLineToLineMode =
2318       m_toolMode->getProperty()->getValue() == L"Line to Line";
2319   m_joinStrokesMode->setEnabled(!isLineToLineMode);
2320 
2321   bool isJoinStrokes = m_joinStrokesMode->isChecked();
2322   m_smoothMode->setEnabled(!isLineToLineMode && isJoinStrokes);
2323 
2324   bool ret = connect(m_typeMode, SIGNAL(currentIndexChanged(int)), this,
2325                      SLOT(onToolTypeChanged(int)));
2326   ret      = ret && connect(m_toolMode, SIGNAL(currentIndexChanged(int)), this,
2327                        SLOT(onToolModeChanged(int)));
2328   ret      = ret && connect(m_joinStrokesMode, SIGNAL(toggled(bool)), this,
2329                        SLOT(onJoinStrokesModeChanged()));
2330   assert(ret);
2331 }
2332 
2333 //-----------------------------------------------------------------------------
2334 
updateStatus()2335 void TapeToolOptionsBox::updateStatus() {
2336   QMap<std::string, ToolOptionControl *>::iterator it;
2337   for (it = m_controls.begin(); it != m_controls.end(); it++)
2338     it.value()->updateStatus();
2339 }
2340 
2341 //-----------------------------------------------------------------------------
2342 
onToolTypeChanged(int index)2343 void TapeToolOptionsBox::onToolTypeChanged(int index) {
2344   const TEnumProperty::Range &range = m_typeMode->getProperty()->getRange();
2345   bool isNormalType                 = range[index] == L"Normal";
2346   m_toolMode->setEnabled(isNormalType);
2347   m_autocloseField->setEnabled(!isNormalType);
2348   m_autocloseLabel->setEnabled(!isNormalType);
2349 }
2350 
2351 //-----------------------------------------------------------------------------
2352 
onToolModeChanged(int index)2353 void TapeToolOptionsBox::onToolModeChanged(int index) {
2354   const TEnumProperty::Range &range = m_toolMode->getProperty()->getRange();
2355   bool isLineToLineMode             = range[index] == L"Line to Line";
2356   m_joinStrokesMode->setEnabled(!isLineToLineMode);
2357   bool isJoinStrokes = m_joinStrokesMode->isChecked();
2358   m_smoothMode->setEnabled(!isLineToLineMode && isJoinStrokes);
2359 }
2360 
2361 //-----------------------------------------------------------------------------
2362 
onJoinStrokesModeChanged()2363 void TapeToolOptionsBox::onJoinStrokesModeChanged() {
2364   bool isLineToLineMode =
2365       m_toolMode->getProperty()->getValue() == L"Line to Line";
2366   bool isJoinStrokes = m_joinStrokesMode->isChecked();
2367   m_smoothMode->setEnabled(!isLineToLineMode && isJoinStrokes);
2368 }
2369 
2370 //=============================================================================
2371 // RGBPickerToolOptions
2372 //-----------------------------------------------------------------------------
2373 
2374 //-----------------------------------------------------------------------------
2375 /*! Label with background color
2376  */
2377 class RGBLabel final : public QWidget {
2378   QColor m_color;
2379 
2380 public:
RGBLabel(QColor color,QWidget * parent)2381   RGBLabel(QColor color, QWidget *parent) : QWidget(parent), m_color(color) {
2382     setFixedSize(120, 20);
2383   }
2384 
~RGBLabel()2385   ~RGBLabel() {}
2386 
setColorAndUpdate(QColor color)2387   void setColorAndUpdate(QColor color) {
2388     if (m_color == color) return;
2389     m_color = color;
2390     update();
2391   }
2392 
2393 protected:
paintEvent(QPaintEvent * pe)2394   void paintEvent(QPaintEvent *pe) {
2395     QPainter p(this);
2396     p.setPen(Qt::NoPen);
2397 
2398     if (LutManager::instance()->isValid()) {
2399       QColor convertedColor(m_color);
2400       LutManager::instance()->convert(convertedColor);
2401       p.setBrush(convertedColor);
2402     } else
2403       p.setBrush(m_color);
2404 
2405     p.drawRect(rect());
2406 
2407     // white text on dark color. black text on light color.
2408     int val = m_color.red() * 30 + m_color.green() * 59 + m_color.blue() * 11;
2409     if (val < 12800)
2410       p.setPen(Qt::white);
2411     else
2412       p.setPen(Qt::black);
2413     p.setBrush(Qt::NoBrush);
2414 
2415     p.drawText(rect(), Qt::AlignCenter,
2416                QString("R:%1 G:%2 B:%3")
2417                    .arg(m_color.red())
2418                    .arg(m_color.green())
2419                    .arg(m_color.blue()));
2420   }
2421 };
2422 
2423 //-----------------------------------------------------------------------------
2424 
RGBPickerToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle,PaletteController * paletteController)2425 RGBPickerToolOptionsBox::RGBPickerToolOptionsBox(
2426     QWidget *parent, TTool *tool, TPaletteHandle *pltHandle,
2427     ToolHandle *toolHandle, PaletteController *paletteController)
2428     : ToolOptionsBox(parent) {
2429   setFrameStyle(QFrame::StyledPanel);
2430   setFixedHeight(26);
2431 
2432   m_currentRGBLabel = new RGBLabel(QColor(128, 128, 128), this);
2433 
2434   QAction *pickScreenAction =
2435       CommandManager::instance()->getAction("A_ToolOption_PickScreen");
2436 
2437   QPushButton *button = new QPushButton(tr("Pick Screen"));
2438   int buttonWidth     = fontMetrics().width(button->text()) + 10;
2439   button->setFixedWidth(buttonWidth);
2440   button->setFixedHeight(20);
2441   button->addAction(pickScreenAction);
2442   connect(button, SIGNAL(clicked()), pickScreenAction, SLOT(trigger()));
2443 
2444   TPropertyGroup *props = tool->getProperties(0);
2445   assert(props->getPropertyCount() > 0);
2446 
2447   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
2448   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
2449 
2450   m_realTimePickMode =
2451       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Passive Pick"));
2452 
2453   m_layout->addWidget(m_currentRGBLabel, 0);
2454   m_layout->addStretch(1);
2455   m_layout->addWidget(button, 0);
2456   m_layout->addSpacing(5);
2457 
2458   if (m_realTimePickMode) {
2459     connect(m_realTimePickMode, SIGNAL(toggled(bool)), m_currentRGBLabel,
2460             SLOT(setVisible(bool)));
2461     m_currentRGBLabel->setVisible(m_realTimePickMode->isChecked());
2462   }
2463 
2464   // for passive pick
2465   connect(paletteController, SIGNAL(colorPassivePicked(const QColor &)), this,
2466           SLOT(updateRealTimePickLabel(const QColor &)));
2467 }
2468 
2469 //-----------------------------------------------------------------------------
2470 
updateStatus()2471 void RGBPickerToolOptionsBox::updateStatus() {
2472   QMap<std::string, ToolOptionControl *>::iterator it;
2473   for (it = m_controls.begin(); it != m_controls.end(); it++)
2474     it.value()->updateStatus();
2475 }
2476 
2477 //-----------------------------------------------------------------------------
2478 
updateRealTimePickLabel(const QColor & pix)2479 void RGBPickerToolOptionsBox::updateRealTimePickLabel(const QColor &pix) {
2480   if (isVisible()) m_currentRGBLabel->setColorAndUpdate(pix);
2481 }
2482 
2483 //=============================================================================
2484 // StylePickerToolOptions
2485 //-----------------------------------------------------------------------------
2486 
StylePickerToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle,PaletteController * paletteController)2487 StylePickerToolOptionsBox::StylePickerToolOptionsBox(
2488     QWidget *parent, TTool *tool, TPaletteHandle *pltHandle,
2489     ToolHandle *toolHandle, PaletteController *paletteController)
2490     : ToolOptionsBox(parent) {
2491   setFrameStyle(QFrame::StyledPanel);
2492   setFixedHeight(26);
2493 
2494   m_currentStyleLabel = new QLabel(" - - - ", this);
2495   m_currentStyleLabel->setObjectName("SytlePickerValue");
2496   setStyleSheet(
2497       "#SytlePickerValue {color: black; border:0px; background: "
2498       "rgb(196,196,196);}");
2499 
2500   m_currentStyleLabel->setFixedSize(200, 20);
2501   m_currentStyleLabel->setAlignment(Qt::AlignCenter);
2502 
2503   TPropertyGroup *props = tool->getProperties(0);
2504   assert(props->getPropertyCount() > 0);
2505 
2506   ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
2507   if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
2508 
2509   m_realTimePickMode =
2510       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Passive Pick"));
2511 
2512   m_layout->addWidget(m_currentStyleLabel, 0);
2513   m_layout->addStretch(1);
2514   // retrieve the "organize palette" checkbox from the layout and insert
2515   // into rightmost of the tool option bar
2516   ToolOptionCheckbox *organizePaletteCB =
2517       dynamic_cast<ToolOptionCheckbox *>(m_controls.value("Organize Palette"));
2518   m_layout->removeWidget(organizePaletteCB);
2519   // m_layout->addWidget(new ToolOptionsBarSeparator(this), 0);
2520   m_layout->addWidget(organizePaletteCB);
2521   m_layout->addSpacing(5);
2522   organizePaletteCB->setToolTip(
2523       tr("With this option being activated, the picked style will be\nmoved to "
2524          "the end of the first page of the palette."));
2525 
2526   if (m_realTimePickMode) {
2527     connect(m_realTimePickMode, SIGNAL(toggled(bool)), m_currentStyleLabel,
2528             SLOT(setVisible(bool)));
2529     m_currentStyleLabel->setVisible(m_realTimePickMode->isChecked());
2530   }
2531 
2532   // for passive pick
2533   connect(paletteController,
2534           SIGNAL(stylePassivePicked(const int, const int, const int)), this,
2535           SLOT(updateRealTimePickLabel(const int, const int, const int)));
2536 }
2537 
2538 //-----------------------------------------------------------------------------
2539 
updateStatus()2540 void StylePickerToolOptionsBox::updateStatus() {
2541   QMap<std::string, ToolOptionControl *>::iterator it;
2542   for (it = m_controls.begin(); it != m_controls.end(); it++)
2543     it.value()->updateStatus();
2544 }
2545 
2546 //-----------------------------------------------------------------------------
2547 
updateRealTimePickLabel(const int ink,const int paint,const int tone)2548 void StylePickerToolOptionsBox::updateRealTimePickLabel(const int ink,
2549                                                         const int paint,
2550                                                         const int tone) {
2551   if (isVisible()) {
2552     if (ink < 0)
2553       m_currentStyleLabel->setText(" - - - ");
2554     else
2555       m_currentStyleLabel->setText(QString("INK: #%1  PAINT: #%2  TONE: %3")
2556                                        .arg(ink)
2557                                        .arg(paint)
2558                                        .arg(tone));
2559   }
2560 }
2561 
2562 //=============================================================================
2563 // ShiftTraceToolOptionBox
2564 //-----------------------------------------------------------------------------
2565 
ShiftTraceToolOptionBox(QWidget * parent,TTool * tool)2566 ShiftTraceToolOptionBox::ShiftTraceToolOptionBox(QWidget *parent, TTool *tool)
2567     : ToolOptionsBox(parent), m_tool(tool) {
2568   setFrameStyle(QFrame::StyledPanel);
2569   setFixedHeight(26);
2570 
2571   m_prevFrame  = new QFrame(this);
2572   m_afterFrame = new QFrame(this);
2573 
2574   m_resetPrevGhostBtn  = new QPushButton(tr("Reset Previous"), this);
2575   m_resetAfterGhostBtn = new QPushButton(tr("Reset Following"), this);
2576 
2577   m_prevRadioBtn  = new QRadioButton(tr("Previous Drawing"), this);
2578   m_afterRadioBtn = new QRadioButton(tr("Following Drawing"), this);
2579 
2580   m_prevFrame->setFixedSize(10, 21);
2581   m_afterFrame->setFixedSize(10, 21);
2582   int buttonWidth = fontMetrics().width(m_resetPrevGhostBtn->text()) + 10;
2583   m_resetPrevGhostBtn->setFixedWidth(buttonWidth);
2584   buttonWidth = fontMetrics().width(m_resetAfterGhostBtn->text()) + 10;
2585   m_resetAfterGhostBtn->setFixedWidth(buttonWidth);
2586 
2587   m_layout->addWidget(m_prevFrame, 0);
2588   m_layout->addWidget(m_prevRadioBtn, 0);
2589   m_layout->addWidget(m_resetPrevGhostBtn, 0);
2590 
2591   m_layout->addWidget(new DVGui::Separator("", this, false));
2592 
2593   m_layout->addWidget(m_afterFrame, 0);
2594   m_layout->addWidget(m_afterRadioBtn, 0);
2595   m_layout->addWidget(m_resetAfterGhostBtn, 0);
2596 
2597   m_layout->addStretch(1);
2598 
2599   connect(m_resetPrevGhostBtn, SIGNAL(clicked(bool)), this,
2600           SLOT(onResetPrevGhostBtnPressed()));
2601   connect(m_resetAfterGhostBtn, SIGNAL(clicked(bool)), this,
2602           SLOT(onResetAfterGhostBtnPressed()));
2603   connect(m_prevRadioBtn, SIGNAL(clicked(bool)), this,
2604           SLOT(onPrevRadioBtnClicked()));
2605   connect(m_afterRadioBtn, SIGNAL(clicked(bool)), this,
2606           SLOT(onAfterRadioBtnClicked()));
2607 
2608   updateStatus();
2609 }
2610 
showEvent(QShowEvent *)2611 void ShiftTraceToolOptionBox::showEvent(QShowEvent *) {
2612   TTool::Application *app = TTool::getApplication();
2613   connect(app->getCurrentOnionSkin(), SIGNAL(onionSkinMaskChanged()), this,
2614           SLOT(updateColors()));
2615   updateColors();
2616 }
2617 
hideEvent(QShowEvent *)2618 void ShiftTraceToolOptionBox::hideEvent(QShowEvent *) {
2619   TTool::Application *app = TTool::getApplication();
2620   disconnect(app->getCurrentOnionSkin(), SIGNAL(onionSkinMaskChanged()), this,
2621              SLOT(updateColors()));
2622 }
2623 
resetGhost(int index)2624 void ShiftTraceToolOptionBox::resetGhost(int index) {
2625   TTool::Application *app = TTool::getApplication();
2626   OnionSkinMask osm       = app->getCurrentOnionSkin()->getOnionSkinMask();
2627   osm.setShiftTraceGhostCenter(index, TPointD());
2628   osm.setShiftTraceGhostAff(index, TAffine());
2629   app->getCurrentOnionSkin()->setOnionSkinMask(osm);
2630   app->getCurrentOnionSkin()->notifyOnionSkinMaskChanged();
2631   TTool *tool = app->getCurrentTool()->getTool();
2632   if (tool) tool->reset();
2633 
2634   if (index == 0)
2635     m_resetPrevGhostBtn->setDisabled(true);
2636   else  // index == 1
2637     m_resetAfterGhostBtn->setDisabled(true);
2638 }
2639 
onResetPrevGhostBtnPressed()2640 void ShiftTraceToolOptionBox::onResetPrevGhostBtnPressed() { resetGhost(0); }
2641 
onResetAfterGhostBtnPressed()2642 void ShiftTraceToolOptionBox::onResetAfterGhostBtnPressed() { resetGhost(1); }
2643 
updateColors()2644 void ShiftTraceToolOptionBox::updateColors() {
2645   TPixel front, back;
2646   bool ink;
2647   Preferences::instance()->getOnionData(front, back, ink);
2648 
2649   m_prevFrame->setStyleSheet(QString("background:rgb(%1,%2,%3,255);")
2650                                  .arg((int)back.r)
2651                                  .arg((int)back.g)
2652                                  .arg((int)back.b));
2653   m_afterFrame->setStyleSheet(QString("background:rgb(%1,%2,%3,255);")
2654                                   .arg((int)front.r)
2655                                   .arg((int)front.g)
2656                                   .arg((int)front.b));
2657 }
2658 
updateStatus()2659 void ShiftTraceToolOptionBox::updateStatus() {
2660   TTool::Application *app = TTool::getApplication();
2661   OnionSkinMask osm       = app->getCurrentOnionSkin()->getOnionSkinMask();
2662   if (osm.getShiftTraceGhostAff(0).isIdentity() &&
2663       osm.getShiftTraceGhostCenter(0) == TPointD())
2664     m_resetPrevGhostBtn->setDisabled(true);
2665   else
2666     m_resetPrevGhostBtn->setEnabled(true);
2667 
2668   if (osm.getShiftTraceGhostAff(1).isIdentity() &&
2669       osm.getShiftTraceGhostCenter(1) == TPointD())
2670     m_resetAfterGhostBtn->setDisabled(true);
2671   else
2672     m_resetAfterGhostBtn->setEnabled(true);
2673 
2674   // Check the ghost index
2675   ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool;
2676   if (!stTool) return;
2677   if (stTool->getCurrentGhostIndex() == 0)
2678     m_prevRadioBtn->setChecked(true);
2679   else  // ghostIndex == 1
2680     m_afterRadioBtn->setChecked(true);
2681 }
2682 
onPrevRadioBtnClicked()2683 void ShiftTraceToolOptionBox::onPrevRadioBtnClicked() {
2684   ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool;
2685   if (!stTool) return;
2686   stTool->setCurrentGhostIndex(0);
2687 }
2688 
onAfterRadioBtnClicked()2689 void ShiftTraceToolOptionBox::onAfterRadioBtnClicked() {
2690   ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool;
2691   if (!stTool) return;
2692   stTool->setCurrentGhostIndex(1);
2693 }
2694 
2695 //=============================================================================
2696 // ZoomToolOptionBox
2697 //-----------------------------------------------------------------------------
2698 
ZoomToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)2699 ZoomToolOptionsBox::ZoomToolOptionsBox(QWidget *parent, TTool *tool,
2700                                        TPaletteHandle *pltHandle,
2701                                        ToolHandle *toolHandle)
2702     : ToolOptionsBox(parent) {
2703   setFrameStyle(QFrame::StyledPanel);
2704   setFixedHeight(26);
2705 
2706   QAction *resetZoomAction =
2707       CommandManager::instance()->getAction(VB_ZoomReset);
2708 
2709   QPushButton *button = new QPushButton(tr("Reset Zoom"));
2710   int buttonWidth     = fontMetrics().width(button->text()) + 10;
2711   button->setFixedWidth(buttonWidth);
2712   button->setFixedHeight(20);
2713   button->addAction(resetZoomAction);
2714 
2715   connect(button, SIGNAL(clicked()), resetZoomAction, SLOT(trigger()));
2716 
2717   m_layout->addStretch(1);
2718   m_layout->addWidget(button, 0);
2719   m_layout->addSpacing(5);
2720 }
2721 
2722 //=============================================================================
2723 // RotateToolOptionBox
2724 //-----------------------------------------------------------------------------
2725 
RotateToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)2726 RotateToolOptionsBox::RotateToolOptionsBox(QWidget *parent, TTool *tool,
2727                                            TPaletteHandle *pltHandle,
2728                                            ToolHandle *toolHandle)
2729     : ToolOptionsBox(parent) {
2730   setFrameStyle(QFrame::StyledPanel);
2731   setFixedHeight(26);
2732 
2733   QAction *resetRotationAction =
2734       CommandManager::instance()->getAction(VB_RotateReset);
2735 
2736   QPushButton *button = new QPushButton(tr("Reset Rotation"));
2737   int buttonWidth     = fontMetrics().width(button->text()) + 10;
2738   button->setFixedWidth(buttonWidth);
2739   button->setFixedHeight(20);
2740   button->addAction(resetRotationAction);
2741 
2742   connect(button, SIGNAL(clicked()), resetRotationAction, SLOT(trigger()));
2743 
2744   m_layout->addStretch(1);
2745   m_layout->addWidget(button, 0);
2746   m_layout->addSpacing(5);
2747 }
2748 
2749 //=============================================================================
2750 // HandToolOptionBox
2751 //-----------------------------------------------------------------------------
2752 
HandToolOptionsBox(QWidget * parent,TTool * tool,TPaletteHandle * pltHandle,ToolHandle * toolHandle)2753 HandToolOptionsBox::HandToolOptionsBox(QWidget *parent, TTool *tool,
2754                                        TPaletteHandle *pltHandle,
2755                                        ToolHandle *toolHandle)
2756     : ToolOptionsBox(parent) {
2757   setFrameStyle(QFrame::StyledPanel);
2758   setFixedHeight(26);
2759 
2760   QAction *resetPositionAction =
2761       CommandManager::instance()->getAction(VB_PositionReset);
2762 
2763   QPushButton *button = new QPushButton(tr("Reset Position"));
2764   int buttonWidth     = fontMetrics().width(button->text()) + 10;
2765   button->setFixedWidth(buttonWidth);
2766   button->setFixedHeight(20);
2767   button->addAction(resetPositionAction);
2768 
2769   connect(button, SIGNAL(clicked()), resetPositionAction, SLOT(trigger()));
2770 
2771   m_layout->addStretch(1);
2772   m_layout->addWidget(button, 0);
2773   m_layout->addSpacing(5);
2774 }
2775 
2776 //=============================================================================
2777 // ToolOptions
2778 //-----------------------------------------------------------------------------
2779 
ToolOptions()2780 ToolOptions::ToolOptions() : m_panel(0) {
2781   QHBoxLayout *mainLayout = new QHBoxLayout();
2782   mainLayout->setMargin(0);
2783   mainLayout->setSpacing(0);
2784   setLayout(mainLayout);
2785 }
2786 
2787 //-----------------------------------------------------------------------------
2788 
~ToolOptions()2789 ToolOptions::~ToolOptions() {}
2790 
2791 //-----------------------------------------------------------------------------
2792 
showEvent(QShowEvent *)2793 void ToolOptions::showEvent(QShowEvent *) {
2794   TTool::Application *app = TTool::getApplication();
2795   ToolHandle *currTool    = app->getCurrentTool();
2796   if (currTool) {
2797     onToolSwitched();
2798     connect(currTool, SIGNAL(toolSwitched()), SLOT(onToolSwitched()));
2799     connect(currTool, SIGNAL(toolChanged()), SLOT(onToolChanged()));
2800   }
2801 
2802   TObjectHandle *currObject = app->getCurrentObject();
2803   if (currObject) {
2804     onStageObjectChange();
2805     connect(currObject, SIGNAL(objectSwitched()), SLOT(onStageObjectChange()));
2806     connect(currObject, SIGNAL(objectChanged(bool)),
2807             SLOT(onStageObjectChange()));
2808   }
2809 
2810   TXshLevelHandle *currLevel = app->getCurrentLevel();
2811 
2812   if (currLevel)
2813     connect(currLevel, SIGNAL(xshLevelSwitched(TXshLevel *)), this,
2814             SLOT(onStageObjectChange()));
2815 }
2816 
2817 //-----------------------------------------------------------------------------
2818 
hideEvent(QShowEvent *)2819 void ToolOptions::hideEvent(QShowEvent *) {
2820   TTool::Application *app = TTool::getApplication();
2821   ToolHandle *currTool    = app->getCurrentTool();
2822   if (currTool) currTool->disconnect(this);
2823 
2824   TObjectHandle *currObject = app->getCurrentObject();
2825   if (currObject) currObject->disconnect(this);
2826 
2827   TXshLevelHandle *currLevel = app->getCurrentLevel();
2828   if (currLevel) currLevel->disconnect(this);
2829 }
2830 
2831 //-----------------------------------------------------------------------------
2832 
onToolSwitched()2833 void ToolOptions::onToolSwitched() {
2834   if (m_panel) m_panel->hide();
2835   m_panel = 0;
2836 
2837   TTool::Application *app = TTool::getApplication();
2838 
2839   // Quando i seguenti non serviranno piu', rimuovere gli header corrispondenti
2840   // in cima, thx
2841   TFrameHandle *currFrame   = app->getCurrentFrame();
2842   TObjectHandle *currObject = app->getCurrentObject();
2843   TXsheetHandle *currXsheet = app->getCurrentXsheet();
2844   TPaletteHandle *currPalette =
2845       app->getPaletteController()->getCurrentLevelPalette();
2846   ToolHandle *currTool = app->getCurrentTool();
2847 
2848   TTool *tool = app->getCurrentTool()->getTool();
2849   if (tool) {
2850     // c'e' un tool corrente
2851     ToolOptionsBox *panel                            = 0;
2852     std::map<TTool *, ToolOptionsBox *>::iterator it = m_panels.find(tool);
2853     if (it == m_panels.end()) {
2854       // ... senza panel associato
2855       if (tool->getName() == T_Edit) {
2856         TPropertyGroup *pg = tool->getProperties(0);
2857         panel = new ArrowToolOptionsBox(0, tool, pg, currFrame, currObject,
2858                                         currXsheet, currTool);
2859       } else if (tool->getName() == T_Selection)
2860         panel = new SelectionToolOptionsBox(0, tool, currPalette, currTool);
2861       else if (tool->getName() == T_Geometric)
2862         panel = new GeometricToolOptionsBox(0, tool, currPalette, currTool);
2863       else if (tool->getName() == T_Type)
2864         panel = new TypeToolOptionsBox(0, tool, currPalette, currTool);
2865       else if (tool->getName() == T_PaintBrush)
2866         panel = new PaintbrushToolOptionsBox(0, tool, currPalette, currTool);
2867       else if (tool->getName() == T_Fill) {
2868         if (tool->getTargetType() & TTool::RasterImage)
2869           panel =
2870               new FullColorFillToolOptionsBox(0, tool, currPalette, currTool);
2871         else
2872           panel = new FillToolOptionsBox(0, tool, currPalette, currTool);
2873       } else if (tool->getName() == T_Eraser)
2874         panel = new EraserToolOptionsBox(0, tool, currPalette, currTool);
2875       else if (tool->getName() == T_Tape)
2876         panel = new TapeToolOptionsBox(0, tool, currPalette, currTool);
2877       else if (tool->getName() == T_RGBPicker)
2878         panel = new RGBPickerToolOptionsBox(0, tool, currPalette, currTool,
2879                                             app->getPaletteController());
2880       else if (tool->getName() == T_Ruler) {
2881         RulerToolOptionsBox *p = new RulerToolOptionsBox(0, tool);
2882         panel                  = p;
2883         RulerTool *rt          = dynamic_cast<RulerTool *>(tool);
2884         if (rt) rt->setToolOptionsBox(p);
2885       } else if (tool->getName() == T_StylePicker)
2886         panel = new StylePickerToolOptionsBox(0, tool, currPalette, currTool,
2887                                               app->getPaletteController());
2888       else if (tool->getName() == "T_ShiftTrace")
2889         panel = new ShiftTraceToolOptionBox(this, tool);
2890       else if (tool->getName() == T_Zoom)
2891         panel = new ZoomToolOptionsBox(0, tool, currPalette, currTool);
2892       else if (tool->getName() == T_Rotate)
2893         panel = new RotateToolOptionsBox(0, tool, currPalette, currTool);
2894       else if (tool->getName() == T_Hand)
2895         panel = new HandToolOptionsBox(0, tool, currPalette, currTool);
2896       else
2897         panel = tool->createOptionsBox();  // Only this line should remain out
2898                                            // of that if/else monstrosity
2899 
2900       /* DANIELE: Regola per il futuro - NON FARE PIU' COME SOPRA.
2901 Bisogna cominciare a collegare il metodo virtuale
2902 createOptionsBox() di ogni tool.
2903 
2904 Chi ha tempo si adoperi un pochino per normalizzare
2905 la situazione anche per i tool sopra, plz - basta spostare
2906 un po' di codice... */
2907 
2908       m_panels[tool] = panel;
2909       layout()->addWidget(panel);
2910       emit newPanelCreated();
2911     } else {
2912       // il panel c'e' gia'.
2913       panel = it->second;
2914       panel->updateStatus();
2915     }
2916     m_panel = panel;
2917     m_panel->show();
2918   } else {
2919     // niente tool
2920   }
2921 }
2922 
2923 //-----------------------------------------------------------------------------
2924 
onToolChanged()2925 void ToolOptions::onToolChanged() {
2926   assert(m_panel);
2927   ToolOptionsBox *optionBox = dynamic_cast<ToolOptionsBox *>(m_panel);
2928   assert(optionBox);
2929   optionBox->updateStatus();
2930 }
2931 
2932 //-----------------------------------------------------------------------------
2933 
onStageObjectChange()2934 void ToolOptions::onStageObjectChange() {
2935   TTool *tool = TTool::getApplication()->getCurrentTool()->getTool();
2936   if (!tool) return;
2937 
2938   std::map<TTool *, ToolOptionsBox *>::iterator it = m_panels.find(tool);
2939   if (it == m_panels.end()) return;
2940 
2941   ToolOptionsBox *panel = it->second;
2942   panel->onStageObjectChange();
2943 }
2944