1 /****************************************************************************
2 * MeshLab                                                           o o     *
3 * A versatile mesh processing toolbox                             o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2005-2008                                           \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 
24 #include "rfx_colorbox.h"
25 
26 const QString RfxColorBox::_BASE_RGB_BOX_STYLE = QString("margin-left: 25px;border-top-left-radius: 5px;border-bottom-left-radius: 5px;border-left: 1px solid black;border-top: 1px solid black;border-bottom: 1px solid black;padding: 2px;");
27 const QString RfxColorBox::_BASE_RGBA_BOX_STYLE = QString("margin-left: 25px;margin-right: 25px;border: 1px solid black;border-radius: 5px;padding: 2px;");
28 
29 /* Constructor
30    @param w the width of the widget.
31    @param h the height of the widget.
32    @param first the start color of the box.
33    @param parent the parent widget. Default to 0.
34 */
RfxColorBox(const int & w,const int & h,const QColor & first,QWidget * parent)35 RfxColorBox::RfxColorBox(const int& w, const int& h, const QColor& first, QWidget* parent)
36 : QWidget(parent)
37 {
38      int r,g,b,a;
39      r = first.red();
40      g = first.green();
41      b = first.blue();
42      a = first.alpha();
43 
44      this->_rgbaBox = new QPushButton(this);
45      this->_rgbaBox->setObjectName("rgbaBox");
46      this->_rgbaBox->setFixedSize (w, h);
47      this->_rgbaBox->setStyleSheet(RfxColorBox::_BASE_RGBA_BOX_STYLE + QString("background-color: rgba(%1,%2,%3,%4);").arg(r).arg(g).arg(b).arg(a));
48 
49      this->_rgbBox = new QFrame(this);
50      this->_rgbBox->setObjectName("rgbBox");
51      this->_rgbBox->setFixedSize ((w/2), h);
52      this->_rgbBox->setStyleSheet(RfxColorBox::_BASE_RGB_BOX_STYLE + QString("background-color: rgb(%1,%2,%3);").arg(r).arg(g).arg(b));
53 
54      this->_scacchiera = new QFrame(this);
55      this->_scacchiera->setObjectName("scacchiera");
56      this->_scacchiera->setStyleSheet(RfxColorBox::_BASE_RGBA_BOX_STYLE + QString("background-image: url(:/images/scacchiera.png);"));
57      this->_scacchiera->setFixedSize (w, h);
58 
59 
60      this->_rgbBox->raise();
61      this->_rgbaBox->raise();
62 
63 	 QVBoxLayout *verticalLayout = new QVBoxLayout();
64 
65 
66 	/* the sliders and text boxes */
67 	this->_redS = new QSlider();
68 	initSlider(_redS, r);
69 	this->_redT = new QLineEdit(QString().setNum(r));
70 	initTextBox(this->_redT);
71 	connect(this->_redT, SIGNAL(editingFinished()), this, SLOT(setR()));
72 
73 	this->_greenS = new QSlider();
74 	initSlider(_greenS, g);
75 	this->_greenT = new QLineEdit(QString().setNum(g));
76 	initTextBox(this->_greenT);
77 	connect(this->_greenT, SIGNAL(editingFinished()), this, SLOT(setG()));
78 
79 	this->_blueS = new QSlider();
80 	initSlider(_blueS, b);
81 	this->_blueT = new QLineEdit(QString().setNum(b));
82 	initTextBox(this->_blueT);
83 	connect(this->_blueT, SIGNAL(editingFinished()), this, SLOT(setB()));
84 
85 	this->_alphaS = new QSlider();
86 	initSlider(_alphaS, a);
87 	this->_alphaT = new QLineEdit(QString().setNum(a));
88 	initTextBox(this->_alphaT);
89 	connect(this->_alphaT, SIGNAL(editingFinished()), this, SLOT(setA()));
90 
91 	connectSliders();
92 
93 	QHBoxLayout *redLayout = new QHBoxLayout();
94 	QWidget* redBox = new QWidget();
95 	redBox->setFixedSize (10, 10);
96 	redBox->setStyleSheet("background-color: rgb(255,0,0);");
97 	redLayout->addWidget(redBox);
98 	redLayout->addWidget(this->_redS);
99 	redLayout->addWidget(this->_redT);
100 	redLayout->setSpacing(3);
101 
102 	QHBoxLayout *greenLayout = new QHBoxLayout();
103 	QWidget* greenBox = new QWidget();
104 	greenBox->setFixedSize (10, 10);
105 	greenBox->setStyleSheet("background-color: rgb(0,255,0);");
106 	greenLayout->addWidget(greenBox);
107 	greenLayout->addWidget(this->_greenS);
108 	greenLayout->addWidget(this->_greenT);
109 	greenLayout->setSpacing(3);
110 
111 	QHBoxLayout *blueLayout = new QHBoxLayout();
112 	QWidget* blueBox = new QWidget();
113 	blueBox->setFixedSize (10, 10);
114 	blueBox->setStyleSheet("background-color: rgb(0,0,255);");
115 	blueLayout->addWidget(blueBox);
116 	blueLayout->addWidget(this->_blueS);
117 	blueLayout->addWidget(this->_blueT);
118 	blueLayout->setSpacing(3);
119 
120 	QHBoxLayout *alphaLayout = new QHBoxLayout();
121 	QWidget* alphaBox = new QWidget();
122 	alphaBox->setFixedSize (10, 10);
123 	alphaBox->setStyleSheet("background-color: rgb(100,100,100);");
124 	alphaLayout->addWidget(alphaBox);
125 	alphaLayout->addWidget(this->_alphaS);
126 	alphaLayout->addWidget(this->_alphaT);
127 	alphaLayout->setSpacing(3);
128 
129 	QGridLayout *colorDialogLayout = new QGridLayout();
130 	colorDialogLayout->setVerticalSpacing(0);
131 	colorDialogLayout->setHorizontalSpacing(0);
132 	colorDialogLayout->setMargin(0);
133 	colorDialogLayout->setSpacing(0);
134 
135 	verticalLayout->addLayout(redLayout);
136 	verticalLayout->addLayout(greenLayout);
137 	verticalLayout->addLayout(blueLayout);
138 	verticalLayout->addLayout(alphaLayout);
139 
140 	connect(this->_rgbaBox, SIGNAL(clicked()), this, SLOT(setBoxColorFromDialog()));
141 
142      QGridLayout *layout = new QGridLayout();
143      layout->addWidget(_scacchiera, 0, 0);
144      layout->addWidget(_rgbBox, 0, 0);
145      layout->addWidget(_rgbaBox, 0, 0);
146      this->_rgbBox->raise();
147      this->_rgbaBox->raise();
148 
149 	 colorDialogLayout->addLayout(verticalLayout, 0,0);
150 	 colorDialogLayout->addLayout(layout, 0,1);
151 
152 	setLayout(colorDialogLayout);
153 }
154 
~RfxColorBox()155 RfxColorBox::~RfxColorBox()
156 {
157 	if(this->_rgbaBox)
158 		delete _rgbaBox;
159 	if(this->_rgbBox)
160 		delete _rgbBox;
161 	if(this->_scacchiera)
162 		delete _scacchiera;
163 
164 	if(this->_redS)
165 		delete _redS;
166 	if(this->_greenS)
167 		delete _greenS;
168 	if(this->_blueS)
169 		delete _blueS;
170 	if(this->_alphaS)
171 		delete _alphaS;
172 
173 	if(this->_redT)
174 		delete _redT;
175 	if(this->_greenT)
176 		delete _greenT;
177 	if(this->_blueT)
178 		delete _blueT;
179 	if(this->_alphaT)
180 		delete _alphaT;
181 }
182 
183 /* Receives button click and shows a default system dialog for color selection.
184 Once the color has been selected sets it as the color of the widget and emits the color changes signals.
185 */
setBoxColorFromDialog()186 void RfxColorBox::setBoxColorFromDialog(){
187 
188 	QColor c = QColorDialog::getColor(QColor(_redS->value(), _greenS->value(), _blueS->value()));//(*(this->_color));
189      if(c.isValid()){
190 		disconnectSliders();
191 		this->_redS->setValue(c.red());
192 		this->_redS->setToolTip(QString().setNum(c.red()));
193 		this->_redT->setText(QString().setNum(c.red()));
194 
195 		this->_greenS->setValue(c.green());
196 		this->_greenS->setToolTip(QString().setNum(c.green()));
197 		this->_greenT->setText(QString().setNum(c.green()));
198 
199 		this->_blueS->setValue(c.blue());
200 		this->_blueS->setToolTip(QString().setNum(c.blue()));
201 		this->_blueT->setText(QString().setNum(c.blue()));
202 
203 		emit colorChanged();
204 		int r, g, b, a;
205 		r = c.red();
206 		g = c.green();
207 		b = c.blue();
208 		a = this->_alphaS->value();
209 
210 		int* vals[4] = {&r, &g, &b, &a};
211 		this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_ALL, vals));
212 		this->_rgbBox->setStyleSheet(getNewRGBStylesheet(this->_rgbBox->styleSheet(), CHANNEL_ALL, vals));
213 		connectSliders();
214      }
215 }
216 
217 /* Sets just the red channel.
218    @param r The new red value.
219 */
setR(int r)220 void RfxColorBox::setR(int r){
221 	this->_redS->setToolTip(QString().setNum(r));
222 	this->_redT->setText(QString().setNum(r));
223 	emit colorChanged();
224      int* vals[1] = {&r};
225      this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_R, vals));
226      this->_rgbBox->setStyleSheet(getNewRGBStylesheet(this->_rgbBox->styleSheet(), CHANNEL_R, vals));
227 }
228 
229 /* Sets just the green channel.
230    @param g The new green value.
231 */
setG(int g)232 void RfxColorBox::setG(int g){
233 	this->_greenS->setToolTip(QString().setNum(g));
234 	this->_greenT->setText(QString().setNum(g));
235 	emit colorChanged();
236      int* vals[1] = {&g};
237      this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_G, vals));
238      this->_rgbBox->setStyleSheet(getNewRGBStylesheet(this->_rgbBox->styleSheet(), CHANNEL_G, vals));
239 }
240 
241 /* Sets just the blue channel.
242    @param b The new blue value.
243 */
setB(int b)244 void RfxColorBox::setB(int b){
245 this->_blueS->setToolTip(QString().setNum(b));
246 this->_blueT->setText(QString().setNum(b));
247 emit colorChanged();
248      int* vals[1] = {&b};
249 	 this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_B, vals));
250      this->_rgbBox->setStyleSheet(getNewRGBStylesheet(this->_rgbBox->styleSheet(), CHANNEL_B, vals));
251 }
252 
253 /* Sets just the alpha channel.
254    @param a The new alpha value.
255 */
setA(int a)256 void RfxColorBox::setA(int a){
257 	this->_alphaS->setToolTip(QString().setNum(a));
258 	this->_alphaT->setText(QString().setNum(a));
259 	emit colorChanged();
260      int* vals[1] = {&a};
261      this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_A, vals));
262 }
263 
264 /* Sets just the red channel.*/
setR()265 void RfxColorBox::setR(){
266 	bool res = false;
267 	int val = this->_redT->text().toInt(&res);
268 	if (!res){
269 		this->_redT->setText(QString().setNum(this->_redS->value()));
270 		return;
271 	}
272 
273 	if (val > 255)
274 		this->_redS->setValue(255);
275 	else if (val < 0)
276 		this->_redS->setValue(0);
277 	else
278 		this->_redS->setValue(val);
279 }
280 
281 /* Sets just the green channel.*/
setG()282 void RfxColorBox::setG(){
283 	bool res = false;
284 	int val = this->_greenT->text().toInt(&res);
285 	if (!res){
286 		this->_redT->setText(QString().setNum(this->_greenS->value()));
287 		return;
288 	}
289 
290 	if (val > 255)
291 		this->_greenS->setValue(255);
292 	else if (val < 0)
293 		this->_greenS->setValue(0);
294 	else
295 		this->_greenS->setValue(val);
296 }
297 
298 /* Sets just the blue channel.*/
setB()299 void RfxColorBox::setB(){
300 	bool res = false;
301 	int val = this->_blueT->text().toInt(&res);
302 	if (!res){
303 		this->_blueT->setText(QString().setNum(this->_blueS->value()));
304 		return;
305 	}
306 
307 	if (val > 255)
308 		this->_blueS->setValue(255);
309 	else if (val < 0)
310 		this->_blueS->setValue(0);
311 	else
312 		this->_blueS->setValue(val);
313 }
314 
315 /* Sets just the alpha channel.*/
setA()316 void RfxColorBox::setA(){
317 	bool res = false;
318 	int val = this->_alphaT->text().toInt(&res);
319 	if (!res){
320 		this->_alphaT->setText(QString().setNum(this->_alphaS->value()));
321 		return;
322 	}
323 
324 	if (val > 255)
325 		this->_alphaS->setValue(255);
326 	else if (val < 0)
327 		this->_alphaS->setValue(0);
328 	else
329 		this->_alphaS->setValue(val);
330 }
331 
332 /*
333      Returns a string rapresenting a new stylesheet(with alpha channel)
334 	 @param stykeSheet the old stylesheet.
335 	 @param channels The channel that have to be modified.
336 	 @param vals the new values
337 	 @return the new stylesheet
338 
339 */
getNewRGBAStylesheet(const QString & styleSheet,RfxColorBox::Channels channels,int * vals[])340 QString RfxColorBox::getNewRGBAStylesheet(const QString& styleSheet, RfxColorBox::Channels channels, int* vals[]){
341      int openBracket = styleSheet.indexOf("(");
342      int closedBracket = styleSheet.indexOf(")");
343      QStringList list = styleSheet.mid(openBracket + 1, closedBracket - openBracket).split(",");
344      QString newStyleSheet = RfxColorBox::_BASE_RGBA_BOX_STYLE + QString("background-color: rgba(");
345 
346 	 switch(channels){
347 		 case CHANNEL_R :
348           newStyleSheet = newStyleSheet+QString("%1,").arg(*vals[0])+list[1]+','+list[2]+','+list[3]+';';
349 		  break;
350 
351 		 case CHANNEL_G:
352           newStyleSheet = newStyleSheet+list[0]+','+QString("%1,").arg(*vals[0])+list[2]+','+list[3]+';';
353 		  break;
354 
355 		 case CHANNEL_B:
356 		  newStyleSheet = newStyleSheet+list[0]+','+list[1]+','+QString("%1,").arg(*vals[0])+list[3]+';';
357 		  break;
358 
359 		 case CHANNEL_A:
360 		  newStyleSheet = newStyleSheet+list[0]+','+list[1]+','+list[2]+','+QString("%1);").arg(*vals[0]);
361 		  break;
362 
363 		 case CHANNEL_ALL:
364 			newStyleSheet = newStyleSheet+QString("%1,").arg(*vals[0])+QString("%1,").arg(*vals[1])+QString("%1,").arg(*vals[2])+QString("%1);").arg(*vals[3]);
365 			break;
366      }
367 
368      return newStyleSheet;
369 }
370 
371 /*
372 	 Returns a string rapresenting a new stylesheet(without alpha channel)
373 	 @param stykeSheet the old stylesheet.
374 	 @param channels The channel that have to be modified.
375 	 @param vals the new values
376 	 @return the new stylesheet
377 
378 */
getNewRGBStylesheet(const QString & styleSheet,RfxColorBox::Channels channels,int * vals[])379 QString RfxColorBox::getNewRGBStylesheet(const QString& styleSheet, RfxColorBox::Channels channels, int* vals[]){
380      int openBracket = styleSheet.indexOf("(");
381      int closedBracket = styleSheet.indexOf(")");
382      QStringList list = styleSheet.mid(openBracket + 1, closedBracket - openBracket).split(",");
383      QString newStyleSheet = RfxColorBox::_BASE_RGB_BOX_STYLE + QString("background-color: rgb(");
384 
385 	 switch(channels){
386 		 case CHANNEL_R :
387           newStyleSheet = newStyleSheet+QString("%1,").arg(*vals[0])+list[1]+','+list[2]+';';
388 		  break;
389 
390 		 case CHANNEL_G:
391           newStyleSheet = newStyleSheet+list[0]+','+QString("%1,").arg(*vals[0])+list[2]+';';
392 		  break;
393 
394 		 case CHANNEL_B:
395 		  newStyleSheet = newStyleSheet+list[0]+','+list[1]+','+QString("%1);").arg(*vals[0]);
396 		  break;
397 
398 		 case CHANNEL_A:
399 		  break;
400 
401 		 case CHANNEL_ALL:
402 			newStyleSheet = newStyleSheet+QString("%1,").arg(*vals[0])+QString("%1,").arg(*vals[1])+QString("%1);").arg(*vals[2]);
403 			break;
404      }
405      return newStyleSheet;
406 }
407 
408 
409 /* Initialize a slider
410 @param slider the slider to initialize
411 @param value the initial value
412 */
initSlider(QSlider * slider,int value)413 void RfxColorBox::initSlider(QSlider* slider, int value){
414 	slider->setTickPosition(QSlider::NoTicks);
415 	slider->setOrientation(Qt::Horizontal);
416 	slider->setMaximumSize(100, 15);
417 
418 	slider->setTickInterval(1);
419 	slider->setRange(0,255);
420 	slider->setValue(value);
421 	slider->setToolTip(QString().setNum(value));
422 }
423 
424 /* Initialize a text box.
425 @param box the text box to initialize
426 */
initTextBox(QLineEdit * box)427 void RfxColorBox::initTextBox(QLineEdit* box){
428 	box->setAlignment(Qt::AlignRight);
429 	box->setMaximumWidth(75);
430 	box->setMaximumHeight(15);
431 	box->setFont(QFont("verdana", 7));
432 }
433 
434 /* Connects all the slider to the color box. */
connectSliders()435 void RfxColorBox::connectSliders(){
436 	connect(this->_redS, SIGNAL(valueChanged(int)), this, SLOT(setR(int)));
437 	 connect(this->_greenS, SIGNAL(valueChanged(int)), this, SLOT(setG(int)));
438 	 connect(this->_blueS, SIGNAL(valueChanged(int)), this, SLOT(setB(int)));
439 	 connect(this->_alphaS, SIGNAL(valueChanged(int)), this, SLOT(setA(int)));
440 }
441 
442 /* Disconnects all the slider to the color box. */
disconnectSliders()443 void RfxColorBox::disconnectSliders(){
444 	disconnect(this->_redS, SIGNAL(valueChanged(int)), this, SLOT(setR(int)));
445 	 disconnect(this->_greenS, SIGNAL(valueChanged(int)), this, SLOT(setG(int)));
446 	 disconnect(this->_blueS, SIGNAL(valueChanged(int)), this, SLOT(setB(int)));
447 	 disconnect(this->_alphaS, SIGNAL(valueChanged(int)), this, SLOT(setA(int)));
448 }