1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8 gradienteditor - description
9 -------------------
10 begin : Mit Mai 26 2004
11 copyright : (C) 2004 by Franz Schmid
12 email : Franz.Schmid@altmuehlnet.de
13 ***************************************************************************/
14
15 /***************************************************************************
16 * *
17 * This program is free software; you can redistribute it and/or modify *
18 * it under the terms of the GNU General Public License as published by *
19 * the Free Software Foundation; either version 2 of the License, or *
20 * (at your option) any later version. *
21 * *
22 ***************************************************************************/
23
24 #include <algorithm>
25 #include <QApplication>
26 #include <QCursor>
27 #include <QEvent>
28 #include <QMenu>
29 #include <QMouseEvent>
30 #include <QPaintEvent>
31 #include <QPainter>
32 #include <QPixmap>
33 #include <QPolygon>
34 #include <QToolTip>
35
36 #include "fpoint.h"
37 #include "gradientpreview.h"
38 #include "iconmanager.h"
39 #include "scpainter.h"
40
41
GradientPreview(QWidget * pa)42 GradientPreview::GradientPreview(QWidget *pa) : QFrame(pa)
43 {
44 setFrameShape( QFrame::Panel );
45 setFrameShadow( QFrame::Sunken );
46 setLineWidth( 2 );
47 setMinimumSize(QSize(200, 70));
48 setMaximumSize(QSize(3000, 70));
49 setMouseTracking(true);
50 setFocusPolicy(Qt::ClickFocus);
51 Mpressed = false;
52 outside = true;
53 onlyselect = true;
54 isEditable = true;
55 fill_gradient = VGradient(VGradient::linear);
56 fill_gradient.clearStops();
57
58 QColor color;
59 color = QColor(255,255,255);
60 fill_gradient.addStop( color, 0.0, 0.5, 1.0 );
61 color = QColor(0,0,0);
62 fill_gradient.addStop( color, 1.0, 0.5, 1.0 );
63
64 QList<VColorStop*> cstops = fill_gradient.colorStops();
65 StopM.clear();
66 contextStop = 0;
67 ActStop = 0;
68 for (int i = 0; i < fill_gradient.stops(); ++i)
69 {
70 int center = qRound(cstops.at(i)->rampPoint * (width() - 20)) + 10;
71 StopM.append(center);
72 }
73 }
74
paintEvent(QPaintEvent * e)75 void GradientPreview::paintEvent(QPaintEvent *e)
76 {
77 QList<VColorStop*> cstops = fill_gradient.colorStops();
78 StopM.clear();
79 for (int i = 0; i < fill_gradient.stops(); ++i)
80 {
81 int center = qRound(cstops.at(i)->rampPoint * (width() - 20)) + 10;
82 StopM.append(center);
83 }
84 QImage pixm(width() - 20, 37, QImage::Format_ARGB32_Premultiplied);
85 QPainter pb;
86 QBrush b(QColor(205,205,205), IconManager::instance().loadPixmap("testfill.png"));
87 pb.begin(&pixm);
88 pb.fillRect(0, 0, pixm.width(), pixm.height(), b);
89 pb.end();
90 ScPainter *p = new ScPainter(&pixm, width() - 20, 37);
91 // p->clear(Qt::white);
92 p->setPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
93 p->setFillMode(ScPainter::Gradient);
94 p->fill_gradient = fill_gradient;
95 p->setGradient(VGradient::linear, FPoint(0, 20), FPoint(width() - 20, 20), FPoint(0, 0), 1.0, 0.0);
96 p->drawRect(0, 0, width() - 20, 37);
97 p->end();
98 delete p;
99 QPainter pw;
100 pw.begin(this);
101 pw.drawImage(10, 5, pixm);
102 if (isEditable)
103 {
104 for (int i = 0; i < fill_gradient.stops(); ++i)
105 {
106 int center = qRound(cstops.at(i)->rampPoint * (width() - 20)) + 10;
107 pw.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
108 if (StopM[qMax(ActStop,0)] == center)
109 pw.setBrush(Qt::red);
110 else
111 pw.setBrush(Qt::blue);
112 QPolygon cr;
113 cr.setPoints(3, center, 43, center - 4, 56, center + 4, 56);
114 pw.drawPolygon(cr);
115 }
116 }
117 pw.end();
118 QFrame::paintEvent(e);
119 }
120
keyPressEvent(QKeyEvent * e)121 void GradientPreview::keyPressEvent(QKeyEvent *e)
122 {
123 if (isEditable)
124 {
125 if(e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace)
126 {
127 if ((ActStop > 0) && (ActStop != static_cast<int>(StopM.count()-1)))
128 {
129 onlyselect = false;
130 fill_gradient.removeStop(ActStop);
131 ActStop = 0;
132 repaint();
133 QList<VColorStop*> cstops = fill_gradient.colorStops();
134 emit selectedStop(cstops.at(ActStop));
135 }
136 }
137 }
138 }
139
mousePressEvent(QMouseEvent * m)140 void GradientPreview::mousePressEvent(QMouseEvent *m)
141 {
142 QRect fpo;
143 Mpressed = true;
144 qApp->setOverrideCursor(QCursor(Qt::ArrowCursor));
145 ActStop = -1;
146 if (isEditable)
147 {
148 QList<VColorStop*> cstops = fill_gradient.colorStops();
149 for (int yg = 0; yg < static_cast<int>(StopM.count()); ++yg)
150 {
151 fpo = QRect(static_cast<int>(StopM[yg]) - 4, 43, 8, 13);
152 if (fpo.contains(m->pos()))
153 {
154 ActStop = yg;
155 emit selectedStop(cstops.at(ActStop));
156 repaint();
157 onlyselect = true;
158 return;
159 }
160 }
161 }
162 }
163
mouseReleaseEvent(QMouseEvent * m)164 void GradientPreview::mouseReleaseEvent(QMouseEvent *m)
165 {
166 qApp->restoreOverrideCursor();
167 QRect insideRect = QRect(10, 43, width() - 20, 13);
168 if (isEditable)
169 {
170 QRect fpo;
171 if (m->button() == Qt::LeftButton)
172 {
173 if ((Mpressed) && (ActStop > 0) && (ActStop != static_cast<int>(StopM.count()-1)) && (outside || !insideRect.contains(m->pos())))
174 {
175 onlyselect = false;
176 fill_gradient.removeStop(ActStop);
177 ActStop = 0;
178 repaint();
179 QList<VColorStop*> cstops = fill_gradient.colorStops();
180 emit selectedStop(cstops.at(ActStop));
181 }
182 if ((m->y() < height()) && (m->y() > 43) && (m->x() > 0) && (m->x() < width()) && (ActStop == -1))
183 {
184 QList<VColorStop*> cstops = fill_gradient.colorStops();
185 double newStop = static_cast<double>((m->x() - 10)) / (static_cast<double>(width()) - 20);
186 QColor stopColor = (cstops.count() > 0) ? cstops.at(0)->color : QColor(255, 255, 255);
187 QString stopName = (cstops.count() > 0) ? cstops.at(0)->name : QString("White");
188 int stopShade = (cstops.count() > 0) ? cstops.at(0)->shade : 100;
189 fill_gradient.addStop(stopColor, newStop, 0.5, 1.0, stopName, stopShade);
190 repaint();
191 onlyselect = false;
192 cstops = fill_gradient.colorStops();
193 for (int yg = 0; yg < static_cast<int>(StopM.count()); ++yg)
194 {
195 fpo = QRect(static_cast<int>(StopM[yg]) - 4, 43, 8, 13);
196 if (fpo.contains(m->pos()))
197 {
198 ActStop = yg;
199 emit selectedStop(cstops.at(ActStop));
200 repaint();
201 break;
202 }
203 }
204 }
205 }
206 else if (m->button() == Qt::RightButton)
207 {
208 Mpressed = false;
209 // QList<VColorStop*> cstops = fill_gradient.colorStops();
210 int stop = -1;
211 for (int yg = 0; yg < static_cast<int>(StopM.count()); ++yg)
212 {
213 fpo = QRect(static_cast<int>(StopM[yg]) - 4, 43, 8, 13);
214 if (fpo.contains(m->pos()))
215 {
216 stop = yg;
217 break;
218 }
219 }
220 contextStop = stop;
221 mPos = m->pos();
222 QMenu *pmen = new QMenu();
223 setCursor(QCursor(Qt::ArrowCursor));
224 pmen->addAction( tr("Add Stop"), this, SLOT(addStop()));
225 if (stop != -1)
226 pmen->addAction( tr("Remove Stop"), this, SLOT(removeStop()));
227 pmen->exec(QCursor::pos());
228 delete pmen;
229 }
230 }
231 Mpressed = false;
232 if ((!onlyselect) && (ActStop >= 0))
233 {
234 emit gradientChanged();
235 QList<VColorStop*> cstops = fill_gradient.colorStops();
236 emit currStep(cstops.at(ActStop)->rampPoint);
237 }
238 }
239
mouseMoveEvent(QMouseEvent * m)240 void GradientPreview::mouseMoveEvent(QMouseEvent *m)
241 {
242 QRect insideRect = QRect(10, 43, width() - 20, 13);
243 if (isEditable)
244 {
245 QRect fpo;
246 qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
247 if ((!Mpressed) && (m->y() < height()) && (m->y() > 43) && (m->x() > 9) && (m->x() < width()-9))
248 {
249 setCursor(IconManager::instance().loadCursor("AddPoint.png", 1, 1));
250 for (int yg = 0; yg < static_cast<int>(StopM.count()); ++yg)
251 {
252 fpo = QRect(static_cast<int>(StopM[yg]) - 4, 43, 8, 13);
253 if (fpo.contains(m->pos()))
254 {
255 setCursor(QCursor(Qt::SizeHorCursor));
256 return;
257 }
258 }
259 }
260 if (m->buttons() & Qt::LeftButton)
261 {
262 if ((Mpressed) && (m->y() < height()) && (m->y() > 43) && (m->x() > 9) && (m->x() < width() - 9) && (ActStop != -1))
263 {
264 qApp->changeOverrideCursor(QCursor(Qt::SizeHorCursor));
265 double newStop = static_cast<double>((m->x() - 10)) / (static_cast<double>(width()) - 20);
266 if (ActStop > 1)
267 {
268 if (StopM[ActStop-1]+2 >= m->x())
269 return;
270 }
271 if (ActStop < static_cast<int>(StopM.count()-2))
272 {
273 if (StopM[ActStop+1]-2 < m->x())
274 return;
275 }
276 StopM[ActStop] = m->x();
277 QList<VColorStop*> cstops = fill_gradient.colorStops();
278 cstops.at(ActStop)->rampPoint = newStop;
279 std::sort(cstops.begin(), cstops.end());
280 onlyselect = false;
281 repaint();
282 }
283 if ((Mpressed) && (outside || !insideRect.contains(m->pos())) && (ActStop > 0) && (ActStop != static_cast<int>(StopM.count()-1)))
284 qApp->changeOverrideCursor(IconManager::instance().loadCursor("DelPoint.png", 1, 1));
285 }
286 }
287 }
288
leaveEvent(QEvent *)289 void GradientPreview::leaveEvent(QEvent*)
290 {
291 if (isEditable)
292 {
293 if (Mpressed)
294 {
295 if ((ActStop > 0) && (ActStop != static_cast<int>(StopM.count()-1)))
296 qApp->changeOverrideCursor(IconManager::instance().loadCursor("DelPoint.png", 1, 1));
297 else
298 qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
299 }
300 outside = true;
301 }
302 }
303
enterEvent(QEvent *)304 void GradientPreview::enterEvent(QEvent*)
305 {
306 outside = false;
307 }
308
addStop()309 void GradientPreview::addStop()
310 {
311 QList<VColorStop*> cstops = fill_gradient.colorStops();
312 double newStop = static_cast<double>((mPos.x() - 10)) / (static_cast<double>(width()) - 20);
313 QColor stopColor = (cstops.count() > 0) ? cstops.at(0)->color : QColor(255, 255, 255);
314 QString stopName = (cstops.count() > 0) ? cstops.at(0)->name : QString("White");
315 int stopShade = (cstops.count() > 0) ? cstops.at(0)->shade : 100;
316 fill_gradient.addStop(stopColor, newStop, 0.5, 1.0, stopName, stopShade);
317 repaint();
318 onlyselect = false;
319 cstops = fill_gradient.colorStops();
320 for (int yg = 0; yg < static_cast<int>(StopM.count()); ++yg)
321 {
322 QRect fpo = QRect(static_cast<int>(StopM[yg]) - 4, 43, 8, 13);
323 if (fpo.contains(mPos))
324 {
325 ActStop = yg;
326 emit selectedStop(cstops.at(ActStop));
327 repaint();
328 break;
329 }
330 }
331 }
332
removeStop()333 void GradientPreview::removeStop()
334 {
335 if ((contextStop > 0) && (contextStop != static_cast<int>(StopM.count()-1)))
336 {
337 onlyselect = false;
338 fill_gradient.removeStop(contextStop);
339 ActStop = 0;
340 repaint();
341 QList<VColorStop*> cstops = fill_gradient.colorStops();
342 emit selectedStop(cstops.at(ActStop));
343 }
344 }
345
updateDisplay()346 void GradientPreview::updateDisplay()
347 {
348 repaint();
349 if (!fill_gradient.colorStops().isEmpty())
350 {
351 QList<VColorStop*> cstops = fill_gradient.colorStops();
352 emit selectedStop(cstops.at(ActStop));
353 }
354 }
355
setActColor(const QColor & c,const QString & n,int s)356 void GradientPreview::setActColor(const QColor& c, const QString& n, int s)
357 {
358 if (ActStop == -1)
359 return;
360 QList<VColorStop*> cstops = fill_gradient.colorStops();
361 cstops.at(ActStop)->color = c;
362 cstops.at(ActStop)->name = n;
363 cstops.at(ActStop)->shade = s;
364 repaint();
365 }
366
setActTrans(double t)367 void GradientPreview::setActTrans(double t)
368 {
369 if (ActStop == -1)
370 return;
371 QList<VColorStop*> cstops = fill_gradient.colorStops();
372 cstops.at(ActStop)->opacity = t;
373 repaint();
374 }
375
setActStep(double t)376 void GradientPreview::setActStep(double t)
377 {
378 if (ActStop == -1)
379 return;
380 QList<VColorStop*> cstops = fill_gradient.colorStops();
381 cstops.at(ActStop)->rampPoint = t;
382 repaint();
383 }
384
setGradient(const VGradient & gradient)385 void GradientPreview::setGradient(const VGradient& gradient)
386 {
387 if ((gradient.colorStops().count() == fill_gradient.colorStops().count()) && (ActStop >= 0))
388 {
389 int diffStops = 0;
390 for (int i = 0; i < fill_gradient.colorStops().count(); ++i)
391 {
392 VColorStop* stop1 = gradient.colorStops().at(i);
393 VColorStop* stop2 = fill_gradient.colorStops().at(i);
394 if ((stop1->color != stop2->color) || (stop1->midPoint != stop2->midPoint) ||
395 (stop1->name != stop2->name) || (stop1->opacity != stop2->opacity) ||
396 (stop1->rampPoint != stop2->rampPoint) || (stop1->shade != stop2->shade))
397 {
398 ++diffStops;
399 }
400 }
401 if (diffStops > 1)
402 ActStop = 0;
403 }
404 if ((ActStop < 0) && (gradient.colorStops().count() > 0))
405 ActStop = 0;
406 if (ActStop >= gradient.colorStops().count())
407 ActStop = 0;
408 fill_gradient = gradient;
409 }
410
setGradientEditable(bool val)411 void GradientPreview::setGradientEditable(bool val)
412 {
413 isEditable = val;
414 repaint();
415 }
416