Fix README.md
[gencolormap.git] / colormapwidgets.cpp
1 /*
2  * Copyright (C) 2015, 2016 Computer Graphics Group, University of Siegen
3  * Written by Martin Lambers <martin.lambers@uni-siegen.de>
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23
24 #include "gui.hpp"
25
26 #include <QGridLayout>
27 #include <QLabel>
28 #include <QSlider>
29 #include <QDoubleSpinBox>
30 #include <QPushButton>
31 #include <QColorDialog>
32 #include <QImage>
33 #include <QtMath>
34
35 #include "colormapwidgets.hpp"
36 #include "colormap.hpp"
37
38
39 /* References */
40
41 static QString brewerlike_reference = QString("Relevant paper: "
42         "M. Wijffelaars, R. Vliegen, J. J. van Wijk, E-J. van der Linden, "
43         "<a href=\"http://dx.doi.org/10.1111/j.1467-8659.2008.01203.x\">Generating Color Palettes using Intuitive Parameters</a>, "
44         "Computer Graphics Forum 27(3), May 2008.");
45
46 static QString plseq_lightness_reference = QString(
47         "Perceptually linear, constant hue, varying lightness and saturation.<br>"
48         "Computed in CIELUV/LCH color space.");
49
50 static QString plseq_saturation_reference = QString(
51         "Perceptually linear, constant lightness and hue, varying saturation.<br>"
52         "Computed in CIELUV/LCH color space.");
53
54 static QString plseq_rainbow_reference = QString(
55         "Perceptually linear, varying lightness, saturation, and hue (rainbow).<br>"
56         "Computed in CIELUV/LCH color space.");
57
58 static QString plseq_blackbody_reference = QString(
59         "Perceptually linear, varying lightness, saturation, and hue (black body at increasing temperatures).<br>"
60         "Computed in CIELUV/LCH color space.");
61
62 static QString pldiv_lightness_reference = QString(
63         "Perceptually linear, constant hues, varying lightness and saturation.<br>"
64         "Computed in CIELUV/LCH color space.");
65
66 static QString pldiv_saturation_reference = QString(
67         "Perceptually linear, constant lightness and hues, varying saturation.<br>"
68         "Computed in CIELUV/LCH color space.");
69
70 static QString plqual_hue_reference = QString(
71         "Perceptually linear, constant lightness and saturation, evenly distributed hue.<br>"
72         "Computed in CIELUV/LCH color space.");
73
74 static QString cubehelix_reference = QString("Relevant paper: "
75         "D. A. Green, "
76         "<a href=\"http://www.mrao.cam.ac.uk/~dag/CUBEHELIX/\">A colour scheme for the display of astronomical intensity</a>, "
77         "Bulletin of the Astronomical Society of India 39(2), June 2011.");
78
79 static QString moreland_reference = QString("Relevant paper: "
80         "K. Moreland, "
81         "<a href=\"http://www.kennethmoreland.com/color-maps/\">Diverging Color Maps for Scientific Visualization</a>, "
82         "Proc. Int. Symp. Visual Computing, December 2009."); // DOI 10.1007/978-3-642-10520-3_9.
83
84 static QString mcnames_references = QString("Relevant paper: "
85         "J. McNames, "
86         "<a href=\"http://dx.doi.org/10.1109/MSP.2006.1593340\">An Effective Color Scale for Simultaneous Color and Gray-Scale Publications</a>, "
87         "IEEE Signal Processing Magazine 23(1), January 2006.");
88
89 /* ColorMapCombinedSliderSpinBox */
90
91 ColorMapCombinedSliderSpinBox::ColorMapCombinedSliderSpinBox(float minval, float maxval, float step) :
92     _update_lock(false),
93     minval(minval), maxval(maxval), step(step)
94 {
95     slider = new QSlider(Qt::Horizontal);
96     slider->setMinimum(0);
97     slider->setMaximum((maxval - minval) / step);
98     slider->setSingleStep(step);
99
100     spinbox = new QDoubleSpinBox();
101     spinbox->setRange(minval, maxval);
102     spinbox->setSingleStep(step);
103     spinbox->setDecimals(std::log10(1.0f / step));
104
105     connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged()));
106     connect(spinbox, SIGNAL(valueChanged(double)), this, SLOT(spinboxChanged()));
107 }
108
109 float ColorMapCombinedSliderSpinBox::value() const
110 {
111     return spinbox->value();
112 }
113
114 void ColorMapCombinedSliderSpinBox::setValue(float v)
115 {
116     _update_lock = true;
117     spinbox->setValue(v);
118     slider->setValue((v - minval) / step);
119     _update_lock = false;
120 }
121
122 void ColorMapCombinedSliderSpinBox::sliderChanged()
123 {
124     if (!_update_lock) {
125         _update_lock = true;
126         int i = slider->value();
127         float v = i * step + minval;
128         spinbox->setValue(v);
129         _update_lock = false;
130         emit valueChanged(value());
131     }
132 }
133
134 void ColorMapCombinedSliderSpinBox::spinboxChanged()
135 {
136     if (!_update_lock) {
137         _update_lock = true;
138         float v = spinbox->value();
139         int i = (v - minval) / step;
140         slider->setValue(i);
141         _update_lock = false;
142         emit valueChanged(value());
143     }
144 }
145
146 /* ColorMapWidget */
147
148 ColorMapWidget::ColorMapWidget() : QWidget()
149 {
150 }
151
152 ColorMapWidget::~ColorMapWidget()
153 {
154 }
155
156 QImage ColorMapWidget::colorMapImage(const QVector<QColor>& colormap, int width, int height)
157 {
158     if (width <= 0)
159         width = colormap.size();
160     if (height <= 0)
161         height = colormap.size();
162     QImage img(width, height, QImage::Format_RGB32);
163     bool y_direction = (height > width);
164     if (y_direction) {
165         for (int y = 0; y < height; y++) {
166             float entry_height = height / static_cast<float>(colormap.size());
167             int i = y / entry_height;
168             QRgb rgb = colormap[i].rgb();
169             QRgb* scanline = reinterpret_cast<QRgb*>(img.scanLine(height - 1 - y));
170             for (int x = 0; x < width; x++)
171                 scanline[x] = rgb;
172         }
173     } else {
174         for (int y = 0; y < height; y++) {
175             QRgb* scanline = reinterpret_cast<QRgb*>(img.scanLine(y));
176             for (int x = 0; x < width; x++) {
177                 float entry_width = width / static_cast<float>(colormap.size());
178                 int i = x / entry_width;
179                 scanline[x] = colormap[i].rgb();
180             }
181         }
182     }
183     return img;
184 }
185
186 /* Helper functions for ColorMap*Widget */
187
188 static QVector<QColor> toQColor(const QVector<unsigned char>& cm)
189 {
190     QVector<QColor> colormap(cm.size() / 3);
191     for (int i = 0; i < colormap.size(); i++)
192         colormap[i] = QColor(cm[3 * i + 0], cm[3 * i + 1], cm[3 * i + 2]);
193     return colormap;
194 }
195
196 static void hideWidgetButPreserveSize(QWidget* widget)
197 {
198     QSizePolicy sp = widget->sizePolicy();
199     sp.setRetainSizeWhenHidden(true);
200     widget->setSizePolicy(sp);
201     widget->hide();
202 }
203
204 /* ColorMapBrewerSequentialWidget */
205
206 ColorMapBrewerSequentialWidget::ColorMapBrewerSequentialWidget() :
207     _update_lock(false)
208 {
209     QGridLayout *layout = new QGridLayout;
210
211     QLabel* n_label = new QLabel("Colors:");
212     layout->addWidget(n_label, 1, 0);
213     _n_spinbox = new QSpinBox();
214     _n_spinbox->setRange(2, 1024);
215     _n_spinbox->setSingleStep(1);
216     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
217
218     QLabel* hue_label = new QLabel("Hue:");
219     layout->addWidget(hue_label, 2, 0);
220     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
221     layout->addWidget(_hue_changer->slider, 2, 1, 1, 2);
222     layout->addWidget(_hue_changer->spinbox, 2, 3);
223
224     QLabel* divergence_label = new QLabel("Divergence:");
225     layout->addWidget(divergence_label, 3, 0);
226     ColorMapCombinedSliderSpinBox* divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
227     layout->addWidget(divergence_changer->slider, 3, 1, 1, 2);
228     layout->addWidget(divergence_changer->spinbox, 3, 3);
229     hideWidgetButPreserveSize(divergence_label);
230     hideWidgetButPreserveSize(divergence_changer->slider);
231     hideWidgetButPreserveSize(divergence_changer->spinbox);
232
233     QLabel* warmth_label = new QLabel("Warmth:");
234     layout->addWidget(warmth_label, 4, 0);
235     _warmth_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
236     layout->addWidget(_warmth_changer->slider, 4, 1, 1, 2);
237     layout->addWidget(_warmth_changer->spinbox, 4, 3);
238
239     QLabel* contrast_label = new QLabel("Contrast:");
240     layout->addWidget(contrast_label, 5, 0);
241     _contrast_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
242     layout->addWidget(_contrast_changer->slider, 5, 1, 1, 2);
243     layout->addWidget(_contrast_changer->spinbox, 5, 3);
244
245     QLabel* saturation_label = new QLabel("Saturation:");
246     layout->addWidget(saturation_label, 6, 0);
247     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
248     layout->addWidget(_saturation_changer->slider, 6, 1, 1, 2);
249     layout->addWidget(_saturation_changer->spinbox, 6, 3);
250
251     QLabel* brightness_label = new QLabel("Brightness:");
252     layout->addWidget(brightness_label, 7, 0);
253     _brightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
254     layout->addWidget(_brightness_changer->slider, 7, 1, 1, 2);
255     layout->addWidget(_brightness_changer->spinbox, 7, 3);
256
257     layout->setColumnStretch(1, 1);
258     layout->addItem(new QSpacerItem(0, 0), 8, 0, 1, 4);
259     layout->setRowStretch(8, 1);
260     setLayout(layout);
261
262     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
263     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
264     connect(_warmth_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
265     connect(_contrast_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
266     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
267     connect(_brightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
268     reset();
269 }
270
271 ColorMapBrewerSequentialWidget::~ColorMapBrewerSequentialWidget()
272 {
273 }
274
275 void ColorMapBrewerSequentialWidget::reset()
276 {
277     _update_lock = true;
278     _n_spinbox->setValue(256);
279     _hue_changer->setValue(qRadiansToDegrees(ColorMap::BrewerSequentialDefaultHue));
280     _warmth_changer->setValue(ColorMap::BrewerSequentialDefaultWarmth);
281     _contrast_changer->setValue(ColorMap::BrewerSequentialDefaultContrast);
282     _saturation_changer->setValue(ColorMap::BrewerSequentialDefaultSaturation);
283     _brightness_changer->setValue(ColorMap::BrewerSequentialDefaultBrightness);
284     _update_lock = false;
285     update();
286 }
287
288 QVector<QColor> ColorMapBrewerSequentialWidget::colorMap(int* clipped) const
289 {
290     int n;
291     float h, c, s, b, w;
292     parameters(n, h, c, s, b, w);
293     QVector<unsigned char> colormap(3 * n);
294     int cl = ColorMap::BrewerSequential(n, colormap.data(), h, c, s, b, w);
295     if (clipped)
296         *clipped = cl;
297     return toQColor(colormap);
298 }
299
300 QString ColorMapBrewerSequentialWidget::reference() const
301 {
302     return brewerlike_reference;
303 }
304
305 void ColorMapBrewerSequentialWidget::parameters(int& n, float& hue,
306         float& contrast, float& saturation, float& brightness, float& warmth) const
307 {
308     n = _n_spinbox->value();
309     hue = qDegreesToRadians(_hue_changer->value());
310     contrast = _contrast_changer->value();
311     saturation = _saturation_changer->value();
312     brightness = _brightness_changer->value();
313     warmth = _warmth_changer->value();
314 }
315
316 void ColorMapBrewerSequentialWidget::update()
317 {
318     if (!_update_lock)
319         emit colorMapChanged();
320 }
321
322 /* ColorMapBrewerDivergingWidget */
323
324 ColorMapBrewerDivergingWidget::ColorMapBrewerDivergingWidget() :
325     _update_lock(false)
326 {
327     QGridLayout *layout = new QGridLayout;
328
329     QLabel* n_label = new QLabel("Colors:");
330     layout->addWidget(n_label, 1, 0);
331     _n_spinbox = new QSpinBox();
332     _n_spinbox->setRange(2, 1024);
333     _n_spinbox->setSingleStep(1);
334     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
335
336     QLabel* hue_label = new QLabel("Hue:");
337     layout->addWidget(hue_label, 2, 0);
338     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
339     layout->addWidget(_hue_changer->slider, 2, 1, 1, 2);
340     layout->addWidget(_hue_changer->spinbox, 2, 3);
341
342     QLabel* divergence_label = new QLabel("Divergence:");
343     layout->addWidget(divergence_label, 3, 0);
344     _divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
345     layout->addWidget(_divergence_changer->slider, 3, 1, 1, 2);
346     layout->addWidget(_divergence_changer->spinbox, 3, 3);
347
348     QLabel* warmth_label = new QLabel("Warmth:");
349     layout->addWidget(warmth_label, 4, 0);
350     _warmth_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
351     layout->addWidget(_warmth_changer->slider, 4, 1, 1, 2);
352     layout->addWidget(_warmth_changer->spinbox, 4, 3);
353
354     QLabel* contrast_label = new QLabel("Contrast:");
355     layout->addWidget(contrast_label, 5, 0);
356     _contrast_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
357     layout->addWidget(_contrast_changer->slider, 5, 1, 1, 2);
358     layout->addWidget(_contrast_changer->spinbox, 5, 3);
359
360     QLabel* saturation_label = new QLabel("Saturation:");
361     layout->addWidget(saturation_label, 6, 0);
362     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
363     layout->addWidget(_saturation_changer->slider, 6, 1, 1, 2);
364     layout->addWidget(_saturation_changer->spinbox, 6, 3);
365
366     QLabel* brightness_label = new QLabel("Brightness:");
367     layout->addWidget(brightness_label, 7, 0);
368     _brightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
369     layout->addWidget(_brightness_changer->slider, 7, 1, 1, 2);
370     layout->addWidget(_brightness_changer->spinbox, 7, 3);
371
372     layout->setColumnStretch(1, 1);
373     layout->addItem(new QSpacerItem(0, 0), 8, 0, 1, 4);
374     layout->setRowStretch(8, 1);
375     setLayout(layout);
376
377     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
378     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
379     connect(_divergence_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
380     connect(_warmth_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
381     connect(_contrast_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
382     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
383     connect(_brightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
384     reset();
385 }
386
387 ColorMapBrewerDivergingWidget::~ColorMapBrewerDivergingWidget()
388 {
389 }
390
391 void ColorMapBrewerDivergingWidget::reset()
392 {
393     _update_lock = true;
394     _n_spinbox->setValue(257);
395     _hue_changer->setValue(qRadiansToDegrees(ColorMap::BrewerDivergingDefaultHue));
396     _divergence_changer->setValue(qRadiansToDegrees(ColorMap::BrewerDivergingDefaultDivergence));
397     _warmth_changer->setValue(ColorMap::BrewerDivergingDefaultWarmth);
398     _contrast_changer->setValue(ColorMap::BrewerDivergingDefaultContrast);
399     _saturation_changer->setValue(ColorMap::BrewerDivergingDefaultSaturation);
400     _brightness_changer->setValue(ColorMap::BrewerDivergingDefaultBrightness);
401     _update_lock = false;
402     update();
403 }
404
405 QVector<QColor> ColorMapBrewerDivergingWidget::colorMap(int* clipped) const
406 {
407     int n;
408     float h, d, c, s, b, w;
409     parameters(n, h, d, c, s, b, w);
410     QVector<unsigned char> colormap(3 * n);
411     int cl = ColorMap::BrewerDiverging(n, colormap.data(), h, d, c, s, b, w);
412     if (clipped)
413         *clipped = cl;
414     return toQColor(colormap);
415 }
416
417 QString ColorMapBrewerDivergingWidget::reference() const
418 {
419     return brewerlike_reference;
420 }
421
422 void ColorMapBrewerDivergingWidget::parameters(int& n, float& hue, float& divergence,
423         float& contrast, float& saturation, float& brightness, float& warmth) const
424 {
425     n = _n_spinbox->value();
426     hue = qDegreesToRadians(_hue_changer->value());
427     divergence = qDegreesToRadians(_divergence_changer->value());
428     contrast = _contrast_changer->value();
429     saturation = _saturation_changer->value();
430     brightness = _brightness_changer->value();
431     warmth = _warmth_changer->value();
432 }
433
434 void ColorMapBrewerDivergingWidget::update()
435 {
436     if (!_update_lock)
437         emit colorMapChanged();
438 }
439
440 /* ColorMapBrewerQualitativeWidget */
441
442 ColorMapBrewerQualitativeWidget::ColorMapBrewerQualitativeWidget() :
443     _update_lock(false)
444 {
445     QGridLayout *layout = new QGridLayout;
446
447     QLabel* n_label = new QLabel("Colors:");
448     layout->addWidget(n_label, 1, 0);
449     _n_spinbox = new QSpinBox();
450     _n_spinbox->setRange(2, 1024);
451     _n_spinbox->setSingleStep(1);
452     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
453
454     QLabel* hue_label = new QLabel("Hue:");
455     layout->addWidget(hue_label, 2, 0);
456     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
457     layout->addWidget(_hue_changer->slider, 2, 1, 1, 2);
458     layout->addWidget(_hue_changer->spinbox, 2, 3);
459
460     QLabel* divergence_label = new QLabel("Divergence:");
461     layout->addWidget(divergence_label, 3, 0);
462     _divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
463     layout->addWidget(_divergence_changer->slider, 3, 1, 1, 2);
464     layout->addWidget(_divergence_changer->spinbox, 3, 3);
465
466     QLabel* warmth_label = new QLabel("Warmth:");
467     layout->addWidget(warmth_label, 4, 0);
468     ColorMapCombinedSliderSpinBox* warmth_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
469     layout->addWidget(warmth_changer->slider, 4, 1, 1, 2);
470     layout->addWidget(warmth_changer->spinbox, 4, 3);
471     hideWidgetButPreserveSize(warmth_label);
472     hideWidgetButPreserveSize(warmth_changer->slider);
473     hideWidgetButPreserveSize(warmth_changer->spinbox);
474
475     QLabel* contrast_label = new QLabel("Contrast:");
476     layout->addWidget(contrast_label, 5, 0);
477     _contrast_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
478     layout->addWidget(_contrast_changer->slider, 5, 1, 1, 2);
479     layout->addWidget(_contrast_changer->spinbox, 5, 3);
480
481     QLabel* saturation_label = new QLabel("Saturation:");
482     layout->addWidget(saturation_label, 6, 0);
483     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
484     layout->addWidget(_saturation_changer->slider, 6, 1, 1, 2);
485     layout->addWidget(_saturation_changer->spinbox, 6, 3);
486
487     QLabel* brightness_label = new QLabel("Brightness:");
488     layout->addWidget(brightness_label, 7, 0);
489     _brightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
490     layout->addWidget(_brightness_changer->slider, 7, 1, 1, 2);
491     layout->addWidget(_brightness_changer->spinbox, 7, 3);
492
493     layout->setColumnStretch(1, 1);
494     layout->addItem(new QSpacerItem(0, 0), 8, 0, 1, 4);
495     layout->setRowStretch(8, 1);
496     setLayout(layout);
497
498     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
499     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
500     connect(_divergence_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
501     connect(_contrast_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
502     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
503     connect(_brightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
504     reset();
505 }
506
507 ColorMapBrewerQualitativeWidget::~ColorMapBrewerQualitativeWidget()
508 {
509 }
510
511 void ColorMapBrewerQualitativeWidget::reset()
512 {
513     _update_lock = true;
514     _n_spinbox->setValue(9);
515     _hue_changer->setValue(qRadiansToDegrees(ColorMap::BrewerQualitativeDefaultHue));
516     _divergence_changer->setValue(qRadiansToDegrees(ColorMap::BrewerQualitativeDefaultDivergence));
517     _contrast_changer->setValue(ColorMap::BrewerQualitativeDefaultContrast);
518     _saturation_changer->setValue(ColorMap::BrewerQualitativeDefaultSaturation);
519     _brightness_changer->setValue(ColorMap::BrewerQualitativeDefaultBrightness);
520     _update_lock = false;
521     update();
522 }
523
524 QVector<QColor> ColorMapBrewerQualitativeWidget::colorMap(int* clipped) const
525 {
526     int n;
527     float h, d, c, s, b;
528     parameters(n, h, d, c, s, b);
529     QVector<unsigned char> colormap(3 * n);
530     int cl = ColorMap::BrewerQualitative(n, colormap.data(), h, d, c, s, b);
531     if (clipped)
532         *clipped = cl;
533     return toQColor(colormap);
534 }
535
536 QString ColorMapBrewerQualitativeWidget::reference() const
537 {
538     return brewerlike_reference;
539 }
540
541 void ColorMapBrewerQualitativeWidget::parameters(int& n, float& hue, float& divergence,
542         float& contrast, float& saturation, float& brightness) const
543 {
544     n = _n_spinbox->value();
545     hue = qDegreesToRadians(_hue_changer->value());
546     divergence = qDegreesToRadians(_divergence_changer->value());
547     contrast = _contrast_changer->value();
548     saturation = _saturation_changer->value();
549     brightness = _brightness_changer->value();
550 }
551
552 void ColorMapBrewerQualitativeWidget::update()
553 {
554     if (!_update_lock)
555         emit colorMapChanged();
556 }
557
558 /* ColorMapPLSequentialLightnessWidget */
559
560 ColorMapPLSequentialLightnessWidget::ColorMapPLSequentialLightnessWidget() :
561     _update_lock(false)
562 {
563     QGridLayout *layout = new QGridLayout;
564
565     QLabel* n_label = new QLabel("Colors:");
566     layout->addWidget(n_label, 1, 0);
567     _n_spinbox = new QSpinBox();
568     _n_spinbox->setRange(2, 1024);
569     _n_spinbox->setSingleStep(1);
570     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
571
572     QLabel* saturation_label = new QLabel("Saturation:");
573     layout->addWidget(saturation_label, 2, 0);
574     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
575     layout->addWidget(_saturation_changer->slider, 2, 1, 1, 2);
576     layout->addWidget(_saturation_changer->spinbox, 2, 3);
577
578     QLabel* hue_label = new QLabel("Hue:");
579     layout->addWidget(hue_label, 3, 0);
580     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
581     layout->addWidget(_hue_changer->slider, 3, 1, 1, 2);
582     layout->addWidget(_hue_changer->spinbox, 3, 3);
583
584     layout->setColumnStretch(1, 1);
585     layout->addItem(new QSpacerItem(0, 0), 4, 0, 1, 4);
586     layout->setRowStretch(4, 1);
587     setLayout(layout);
588
589     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
590     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
591     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
592     reset();
593 }
594
595 ColorMapPLSequentialLightnessWidget::~ColorMapPLSequentialLightnessWidget()
596 {
597 }
598
599 void ColorMapPLSequentialLightnessWidget::reset()
600 {
601     _update_lock = true;
602     _n_spinbox->setValue(256);
603     _saturation_changer->setValue(ColorMap::PLSequentialLightnessDefaultSaturation);
604     _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLSequentialLightnessDefaultHue));
605     _update_lock = false;
606     update();
607 }
608
609 QVector<QColor> ColorMapPLSequentialLightnessWidget::colorMap(int* clipped) const
610 {
611     int n;
612     float s, h;
613     parameters(n, s, h);
614     QVector<unsigned char> colormap(3 * n);
615     int cl = ColorMap::PLSequentialLightness(n, colormap.data(), s, h);
616     if (clipped)
617         *clipped = cl;
618     return toQColor(colormap);
619 }
620
621 QString ColorMapPLSequentialLightnessWidget::reference() const
622 {
623     return plseq_lightness_reference;
624 }
625
626 void ColorMapPLSequentialLightnessWidget::parameters(int& n, float& saturation, float& hue) const
627 {
628     n = _n_spinbox->value();
629     saturation = _saturation_changer->value();
630     hue = qDegreesToRadians(_hue_changer->value());
631 }
632
633 void ColorMapPLSequentialLightnessWidget::update()
634 {
635     if (!_update_lock)
636         emit colorMapChanged();
637 }
638
639 /* ColorMapPLSequentialSaturationWidget */
640
641 ColorMapPLSequentialSaturationWidget::ColorMapPLSequentialSaturationWidget() :
642     _update_lock(false)
643 {
644     QGridLayout *layout = new QGridLayout;
645
646     QLabel* n_label = new QLabel("Colors:");
647     layout->addWidget(n_label, 1, 0);
648     _n_spinbox = new QSpinBox();
649     _n_spinbox->setRange(2, 1024);
650     _n_spinbox->setSingleStep(1);
651     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
652
653     QLabel* lightness_label = new QLabel("Lightness:");
654     layout->addWidget(lightness_label, 2, 0);
655     _lightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
656     layout->addWidget(_lightness_changer->slider, 2, 1, 1, 2);
657     layout->addWidget(_lightness_changer->spinbox, 2, 3);
658
659     QLabel* saturation_label = new QLabel("Saturation:");
660     layout->addWidget(saturation_label, 3, 0);
661     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
662     layout->addWidget(_saturation_changer->slider, 3, 1, 1, 2);
663     layout->addWidget(_saturation_changer->spinbox, 3, 3);
664
665     QLabel* hue_label = new QLabel("Hue:");
666     layout->addWidget(hue_label, 4, 0);
667     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
668     layout->addWidget(_hue_changer->slider, 4, 1, 1, 2);
669     layout->addWidget(_hue_changer->spinbox, 4, 3);
670
671     layout->setColumnStretch(1, 1);
672     layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
673     layout->setRowStretch(5, 1);
674     setLayout(layout);
675
676     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
677     connect(_lightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
678     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
679     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
680     reset();
681 }
682
683 ColorMapPLSequentialSaturationWidget::~ColorMapPLSequentialSaturationWidget()
684 {
685 }
686
687 void ColorMapPLSequentialSaturationWidget::reset()
688 {
689     _update_lock = true;
690     _n_spinbox->setValue(256);
691     _lightness_changer->setValue(ColorMap::PLSequentialSaturationDefaultLightness);
692     _saturation_changer->setValue(ColorMap::PLSequentialSaturationDefaultSaturation);
693     _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLSequentialSaturationDefaultHue));
694     _update_lock = false;
695     update();
696 }
697
698 QVector<QColor> ColorMapPLSequentialSaturationWidget::colorMap(int* clipped) const
699 {
700     int n;
701     float l, s, h;
702     parameters(n, l, s, h);
703     QVector<unsigned char> colormap(3 * n);
704     int cl = ColorMap::PLSequentialSaturation(n, colormap.data(), l, s, h);
705     if (clipped)
706         *clipped = cl;
707     return toQColor(colormap);
708 }
709
710 QString ColorMapPLSequentialSaturationWidget::reference() const
711 {
712     return plseq_saturation_reference;
713 }
714
715 void ColorMapPLSequentialSaturationWidget::parameters(int& n, float& lightness, float& saturation, float& hue) const
716 {
717     n = _n_spinbox->value();
718     lightness = _lightness_changer->value();
719     saturation = _saturation_changer->value();
720     hue = qDegreesToRadians(_hue_changer->value());
721 }
722
723 void ColorMapPLSequentialSaturationWidget::update()
724 {
725     if (!_update_lock)
726         emit colorMapChanged();
727 }
728
729 /* ColorMapPLSequentialRainbowWidget */
730
731 ColorMapPLSequentialRainbowWidget::ColorMapPLSequentialRainbowWidget() :
732     _update_lock(false)
733 {
734     QGridLayout *layout = new QGridLayout;
735
736     QLabel* n_label = new QLabel("Colors:");
737     layout->addWidget(n_label, 1, 0);
738     _n_spinbox = new QSpinBox();
739     _n_spinbox->setRange(2, 1024);
740     _n_spinbox->setSingleStep(1);
741     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
742
743     QLabel* hue_label = new QLabel("Hue:");
744     layout->addWidget(hue_label, 2, 0);
745     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
746     layout->addWidget(_hue_changer->slider, 2, 1, 1, 2);
747     layout->addWidget(_hue_changer->spinbox, 2, 3);
748
749     QLabel* rotations_label = new QLabel("Rotations:");
750     layout->addWidget(rotations_label, 3, 0);
751     _rotations_changer = new ColorMapCombinedSliderSpinBox(-5.0f, +5.0f, 0.1f);
752     layout->addWidget(_rotations_changer->slider, 3, 1, 1, 2);
753     layout->addWidget(_rotations_changer->spinbox, 3, 3);
754
755     QLabel* saturation_label = new QLabel("Saturation:");
756     layout->addWidget(saturation_label, 4, 0);
757     _saturation_changer = new ColorMapCombinedSliderSpinBox(0.0f, 5.0f, 0.1f);
758     layout->addWidget(_saturation_changer->slider, 4, 1, 1, 2);
759     layout->addWidget(_saturation_changer->spinbox, 4, 3);
760
761     layout->setColumnStretch(1, 1);
762     layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
763     layout->setRowStretch(5, 1);
764     setLayout(layout);
765
766     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
767     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
768     connect(_rotations_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
769     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
770     reset();
771 }
772
773 ColorMapPLSequentialRainbowWidget::~ColorMapPLSequentialRainbowWidget()
774 {
775 }
776
777 void ColorMapPLSequentialRainbowWidget::reset()
778 {
779     _update_lock = true;
780     _n_spinbox->setValue(256);
781     _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLSequentialRainbowDefaultHue));
782     _rotations_changer->setValue(ColorMap::PLSequentialRainbowDefaultRotations);
783     _saturation_changer->setValue(ColorMap::PLSequentialRainbowDefaultSaturation);
784     _update_lock = false;
785     update();
786 }
787
788 QVector<QColor> ColorMapPLSequentialRainbowWidget::colorMap(int* clipped) const
789 {
790     int n;
791     float h, r, s;
792     parameters(n, h, r, s);
793     QVector<unsigned char> colormap(3 * n);
794     int cl = ColorMap::PLSequentialRainbow(n, colormap.data(), h, r, s);
795     if (clipped)
796         *clipped = cl;
797     return toQColor(colormap);
798 }
799
800 QString ColorMapPLSequentialRainbowWidget::reference() const
801 {
802     return plseq_rainbow_reference;
803 }
804
805 void ColorMapPLSequentialRainbowWidget::parameters(int& n, float& hue,
806         float& rotations, float& saturation) const
807 {
808     n = _n_spinbox->value();
809     hue = qDegreesToRadians(_hue_changer->value());
810     rotations = _rotations_changer->value();
811     saturation = _saturation_changer->value();
812 }
813
814 void ColorMapPLSequentialRainbowWidget::update()
815 {
816     if (!_update_lock)
817         emit colorMapChanged();
818 }
819
820 /* ColorMapPLSequentialBlackBodyWidget */
821
822 ColorMapPLSequentialBlackBodyWidget::ColorMapPLSequentialBlackBodyWidget() :
823     _update_lock(false)
824 {
825     QGridLayout *layout = new QGridLayout;
826
827     QLabel* n_label = new QLabel("Colors:");
828     layout->addWidget(n_label, 1, 0);
829     _n_spinbox = new QSpinBox();
830     _n_spinbox->setRange(2, 10240);
831     _n_spinbox->setSingleStep(1);
832     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
833
834     QLabel* temperature_label = new QLabel("Temperature (K):");
835     layout->addWidget(temperature_label, 2, 0);
836     _temperature_changer = new ColorMapCombinedSliderSpinBox(250.0f, 20000.0f, 100.0f);
837     layout->addWidget(_temperature_changer->slider, 2, 1, 1, 2);
838     layout->addWidget(_temperature_changer->spinbox, 2, 3);
839
840     QLabel* range_label = new QLabel("Range (K):");
841     layout->addWidget(range_label, 3, 0);
842     _range_changer = new ColorMapCombinedSliderSpinBox(0.0f, 20000.0f, 100.0f);
843     layout->addWidget(_range_changer->slider, 3, 1, 1, 2);
844     layout->addWidget(_range_changer->spinbox, 3, 3);
845
846     QLabel* saturation_label = new QLabel("Saturation:");
847     layout->addWidget(saturation_label, 4, 0);
848     _saturation_changer = new ColorMapCombinedSliderSpinBox(0.0f, 5.0f, 0.1f);
849     layout->addWidget(_saturation_changer->slider, 4, 1, 1, 2);
850     layout->addWidget(_saturation_changer->spinbox, 4, 3);
851
852     layout->setColumnStretch(1, 1);
853     layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
854     layout->setRowStretch(5, 1);
855     setLayout(layout);
856
857     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
858     connect(_temperature_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
859     connect(_range_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
860     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
861     reset();
862 }
863
864 ColorMapPLSequentialBlackBodyWidget::~ColorMapPLSequentialBlackBodyWidget()
865 {
866 }
867
868 void ColorMapPLSequentialBlackBodyWidget::reset()
869 {
870     _update_lock = true;
871     _n_spinbox->setValue(256);
872     _temperature_changer->setValue(ColorMap::PLSequentialBlackBodyDefaultTemperature);
873     _range_changer->setValue(ColorMap::PLSequentialBlackBodyDefaultRange);
874     _saturation_changer->setValue(ColorMap::PLSequentialBlackBodyDefaultSaturation);
875     _update_lock = false;
876     update();
877 }
878
879 QVector<QColor> ColorMapPLSequentialBlackBodyWidget::colorMap(int* clipped) const
880 {
881     int n;
882     float t, r, s;
883     parameters(n, t, r, s);
884     QVector<unsigned char> colormap(3 * n);
885     int cl = ColorMap::PLSequentialBlackBody(n, colormap.data(), t, r, s);
886     if (clipped)
887         *clipped = cl;
888     return toQColor(colormap);
889 }
890
891 QString ColorMapPLSequentialBlackBodyWidget::reference() const
892 {
893     return plseq_blackbody_reference;
894 }
895
896 void ColorMapPLSequentialBlackBodyWidget::parameters(int& n, float& temperature, float& range, float& saturation) const
897 {
898     n = _n_spinbox->value();
899     temperature = _temperature_changer->value();
900     range = _range_changer->value();
901     saturation = _saturation_changer->value();
902 }
903
904 void ColorMapPLSequentialBlackBodyWidget::update()
905 {
906     if (!_update_lock)
907         emit colorMapChanged();
908 }
909
910 /* ColorMapPLDivergingLightnessWidget */
911
912 ColorMapPLDivergingLightnessWidget::ColorMapPLDivergingLightnessWidget() :
913     _update_lock(false)
914 {
915     QGridLayout *layout = new QGridLayout;
916
917     QLabel* n_label = new QLabel("Colors:");
918     layout->addWidget(n_label, 1, 0);
919     _n_spinbox = new QSpinBox();
920     _n_spinbox->setRange(2, 1024);
921     _n_spinbox->setSingleStep(1);
922     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
923
924     QLabel* lightness_label = new QLabel("Lightness:");
925     layout->addWidget(lightness_label, 2, 0);
926     _lightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
927     layout->addWidget(_lightness_changer->slider, 2, 1, 1, 2);
928     layout->addWidget(_lightness_changer->spinbox, 2, 3);
929
930     QLabel* saturation_label = new QLabel("Saturation:");
931     layout->addWidget(saturation_label, 3, 0);
932     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
933     layout->addWidget(_saturation_changer->slider, 3, 1, 1, 2);
934     layout->addWidget(_saturation_changer->spinbox, 3, 3);
935
936     QLabel* hue_label = new QLabel("Hue:");
937     layout->addWidget(hue_label, 4, 0);
938     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
939     layout->addWidget(_hue_changer->slider, 4, 1, 1, 2);
940     layout->addWidget(_hue_changer->spinbox, 4, 3);
941
942     QLabel* divergence_label = new QLabel("Divergence:");
943     layout->addWidget(divergence_label, 5, 0);
944     _divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
945     layout->addWidget(_divergence_changer->slider, 5, 1, 1, 2);
946     layout->addWidget(_divergence_changer->spinbox, 5, 3);
947
948     layout->setColumnStretch(1, 1);
949     layout->addItem(new QSpacerItem(0, 0), 6, 0, 1, 4);
950     layout->setRowStretch(6, 1);
951     setLayout(layout);
952
953     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
954     connect(_lightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
955     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
956     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
957     connect(_divergence_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
958     reset();
959 }
960
961 ColorMapPLDivergingLightnessWidget::~ColorMapPLDivergingLightnessWidget()
962 {
963 }
964
965 void ColorMapPLDivergingLightnessWidget::reset()
966 {
967     _update_lock = true;
968     _n_spinbox->setValue(257);
969     _lightness_changer->setValue(ColorMap::PLDivergingLightnessDefaultLightness);
970     _saturation_changer->setValue(ColorMap::PLDivergingLightnessDefaultSaturation);
971     _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLDivergingLightnessDefaultHue));
972     _divergence_changer->setValue(qRadiansToDegrees(ColorMap::PLDivergingLightnessDefaultDivergence));
973     _update_lock = false;
974     update();
975 }
976
977 QVector<QColor> ColorMapPLDivergingLightnessWidget::colorMap(int* clipped) const
978 {
979     int n;
980     float l, s, h, d;
981     parameters(n, l, s, h, d);
982     QVector<unsigned char> colormap(3 * n);
983     int cl = ColorMap::PLDivergingLightness(n, colormap.data(), l, s, h, d);
984     if (clipped)
985         *clipped = cl;
986     return toQColor(colormap);
987 }
988
989 QString ColorMapPLDivergingLightnessWidget::reference() const
990 {
991     return pldiv_lightness_reference;
992 }
993
994 void ColorMapPLDivergingLightnessWidget::parameters(int& n, float& lightness, float& saturation, float& hue, float& divergence) const
995 {
996     n = _n_spinbox->value();
997     lightness = _lightness_changer->value();
998     saturation = _saturation_changer->value();
999     hue = qDegreesToRadians(_hue_changer->value());
1000     divergence = qDegreesToRadians(_divergence_changer->value());
1001 }
1002
1003 void ColorMapPLDivergingLightnessWidget::update()
1004 {
1005     if (!_update_lock)
1006         emit colorMapChanged();
1007 }
1008
1009 /* ColorMapPLDivergingSaturationWidget */
1010
1011 ColorMapPLDivergingSaturationWidget::ColorMapPLDivergingSaturationWidget() :
1012     _update_lock(false)
1013 {
1014     QGridLayout *layout = new QGridLayout;
1015
1016     QLabel* n_label = new QLabel("Colors:");
1017     layout->addWidget(n_label, 1, 0);
1018     _n_spinbox = new QSpinBox();
1019     _n_spinbox->setRange(2, 1024);
1020     _n_spinbox->setSingleStep(1);
1021     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
1022
1023     QLabel* lightness_label = new QLabel("Lightness:");
1024     layout->addWidget(lightness_label, 2, 0);
1025     _lightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
1026     layout->addWidget(_lightness_changer->slider, 2, 1, 1, 2);
1027     layout->addWidget(_lightness_changer->spinbox, 2, 3);
1028
1029     QLabel* saturation_label = new QLabel("Saturation:");
1030     layout->addWidget(saturation_label, 3, 0);
1031     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
1032     layout->addWidget(_saturation_changer->slider, 3, 1, 1, 2);
1033     layout->addWidget(_saturation_changer->spinbox, 3, 3);
1034
1035     QLabel* hue_label = new QLabel("Hue:");
1036     layout->addWidget(hue_label, 4, 0);
1037     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
1038     layout->addWidget(_hue_changer->slider, 4, 1, 1, 2);
1039     layout->addWidget(_hue_changer->spinbox, 4, 3);
1040
1041     QLabel* divergence_label = new QLabel("Divergence:");
1042     layout->addWidget(divergence_label, 5, 0);
1043     _divergence_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
1044     layout->addWidget(_divergence_changer->slider, 5, 1, 1, 2);
1045     layout->addWidget(_divergence_changer->spinbox, 5, 3);
1046
1047     layout->setColumnStretch(1, 1);
1048     layout->addItem(new QSpacerItem(0, 0), 6, 0, 1, 4);
1049     layout->setRowStretch(6, 1);
1050     setLayout(layout);
1051
1052     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
1053     connect(_lightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1054     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1055     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1056     connect(_divergence_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1057     reset();
1058 }
1059
1060 ColorMapPLDivergingSaturationWidget::~ColorMapPLDivergingSaturationWidget()
1061 {
1062 }
1063
1064 void ColorMapPLDivergingSaturationWidget::reset()
1065 {
1066     _update_lock = true;
1067     _n_spinbox->setValue(257);
1068     _lightness_changer->setValue(ColorMap::PLDivergingSaturationDefaultLightness);
1069     _saturation_changer->setValue(ColorMap::PLDivergingSaturationDefaultSaturation);
1070     _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLDivergingSaturationDefaultHue));
1071     _divergence_changer->setValue(qRadiansToDegrees(ColorMap::PLDivergingSaturationDefaultDivergence));
1072     _update_lock = false;
1073     update();
1074 }
1075
1076 QVector<QColor> ColorMapPLDivergingSaturationWidget::colorMap(int* clipped) const
1077 {
1078     int n;
1079     float l, s, h, d;
1080     parameters(n, l, s, h, d);
1081     QVector<unsigned char> colormap(3 * n);
1082     int cl = ColorMap::PLDivergingSaturation(n, colormap.data(), l, s, h, d);
1083     if (clipped)
1084         *clipped = cl;
1085     return toQColor(colormap);
1086 }
1087
1088 QString ColorMapPLDivergingSaturationWidget::reference() const
1089 {
1090     return pldiv_saturation_reference;
1091 }
1092
1093 void ColorMapPLDivergingSaturationWidget::parameters(int& n, float& lightness, float& saturation, float& hue, float& divergence) const
1094 {
1095     n = _n_spinbox->value();
1096     lightness = _lightness_changer->value();
1097     saturation = _saturation_changer->value();
1098     hue = qDegreesToRadians(_hue_changer->value());
1099     divergence = qDegreesToRadians(_divergence_changer->value());
1100 }
1101
1102 void ColorMapPLDivergingSaturationWidget::update()
1103 {
1104     if (!_update_lock)
1105         emit colorMapChanged();
1106 }
1107
1108 /* ColorMapPLQualitativeHueWidget */
1109
1110 ColorMapPLQualitativeHueWidget::ColorMapPLQualitativeHueWidget() :
1111     _update_lock(false)
1112 {
1113     QGridLayout *layout = new QGridLayout;
1114
1115     QLabel* n_label = new QLabel("Colors:");
1116     layout->addWidget(n_label, 1, 0);
1117     _n_spinbox = new QSpinBox();
1118     _n_spinbox->setRange(2, 1024);
1119     _n_spinbox->setSingleStep(1);
1120     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
1121
1122     QLabel* lightness_label = new QLabel("Lightness:");
1123     layout->addWidget(lightness_label, 2, 0);
1124     _lightness_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
1125     layout->addWidget(_lightness_changer->slider, 2, 1, 1, 2);
1126     layout->addWidget(_lightness_changer->spinbox, 2, 3);
1127
1128     QLabel* saturation_label = new QLabel("Saturation:");
1129     layout->addWidget(saturation_label, 3, 0);
1130     _saturation_changer = new ColorMapCombinedSliderSpinBox(0, 1, 0.01f);
1131     layout->addWidget(_saturation_changer->slider, 3, 1, 1, 2);
1132     layout->addWidget(_saturation_changer->spinbox, 3, 3);
1133
1134     QLabel* hue_label = new QLabel("Hue:");
1135     layout->addWidget(hue_label, 4, 0);
1136     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 360, 1);
1137     layout->addWidget(_hue_changer->slider, 4, 1, 1, 2);
1138     layout->addWidget(_hue_changer->spinbox, 4, 3);
1139
1140     layout->setColumnStretch(1, 1);
1141     layout->addItem(new QSpacerItem(0, 0), 5, 0, 1, 4);
1142     layout->setRowStretch(5, 1);
1143     setLayout(layout);
1144
1145     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
1146     connect(_lightness_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1147     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1148     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1149     reset();
1150 }
1151
1152 ColorMapPLQualitativeHueWidget::~ColorMapPLQualitativeHueWidget()
1153 {
1154 }
1155
1156 void ColorMapPLQualitativeHueWidget::reset()
1157 {
1158     _update_lock = true;
1159     _n_spinbox->setValue(9);
1160     _lightness_changer->setValue(ColorMap::PLQualitativeHueDefaultLightness);
1161     _saturation_changer->setValue(ColorMap::PLQualitativeHueDefaultSaturation);
1162     _hue_changer->setValue(qRadiansToDegrees(ColorMap::PLQualitativeHueDefaultHue));
1163     _update_lock = false;
1164     update();
1165 }
1166
1167 QVector<QColor> ColorMapPLQualitativeHueWidget::colorMap(int* clipped) const
1168 {
1169     int n;
1170     float l, s, h;
1171     parameters(n, l, s, h);
1172     QVector<unsigned char> colormap(3 * n);
1173     int cl = ColorMap::PLQualitativeHue(n, colormap.data(), l, s, h);
1174     if (clipped)
1175         *clipped = cl;
1176     return toQColor(colormap);
1177 }
1178
1179 QString ColorMapPLQualitativeHueWidget::reference() const
1180 {
1181     return plqual_hue_reference;
1182 }
1183
1184 void ColorMapPLQualitativeHueWidget::parameters(int& n, float& lightness, float& saturation, float& hue) const
1185 {
1186     n = _n_spinbox->value();
1187     lightness = _lightness_changer->value();
1188     saturation = _saturation_changer->value();
1189     hue = qDegreesToRadians(_hue_changer->value());
1190 }
1191
1192 void ColorMapPLQualitativeHueWidget::update()
1193 {
1194     if (!_update_lock)
1195         emit colorMapChanged();
1196 }
1197
1198 /* ColorMapCubeHelixWidget */
1199
1200 ColorMapCubeHelixWidget::ColorMapCubeHelixWidget() :
1201     _update_lock(false)
1202 {
1203     QGridLayout *layout = new QGridLayout;
1204
1205     QLabel* n_label = new QLabel("Colors:");
1206     layout->addWidget(n_label, 1, 0);
1207     _n_spinbox = new QSpinBox();
1208     _n_spinbox->setRange(2, 1024);
1209     _n_spinbox->setSingleStep(1);
1210     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
1211
1212     QLabel* hue_label = new QLabel("Hue:");
1213     layout->addWidget(hue_label, 2, 0);
1214     _hue_changer = new ColorMapCombinedSliderSpinBox(0, 180, 1);
1215     layout->addWidget(_hue_changer->slider, 2, 1, 1, 2);
1216     layout->addWidget(_hue_changer->spinbox, 2, 3);
1217
1218     QLabel* rotations_label = new QLabel("Rotations:");
1219     layout->addWidget(rotations_label, 3, 0);
1220     _rotations_changer = new ColorMapCombinedSliderSpinBox(-5.0f, +5.0f, 0.1f);
1221     layout->addWidget(_rotations_changer->slider, 3, 1, 1, 2);
1222     layout->addWidget(_rotations_changer->spinbox, 3, 3);
1223
1224     QLabel* saturation_label = new QLabel("Saturation:");
1225     layout->addWidget(saturation_label, 4, 0);
1226     _saturation_changer = new ColorMapCombinedSliderSpinBox(0.0f, 2.0f, 0.1f);
1227     layout->addWidget(_saturation_changer->slider, 4, 1, 1, 2);
1228     layout->addWidget(_saturation_changer->spinbox, 4, 3);
1229
1230     QLabel* gamma_label = new QLabel("Gamma:");
1231     layout->addWidget(gamma_label, 5, 0);
1232     _gamma_changer = new ColorMapCombinedSliderSpinBox(0.3f, 3.0f, 0.1f);
1233     layout->addWidget(_gamma_changer->slider, 5, 1, 1, 2);
1234     layout->addWidget(_gamma_changer->spinbox, 5, 3);
1235
1236     layout->setColumnStretch(1, 1);
1237     layout->addItem(new QSpacerItem(0, 0), 6, 0, 1, 4);
1238     layout->setRowStretch(6, 1);
1239     setLayout(layout);
1240
1241     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
1242     connect(_hue_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1243     connect(_rotations_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1244     connect(_saturation_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1245     connect(_gamma_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1246     reset();
1247 }
1248
1249 ColorMapCubeHelixWidget::~ColorMapCubeHelixWidget()
1250 {
1251 }
1252
1253 void ColorMapCubeHelixWidget::reset()
1254 {
1255     _update_lock = true;
1256     _n_spinbox->setValue(256);
1257     _hue_changer->setValue(qRadiansToDegrees(ColorMap::CubeHelixDefaultHue));
1258     _rotations_changer->setValue(ColorMap::CubeHelixDefaultRotations);
1259     _saturation_changer->setValue(ColorMap::CubeHelixDefaultSaturation);
1260     _gamma_changer->setValue(ColorMap::CubeHelixDefaultGamma);
1261     _update_lock = false;
1262     update();
1263 }
1264
1265 QVector<QColor> ColorMapCubeHelixWidget::colorMap(int* clipped) const
1266 {
1267     int n;
1268     float h, r, s, g;
1269     parameters(n, h, r, s, g);
1270     QVector<unsigned char> colormap(3 * n);
1271     int cl = ColorMap::CubeHelix(n, colormap.data(), h, r, s, g);
1272     if (clipped)
1273         *clipped = cl;
1274     return toQColor(colormap);
1275 }
1276
1277 QString ColorMapCubeHelixWidget::reference() const
1278 {
1279     return cubehelix_reference;
1280 }
1281
1282 void ColorMapCubeHelixWidget::parameters(int& n, float& hue,
1283         float& rotations, float& saturation, float& gamma) const
1284 {
1285     n = _n_spinbox->value();
1286     hue = qDegreesToRadians(_hue_changer->value());
1287     rotations = _rotations_changer->value();
1288     saturation = _saturation_changer->value();
1289     gamma = _gamma_changer->value();
1290 }
1291
1292 void ColorMapCubeHelixWidget::update()
1293 {
1294     if (!_update_lock)
1295         emit colorMapChanged();
1296 }
1297
1298 /* ColorMapMorelandWidget */
1299
1300 ColorMapMorelandWidget::ColorMapMorelandWidget() :
1301     _update_lock(false)
1302 {
1303     QGridLayout *layout = new QGridLayout;
1304
1305     QLabel* n_label = new QLabel("Colors:");
1306     layout->addWidget(n_label, 1, 0);
1307     _n_spinbox = new QSpinBox();
1308     _n_spinbox->setRange(2, 1024);
1309     _n_spinbox->setSingleStep(1);
1310     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
1311
1312     QLabel* color0_label = new QLabel("First color:");
1313     layout->addWidget(color0_label, 2, 0);
1314     _color0_button = new QPushButton;
1315     layout->addWidget(_color0_button, 2, 1, 1, 3);
1316
1317     QLabel* color1_label = new QLabel("Last color:");
1318     layout->addWidget(color1_label, 3, 0);
1319     _color1_button = new QPushButton;
1320     layout->addWidget(_color1_button, 3, 1, 1, 3);
1321
1322     layout->setColumnStretch(1, 1);
1323     layout->addItem(new QSpacerItem(0, 0), 4, 0, 1, 4);
1324     layout->setRowStretch(4, 1);
1325     setLayout(layout);
1326
1327     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
1328     connect(_color0_button, SIGNAL(clicked(bool)), this, SLOT(chooseColor0()));
1329     connect(_color1_button, SIGNAL(clicked(bool)), this, SLOT(chooseColor1()));
1330     reset();
1331 }
1332
1333 ColorMapMorelandWidget::~ColorMapMorelandWidget()
1334 {
1335 }
1336
1337 static void setButtonColor(QPushButton* button, const QColor& color)
1338 {
1339     QPixmap pixmap(button->iconSize());
1340     pixmap.fill(color);
1341     button->setIcon(QIcon(pixmap));
1342 }
1343
1344 static QColor getButtonColor(QPushButton* button)
1345 {
1346     return button->icon().pixmap(1, 1).toImage().pixel(0, 0);
1347 }
1348
1349 void ColorMapMorelandWidget::chooseColor0()
1350 {
1351     QColor c = QColorDialog::getColor(getButtonColor(_color0_button), this);
1352     if (c.isValid()) {
1353         setButtonColor(_color0_button, c);
1354         update();
1355     }
1356 }
1357
1358 void ColorMapMorelandWidget::chooseColor1()
1359 {
1360     QColor c = QColorDialog::getColor(getButtonColor(_color1_button), this);
1361     if (c.isValid()) {
1362         setButtonColor(_color1_button, c);
1363         update();
1364     }
1365 }
1366
1367 void ColorMapMorelandWidget::reset()
1368 {
1369     _update_lock = true;
1370     _n_spinbox->setValue(257);
1371     setButtonColor(_color0_button, QColor(
1372                 ColorMap::MorelandDefaultR0,
1373                 ColorMap::MorelandDefaultG0,
1374                 ColorMap::MorelandDefaultB0));
1375     setButtonColor(_color1_button, QColor(
1376                 ColorMap::MorelandDefaultR1,
1377                 ColorMap::MorelandDefaultG1,
1378                 ColorMap::MorelandDefaultB1));
1379     _update_lock = false;
1380     update();
1381 }
1382
1383 QVector<QColor> ColorMapMorelandWidget::colorMap(int* clipped) const
1384 {
1385     int n;
1386     unsigned char r0, g0, b0, r1, g1, b1;
1387     parameters(n, r0, g0, b0, r1, g1, b1);
1388     QVector<unsigned char> colormap(3 * n);
1389     int cl = ColorMap::Moreland(n, colormap.data(), r0, g0, b0, r1, g1, b1);
1390     if (clipped)
1391         *clipped = cl;
1392     return toQColor(colormap);
1393 }
1394
1395 QString ColorMapMorelandWidget::reference() const
1396 {
1397     return moreland_reference;
1398 }
1399
1400 void ColorMapMorelandWidget::parameters(int& n,
1401         unsigned char& r0, unsigned char& g0, unsigned char& b0,
1402         unsigned char& r1, unsigned char& g1, unsigned char& b1) const
1403 {
1404     n = _n_spinbox->value();
1405     QColor c0 = getButtonColor(_color0_button);
1406     r0 = c0.red();
1407     g0 = c0.green();
1408     b0 = c0.blue();
1409     QColor c1 = getButtonColor(_color1_button);
1410     r1 = c1.red();
1411     g1 = c1.green();
1412     b1 = c1.blue();
1413 }
1414
1415 void ColorMapMorelandWidget::update()
1416 {
1417     if (!_update_lock)
1418         emit colorMapChanged();
1419 }
1420
1421 /* ColorMapMcNamesWidget */
1422
1423 ColorMapMcNamesWidget::ColorMapMcNamesWidget() :
1424     _update_lock(false)
1425 {
1426     QGridLayout *layout = new QGridLayout;
1427
1428     QLabel* n_label = new QLabel("Colors:");
1429     layout->addWidget(n_label, 1, 0);
1430     _n_spinbox = new QSpinBox();
1431     _n_spinbox->setRange(2, 1024);
1432     _n_spinbox->setSingleStep(1);
1433     layout->addWidget(_n_spinbox, 1, 1, 1, 3);
1434
1435     QLabel* periods_label = new QLabel("Periods:");
1436     layout->addWidget(periods_label, 2, 0);
1437     _periods_changer = new ColorMapCombinedSliderSpinBox(0.1f, 5.0f, 0.1f);
1438     layout->addWidget(_periods_changer->slider, 2, 1, 1, 2);
1439     layout->addWidget(_periods_changer->spinbox, 2, 3);
1440
1441     layout->setColumnStretch(1, 1);
1442     layout->addItem(new QSpacerItem(0, 0), 3, 0, 1, 4);
1443     layout->setRowStretch(3, 1);
1444     setLayout(layout);
1445
1446     connect(_n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(update()));
1447     connect(_periods_changer, SIGNAL(valueChanged(float)), this, SLOT(update()));
1448     reset();
1449 }
1450
1451 ColorMapMcNamesWidget::~ColorMapMcNamesWidget()
1452 {
1453 }
1454
1455 void ColorMapMcNamesWidget::reset()
1456 {
1457     _update_lock = true;
1458     _n_spinbox->setValue(256);
1459     _periods_changer->setValue(ColorMap::McNamesDefaultPeriods);
1460     _update_lock = false;
1461     update();
1462 }
1463
1464 QVector<QColor> ColorMapMcNamesWidget::colorMap(int* clipped) const
1465 {
1466     int n;
1467     float p;
1468     parameters(n, p);
1469     QVector<unsigned char> colormap(3 * n);
1470     int cl = ColorMap::McNames(n, colormap.data(), p);
1471     if (clipped)
1472         *clipped = cl;
1473     return toQColor(colormap);
1474 }
1475
1476 QString ColorMapMcNamesWidget::reference() const
1477 {
1478     return mcnames_references;
1479 }
1480
1481 void ColorMapMcNamesWidget::parameters(int& n, float& p) const
1482 {
1483     n = _n_spinbox->value();
1484     p = _periods_changer->value();
1485 }
1486
1487 void ColorMapMcNamesWidget::update()
1488 {
1489     if (!_update_lock)
1490         emit colorMapChanged();
1491 }