1 /* This file is part of the KDE project
2  * Copyright (C) 2012 C. Boemann <cbo@boemann.dk>
3  * Copyright (C) 2008 Jan Hambrecht <jaham@gmx.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "KoShadowConfigWidget.h"
22 #include "ui_KoShadowConfigWidget.h"
23 
24 #include <KoIcon.h>
25 #include <KoUnit.h>
26 #include <KoColorPopupAction.h>
27 #include <KoCanvasBase.h>
28 #include <KoCanvasResourceManager.h>
29 #include <KoSelection.h>
30 #include <KoShapeShadow.h>
31 #include <KoShapeShadowCommand.h>
32 #include <KoShapeManager.h>
33 
34 #include <klocalizedstring.h>
35 
36 #include <QCheckBox>
37 
38 #include <math.h>
39 
40 class Q_DECL_HIDDEN KoShadowConfigWidget::Private
41 {
42 public:
Private()43     Private()
44     {
45     }
46     Ui_KoShadowConfigWidget widget;
47     KoColorPopupAction *actionShadowColor;
48     KoCanvasBase *canvas;
49 };
50 
KoShadowConfigWidget(QWidget * parent)51 KoShadowConfigWidget::KoShadowConfigWidget(QWidget *parent)
52     : QWidget(parent)
53     , d(new Private())
54 {
55     d->widget.setupUi(this);
56     d->widget.shadowOffset->setValue(8.0);
57     d->widget.shadowBlur->setValue(8.0);
58     d->widget.shadowBlur->setMinimum(0.0);
59     d->widget.shadowAngle->setValue(315.0);
60     d->widget.shadowAngle->setMinimum(0.0);
61     d->widget.shadowAngle->setMaximum(360.0);
62     d->widget.shadowVisible->setChecked(false);
63     visibilityChanged();
64 
65     d->actionShadowColor = new KoColorPopupAction(this);
66     d->actionShadowColor->setCurrentColor(QColor(0, 0, 0, 192)); // some reasonable default for shadow
67     d->actionShadowColor->setIcon(koIcon("format-stroke-color"));
68     d->actionShadowColor->setToolTip(i18n("Change the color of the shadow"));
69     d->widget.shadowColor->setDefaultAction(d->actionShadowColor);
70 
71     connect(d->widget.shadowVisible, SIGNAL(toggled(bool)), this, SLOT(applyChanges()));
72     connect(d->widget.shadowVisible, SIGNAL(toggled(bool)), this, SLOT(visibilityChanged()));
73     connect(d->actionShadowColor, SIGNAL(colorChanged(KoColor)), this, SLOT(applyChanges()));
74     connect(d->widget.shadowAngle, SIGNAL(valueChanged(int)), this, SLOT(applyChanges()));
75     connect(d->widget.shadowOffset, SIGNAL(valueChangedPt(qreal)), this, SLOT(applyChanges()));
76     connect(d->widget.shadowBlur, SIGNAL(valueChangedPt(qreal)), this, SLOT(applyChanges()));
77 }
78 
~KoShadowConfigWidget()79 KoShadowConfigWidget::~KoShadowConfigWidget()
80 {
81     delete d;
82 }
83 
setShadowColor(const QColor & color)84 void KoShadowConfigWidget::setShadowColor(const QColor &color)
85 {
86     d->widget.shadowColor->blockSignals(true);
87     d->actionShadowColor->blockSignals(true);
88 
89     d->actionShadowColor->setCurrentColor( color );
90 
91     d->actionShadowColor->blockSignals(false);
92     d->widget.shadowColor->blockSignals(false);
93 }
94 
shadowColor() const95 QColor KoShadowConfigWidget::shadowColor() const
96 {
97     return d->actionShadowColor->currentColor();
98 }
99 
setShadowOffset(const QPointF & offset)100 void KoShadowConfigWidget::setShadowOffset(const QPointF &offset)
101 {
102     qreal length = sqrt(offset.x()*offset.x() + offset.y()*offset.y());
103     qreal angle = atan2(-offset.y(), offset.x());
104     if (angle < 0.0) {
105         angle += 2*M_PI;
106     }
107 
108     d->widget.shadowAngle->blockSignals(true);
109     d->widget.shadowAngle->setValue(-90 - angle * 180.0 / M_PI);
110     d->widget.shadowAngle->blockSignals(false);
111 
112     d->widget.shadowOffset->blockSignals(true);
113     d->widget.shadowOffset->changeValue(length);
114     d->widget.shadowOffset->blockSignals(false);
115 }
116 
shadowOffset() const117 QPointF KoShadowConfigWidget::shadowOffset() const
118 {
119     QPointF offset(d->widget.shadowOffset->value(), 0);
120     QTransform m;
121     m.rotate(d->widget.shadowAngle->value() + 90);
122     return m.map(offset);
123 }
124 
setShadowBlur(const qreal & blur)125 void KoShadowConfigWidget::setShadowBlur(const qreal &blur)
126 {
127     d->widget.shadowBlur->blockSignals(true);
128     d->widget.shadowBlur->changeValue(blur);
129     d->widget.shadowBlur->blockSignals(false);
130 }
131 
shadowBlur() const132 qreal KoShadowConfigWidget::shadowBlur() const
133 {
134     return d->widget.shadowBlur->value();
135 }
136 
setShadowVisible(bool visible)137 void KoShadowConfigWidget::setShadowVisible(bool visible)
138 {
139     d->widget.shadowVisible->blockSignals(true);
140     d->widget.shadowVisible->setChecked(visible);
141     d->widget.shadowVisible->blockSignals(false);
142     visibilityChanged();
143 }
144 
shadowVisible() const145 bool KoShadowConfigWidget::shadowVisible() const
146 {
147     return d->widget.shadowVisible->isChecked();
148 }
149 
visibilityChanged()150 void KoShadowConfigWidget::visibilityChanged()
151 {
152     d->widget.shadowAngle->setEnabled( d->widget.shadowVisible->isChecked() );
153     d->widget.shadowBlur->setEnabled( d->widget.shadowVisible->isChecked() );
154     d->widget.shadowColor->setEnabled( d->widget.shadowVisible->isChecked() );
155     d->widget.shadowOffset->setEnabled( d->widget.shadowVisible->isChecked() );
156 }
157 
applyChanges()158 void KoShadowConfigWidget::applyChanges()
159 {
160     if (d->canvas) {
161         KoSelection *selection = d->canvas->shapeManager()->selection();
162         KoShape * shape = selection->firstSelectedShape(KoFlake::TopLevelSelection);
163         if (! shape) {
164             return;
165         }
166 
167         KoShapeShadow *newShadow = new KoShapeShadow();
168         newShadow->setVisible(shadowVisible());
169         newShadow->setColor(shadowColor());
170         newShadow->setOffset(shadowOffset());
171         newShadow->setBlur(shadowBlur());
172         d->canvas->addCommand(new KoShapeShadowCommand(selection->selectedShapes(KoFlake::TopLevelSelection), newShadow));
173     }
174 }
175 
selectionChanged()176 void KoShadowConfigWidget::selectionChanged()
177 {
178     if (! d->canvas) {
179         return;
180     }
181 
182     KoSelection *selection = d->canvas->shapeManager()->selection();
183     KoShape * shape = selection->firstSelectedShape(KoFlake::TopLevelSelection);
184 
185     setEnabled(shape != nullptr);
186 
187     if (! shape) {
188         setShadowVisible(false);
189         return;
190     }
191 
192     KoShapeShadow * shadow = shape->shadow();
193     if (! shadow) {
194         setShadowVisible(false);
195         return;
196     }
197 
198     setShadowVisible(shadow->isVisible());
199     setShadowOffset(shadow->offset());
200     setShadowColor(shadow->color());
201     setShadowBlur(shadow->blur());
202 }
203 
setCanvas(KoCanvasBase * canvas)204 void KoShadowConfigWidget::setCanvas(KoCanvasBase *canvas)
205 {
206     d->canvas = canvas;
207     connect(canvas->shapeManager(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
208     connect(canvas->shapeManager(), SIGNAL(selectionContentChanged()), this, SLOT(selectionChanged()));
209 
210     setUnit(canvas->unit());
211 
212     connect( d->canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
213              this, SLOT(resourceChanged(int,QVariant)) );
214 }
215 
setUnit(const KoUnit & unit)216 void KoShadowConfigWidget::setUnit(const KoUnit &unit)
217 {
218     d->widget.shadowOffset->blockSignals(true);
219     d->widget.shadowBlur->blockSignals(true);
220     d->widget.shadowOffset->setUnit(unit);
221     d->widget.shadowBlur->setUnit(unit);
222     d->widget.shadowOffset->blockSignals(false);
223     d->widget.shadowBlur->blockSignals(false);
224 }
225 
resourceChanged(int key,const QVariant & res)226 void KoShadowConfigWidget::resourceChanged( int key, const QVariant & res )
227 {
228     if( key == KoCanvasResourceManager::Unit ) {
229         setUnit(res.value<KoUnit>());
230     }
231 }
232